1/*!
2Provides convenience routines for escaping raw bytes.
34This was copied from `regex-automata` with a few light edits.
5*/
67use super::utf8;
89/// Provides a convenient `Debug` implementation for a `u8`.
10///
11/// The `Debug` impl treats the byte as an ASCII, and emits a human
12/// readable representation of it. If the byte isn't ASCII, then it's
13/// emitted as a hex escape sequence.
14#[derive(Clone, Copy)]
15pub(crate) struct Byte(pub u8);
1617impl core::fmt::Display for Byte {
18fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
19if self.0 == b' ' {
20return write!(f, " ");
21 }
22// 10 bytes is enough for any output from ascii::escape_default.
23let mut bytes = [0u8; 10];
24let mut len = 0;
25for (i, mut b) in core::ascii::escape_default(self.0).enumerate() {
26// capitalize \xab to \xAB
27if i >= 2 && b'a' <= b && b <= b'f' {
28 b -= 32;
29 }
30 bytes[len] = b;
31 len += 1;
32 }
33write!(f, "{}", core::str::from_utf8(&bytes[..len]).unwrap())
34 }
35}
3637impl core::fmt::Debug for Byte {
38fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
39write!(f, "\"")?;
40 core::fmt::Display::fmt(self, f)?;
41write!(f, "\"")?;
42Ok(())
43 }
44}
4546/// Provides a convenient `Debug` implementation for `&[u8]`.
47///
48/// This generally works best when the bytes are presumed to be mostly
49/// UTF-8, but will work for anything. For any bytes that aren't UTF-8,
50/// they are emitted as hex escape sequences.
51#[derive(Clone, Copy)]
52pub(crate) struct Bytes<'a>(pub &'a [u8]);
5354impl<'a> core::fmt::Display for Bytes<'a> {
55fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
56// This is a sad re-implementation of a similar impl found in bstr.
57let mut bytes = self.0;
58while let Some(result) = utf8::decode(bytes) {
59let ch = match result {
60Ok(ch) => ch,
61Err(byte) => {
62write!(f, r"\x{:02x}", byte)?;
63 bytes = &bytes[1..];
64continue;
65 }
66 };
67 bytes = &bytes[ch.len_utf8()..];
68match ch {
69'\0' => write!(f, "\\0")?,
70'\x01'..='\x7f' => {
71write!(f, "{}", (ch as u8).escape_ascii())?;
72 }
73_ => write!(f, "{}", ch.escape_debug())?,
74 }
75 }
76Ok(())
77 }
78}
7980impl<'a> core::fmt::Debug for Bytes<'a> {
81fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
82write!(f, "\"")?;
83 core::fmt::Display::fmt(self, f)?;
84write!(f, "\"")?;
85Ok(())
86 }
87}