pub fn fmt_option<T>(x: &Option<T>) -> FmtOption<'_, T>
where
T: std::fmt::Display,
{
FmtOption(x)
}
#[derive(Debug)]
pub struct FmtOption<'a, T>(&'a Option<T>);
impl<T> std::fmt::Display for FmtOption<'_, T>
where
T: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(x) = self.0 {
x.fmt(f)
} else {
write!(f, "<None>")
}
}
}
pub fn fmt_maybe_string(buf: &[u8]) -> FmtMaybeString {
FmtMaybeString(buf)
}
#[derive(Debug)]
pub struct FmtMaybeString<'a>(&'a [u8]);
impl FmtMaybeString<'_> {
fn fmt_str(s: &str, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "\"")?;
for ch in s.chars() {
let code = u32::from(ch);
match code {
0x00..=0x1F | 0x7F => write!(f, "\\x{code:02X}")?,
_ => write!(f, "{ch}")?,
}
}
write!(f, "\"")?;
Ok(())
}
fn fmt_bytes(buf: &[u8], f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "\"")?;
for &b in buf {
write!(f, "\\x{b:02X}")?;
}
write!(f, "\"")?;
Ok(())
}
}
impl std::fmt::Display for FmtMaybeString<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Ok(s) = std::str::from_utf8(self.0) {
Self::fmt_str(s, f)
} else {
Self::fmt_bytes(self.0, f)
}
}
}