< Return to Blog

Journey into no_std: Padding u8 values using 2-bytes

Let's look at some code first
impl fmt::Write for ByteMutWriter<'_> { fn write_str(&mut self, s: &str) -> fmt::Result { let cap = self.capacity(); for (i, &b) in self.buf[self.cursor..cap] .iter_mut() .zip(s.as_bytes().iter()) { *i = b; } self.cursor = usize::min(cap, self.cursor + s.as_bytes().len()); Ok(()) } }
This the meat and potatoes, although I haven't had time to optimise this for performance by any means. Astute readers are welcome to comment and share any improvements this can use.
We can also write this in a functional style. A mutable iterator is created into the shared slice buf and then ziped with an iterator of the bytes of the provided &str.  This is then completed with for_each which uses a closure to access the results of zip, which are bytes of buf as i and the bytes of the provided &str as &b.
self.buf[self.cursor..cap] .iter_mut() .zip(s.as_bytes().iter()) .for_each(|(i, &b)| { *i = b; });
To use this on multiple values, we need to initialise 2-bytes for each value that needs to be padded. In this particular example, I'm dealing with values <= 99. If you need to handle the largest value of a u8 (255), then this will only need 3-bytes.
fn main() { let h = 09u8; let m = 10u8; fn left_pad<'a>(buf: &'a mut crate::formatter::ByteMutWriter<'_>, value: u8) -> &'a str { buf.clear(); write!(buf, "{}{}", if value < 10 { "0" } else { "" }, value).unwrap(); buf.as_str() } let mut buf = [0u8; 2]; let mut buf = ByteMutWriter::new(&mut buf[..]); let hours = left_pad(&mut buf, h); let mut buf = [0u8; 2]; let mut buf = ByteMutWriter::new(&mut buf[..]); let seconds = left_pad(&mut buf, m); println!("hours: {} / seconds: {}", hours, seconds); }