cxx/
lossy.rs

1use core::char;
2use core::fmt::{self, Write as _};
3use core::str;
4
5pub(crate) 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
24pub(crate) 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 && ch != '\'' {
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}