1 use core::char;
2 use core::fmt::{self, Write as _};
3 use core::str;
4
display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result5 pub fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
6 loop {
7 match str::from_utf8(bytes) {
8 Ok(valid) => return f.write_str(valid),
9 Err(utf8_error) => {
10 let valid_up_to = utf8_error.valid_up_to();
11 let valid = unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) };
12 f.write_str(valid)?;
13 f.write_char(char::REPLACEMENT_CHARACTER)?;
14 if let Some(error_len) = utf8_error.error_len() {
15 bytes = &bytes[valid_up_to + error_len..];
16 } else {
17 return Ok(());
18 }
19 }
20 }
21 }
22 }
23
debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result24 pub fn debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
25 f.write_char('"')?;
26
27 while !bytes.is_empty() {
28 let from_utf8_result = str::from_utf8(bytes);
29 let valid = match from_utf8_result {
30 Ok(valid) => valid,
31 Err(utf8_error) => {
32 let valid_up_to = utf8_error.valid_up_to();
33 unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) }
34 }
35 };
36
37 let mut written = 0;
38 for (i, ch) in valid.char_indices() {
39 let esc = ch.escape_debug();
40 if esc.len() != 1 {
41 f.write_str(&valid[written..i])?;
42 for ch in esc {
43 f.write_char(ch)?;
44 }
45 written = i + ch.len_utf8();
46 }
47 }
48 f.write_str(&valid[written..])?;
49
50 match from_utf8_result {
51 Ok(_valid) => break,
52 Err(utf8_error) => {
53 let end_of_broken = if let Some(error_len) = utf8_error.error_len() {
54 valid.len() + error_len
55 } else {
56 bytes.len()
57 };
58 for b in &bytes[valid.len()..end_of_broken] {
59 write!(f, "\\x{:02x}", b)?;
60 }
61 bytes = &bytes[end_of_broken..];
62 }
63 }
64 }
65
66 f.write_char('"')
67 }
68