#![no_std]
use core::cmp::min;
use core::fmt;
use core::str::from_utf8;
pub struct WriteTo<'a> {
buf: &'a mut [u8],
len: usize,
}
impl<'a> WriteTo<'a> {
pub fn new(buf: &'a mut [u8]) -> Self {
WriteTo { buf, len: 0 }
}
pub fn as_str(self) -> Option<&'a str> {
if self.len <= self.buf.len() {
from_utf8(&self.buf[..self.len]).ok()
} else {
None
}
}
pub fn len(&self) -> Option<usize> {
if self.len <= self.buf.len() {
Some(self.len)
} else {
None
}
}
pub fn is_empty(&self) -> Option<bool> {
if self.len <= self.buf.len() {
Some(self.len == 0)
} else {
None
}
}
}
impl<'a> fmt::Write for WriteTo<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
if self.len > self.buf.len() {
return Err(fmt::Error);
}
let rem = &mut self.buf[self.len..];
let raw_s = s.as_bytes();
let num = min(raw_s.len(), rem.len());
rem[..num].copy_from_slice(&raw_s[..num]);
self.len += raw_s.len();
if num < raw_s.len() {
Err(fmt::Error)
} else {
Ok(())
}
}
}
pub fn show<'a>(buf: &'a mut [u8], arg: fmt::Arguments) -> Result<&'a str, fmt::Error> {
let mut w = WriteTo::new(buf);
fmt::write(&mut w, arg)?;
w.as_str().ok_or(fmt::Error)
}
#[test]
fn test() {
let mut buf = [0u8; 64];
let s = show(&mut buf, format_args!("Test String {}: {}", "foo", 42)).unwrap();
assert_eq!("Test String foo: 42", s);
}
#[test]
fn test_to_long() {
let mut buf = [0u8; 8];
let ret = show(&mut buf, format_args!("Too long string"));
assert_eq!(Err(fmt::Error), ret);
}
#[test]
fn test_len() {
use fmt::Write;
let mut buf = [0u8; 64];
let mut w = WriteTo::new(&mut buf);
write!(&mut w, "Test String {}: {}", "foo", 42).unwrap();
assert_eq!(w.len(), Some(19));
assert_eq!(w.is_empty(), Some(false));
}
#[test]
fn test_len_empty() {
use fmt::Write;
let mut buf = [0u8; 64];
let mut w = WriteTo::new(&mut buf);
write!(&mut w, "").unwrap();
assert_eq!(w.len(), Some(0));
assert_eq!(w.is_empty(), Some(true));
}
#[test]
fn test_len_to_long() {
use fmt::Write;
let mut buf = [0u8; 8];
let mut w = WriteTo::new(&mut buf);
let res = write!(&mut w, "Tooo long string");
assert_eq!(res, Err(core::fmt::Error));
assert_eq!(w.len(), None);
assert_eq!(w.is_empty(), None);
}