Skip to content

Instantly share code, notes, and snippets.

@xobs
Created January 5, 2021 01:09
Show Gist options
  • Save xobs/8947b16f48bd0f8bab14b1a87420eccd to your computer and use it in GitHub Desktop.
Save xobs/8947b16f48bd0f8bab14b1a87420eccd to your computer and use it in GitHub Desktop.
Example implementation of a Xous server string
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct XousServerName {
pub name: [u8; 32],
pub length: usize,
}
impl XousServerName {
pub fn new() -> Self {
Default::default()
}
pub fn to_str(&self) -> &str {
core::str::from_utf8(unsafe {
core::slice::from_raw_parts(self.name.as_ptr(), self.length)
})
.unwrap()
}
}
impl Default for XousServerName {
fn default() -> Self {
XousServerName {
name: [0; 32],
length: 0,
}
}
}
impl PartialEq for XousServerName {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for XousServerName {}
// Allow using the `write!()` macro to write into a `&XousServerName`
impl core::fmt::Write for XousServerName {
fn write_str(&mut self, s: &str) -> core::result::Result<(), core::fmt::Error> {
self.length = 0;
let b = s.bytes();
// Ensure the length is acceptable
if b.len() > self.name.len() {
Err(core::fmt::Error)?;
}
self.length = b.len();
// Copy the string into this variable
for (dest, src) in self.name.iter_mut().zip(s.bytes()) {
*dest = src;
}
// Attempt to convert the string to UTF-8 to validate it's correct UTF-8
core::str::from_utf8(unsafe {
core::slice::from_raw_parts(self.name.as_ptr(), self.length)
})
.map_err(|_| core::fmt::Error)?;
Ok(())
}
}
// Allow a `&XousServerName` to be printed out
impl core::fmt::Display for XousServerName {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.to_str())
}
}
// Allow a `&XousServerName` to be used anywhere that expects a `&str`
impl AsRef<str> for XousServerName {
fn as_ref(&self) -> &str {
self.to_str()
}
}
use core::fmt::Write;
fn main() {
let mut s = XousServerName::new();
write!(&mut s, "Hi there, 2+3 = {} (πŸ₯ž)", 2 + 3).unwrap();
println!("Hello, world! String is: {}", s);
// This is fine because the grapheme is large, but still within the limit
if let Err(_) = write!(&mut s, "πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§") {
println!("Unable to write emoji -- resulted in invalid UTF-8");
} else {
println!("String is now: {}", s);
}
// This overflows the string
if let Err(_) = write!(&mut s, "πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§") {
println!("Unable to write emoji -- resulted in invalid UTF-8");
} else {
println!("String is now: {}", s);
}
// The pancake ruins everything because it causes the UTF-8 to not
// line up to a word boundary:
// Utf8Error { valid_up_to: 29, error_len: None }
if let Err(_) = write!(&mut s, "πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§πŸ₯žπŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§") {
println!("Unable to write emoji -- resulted in invalid UTF-8");
} else {
println!("String is now: {}", s);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment