diff options
Diffstat (limited to 'vendor/cxx/src/lossy.rs')
-rw-r--r-- | vendor/cxx/src/lossy.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/vendor/cxx/src/lossy.rs b/vendor/cxx/src/lossy.rs new file mode 100644 index 000000000..8ccf0f93b --- /dev/null +++ b/vendor/cxx/src/lossy.rs @@ -0,0 +1,67 @@ +use core::char; +use core::fmt::{self, Write as _}; +use core::str; + +pub fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { + loop { + match str::from_utf8(bytes) { + Ok(valid) => return f.write_str(valid), + Err(utf8_error) => { + let valid_up_to = utf8_error.valid_up_to(); + let valid = unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) }; + f.write_str(valid)?; + f.write_char(char::REPLACEMENT_CHARACTER)?; + if let Some(error_len) = utf8_error.error_len() { + bytes = &bytes[valid_up_to + error_len..]; + } else { + return Ok(()); + } + } + } + } +} + +pub fn debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { + f.write_char('"')?; + + while !bytes.is_empty() { + let from_utf8_result = str::from_utf8(bytes); + let valid = match from_utf8_result { + Ok(valid) => valid, + Err(utf8_error) => { + let valid_up_to = utf8_error.valid_up_to(); + unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) } + } + }; + + let mut written = 0; + for (i, ch) in valid.char_indices() { + let esc = ch.escape_debug(); + if esc.len() != 1 && ch != '\'' { + f.write_str(&valid[written..i])?; + for ch in esc { + f.write_char(ch)?; + } + written = i + ch.len_utf8(); + } + } + f.write_str(&valid[written..])?; + + match from_utf8_result { + Ok(_valid) => break, + Err(utf8_error) => { + let end_of_broken = if let Some(error_len) = utf8_error.error_len() { + valid.len() + error_len + } else { + bytes.len() + }; + for b in &bytes[valid.len()..end_of_broken] { + write!(f, "\\x{:02x}", b)?; + } + bytes = &bytes[end_of_broken..]; + } + } + } + + f.write_char('"') +} |