// A `fmt` body may write repeatedly, so a formatter write appends rather than // assigns. `UpperHex` here writes once per element. use core::fmt; struct Bytes<'a>(&'a [u8]); impl fmt::UpperHex for Bytes<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for &b in self.0 { write!(f, "{:02X}", b)?; } Ok(()) } } impl fmt::LowerHex for Bytes<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for &b in self.0 { write!(f, "{:02x}", b)?; } Ok(()) } } impl fmt::Display for Bytes<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("<")?; write!(f, "{self:x}")?; f.write_str(">") } } fn main() { let raw: Vec = vec![0xab, 0xcd, 0x01, 0x00]; println!("{:X}", Bytes(&raw)); println!("{:x}", Bytes(&raw)); println!("{}", Bytes(&raw)); println!("[{}]", Bytes(&[])); // `debug_assert*` fires in debug builds, which is the profile modelled. assert!(raw.len() == 4); assert_eq!(raw.len(), 4); assert_ne!(raw.len(), 5); debug_assert_eq!(raw[0], 0xab); println!("asserts passed"); }