Created
January 5, 2021 01:09
-
-
Save xobs/8947b16f48bd0f8bab14b1a87420eccd to your computer and use it in GitHub Desktop.
Example implementation of a Xous server string
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[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