#![doc = include_str!("../README.md")]
#![no_std]
pub struct MaybeAscii<'a> {
pub bytes: &'a [u8],
}
impl<'a> core::fmt::Debug for MaybeAscii<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
let mut start = 0;
while start < self.bytes.len() {
let is_ascii = self.bytes[start] < 128;
let mut end = start + 1;
loop {
if end >= self.bytes.len() {
break;
}
if (self.bytes[end] < 128) != is_ascii {
break;
}
end += 1;
}
if is_ascii {
let s = core::str::from_utf8(&self.bytes[start..end]).expect("The slice should only contain ascii characters (<128) which should be convertible to a utf8 string.");
f.write_str(s)?;
} else {
self.bytes[start..end].fmt(f)?;
}
start = end;
}
Ok(())
}
}
pub fn try_ascii(bytes: &[u8]) -> MaybeAscii<'_> {
MaybeAscii { bytes }
}
pub trait TryAscii {
fn try_ascii(&self) -> MaybeAscii<'_>;
}
impl TryAscii for [u8] {
fn try_ascii(&self) -> MaybeAscii<'_> {
try_ascii(self)
}
}
impl TryAscii for &[u8] {
fn try_ascii(&self) -> MaybeAscii<'_> {
try_ascii(self)
}
}
impl TryAscii for dyn AsRef<[u8]> {
fn try_ascii(&self) -> MaybeAscii<'_> {
try_ascii(self.as_ref())
}
}
#[cfg(test)]
mod tests {
extern crate std;
use crate::try_ascii;
use crate::TryAscii;
use std::*;
#[test]
fn format_ascii() {
let res = format!("{:?}", try_ascii(b"Hello, World"));
assert_eq!(res, "Hello, World");
}
#[test]
fn format_non_ascii() {
let res = format!("{:?}", try_ascii(b"Hello, \xa0"));
assert_eq!(res, "Hello, [160]");
}
#[test]
fn format_slice() {
let res = format!("{:?}", try_ascii(b"Hello, \xa0\xa1\xa2\xa3"));
assert_eq!(res, "Hello, [160, 161, 162, 163]");
}
#[test]
fn format_hex() {
let res = format!("{:x?}", try_ascii(b"Hello, \xa0\xa1\xa2\xa3"));
assert_eq!(res, "Hello, [a0, a1, a2, a3]");
}
#[test]
fn format_pretty() {
let res = format!("{:#X?}", try_ascii(&[0xa0, 0xa1]));
assert_eq!(res, "[\n 0xA0,\n 0xA1,\n]");
}
#[test]
fn format_empty() {
let res = format!("{:?}", try_ascii(&[]));
assert_eq!(res, "");
}
#[test]
fn trait_for_u8() {
let res = format!("{:x?}", b"Hello, \xa0\xa1\xa2\xa3".try_ascii());
assert_eq!(res, "Hello, [a0, a1, a2, a3]");
}
#[test]
fn trait_for_ref_u8() {
let arr: &[u8] = b"Hello, \xa0\xa1\xa2\xa3";
let res = format!("{:x?}", arr.try_ascii());
assert_eq!(res, "Hello, [a0, a1, a2, a3]");
}
#[test]
fn trait_for_as_ref_u8() {
let arr: [u8; 11] = *b"Hello, \xa0\xa1\xa2\xa3";
let res = format!("{:x?}", arr.as_ref().try_ascii());
assert_eq!(res, "Hello, [a0, a1, a2, a3]");
}
}