xo65 0.1.0

Library for parsing cc65 object files (xo65 format)
Documentation
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)
        }
    }
}