scolapasta_string_escape/
string.rs1use core::fmt::{self, Write};
2
3use crate::literal::{Literal, ascii_char_with_escape};
4
5pub fn format_debug_escape_into<W, T>(mut dest: W, message: T) -> fmt::Result
31where
32 W: Write,
33 T: AsRef<[u8]>,
34{
35 let mut buf = [0; 4];
36 let mut message = message.as_ref();
37 while !message.is_empty() {
38 let (ch, size) = bstr::decode_utf8(message);
39 match ch.map(|ch| ascii_char_with_escape(ch).ok_or(ch)) {
40 Some(Ok(escaped)) => {
41 dest.write_str(escaped)?;
42 }
43 Some(Err(ch)) => {
44 let enc = ch.encode_utf8(&mut buf);
45 dest.write_str(enc)?;
46 }
47 None => {
50 for &byte in &message[..size] {
51 let escaped = Literal::debug_escape(byte);
52 dest.write_str(escaped)?;
53 }
54 }
55 }
56 message = &message[size..];
57 }
58 Ok(())
59}
60
61#[cfg(test)]
62mod tests {
63 use alloc::string::{String, ToString};
64
65 use super::format_debug_escape_into;
66
67 #[test]
68 fn format_ascii_message() {
69 let message = "Spinoso Exception";
70 let mut dest = String::new();
71 format_debug_escape_into(&mut dest, message).unwrap();
72 assert_eq!(dest, "Spinoso Exception");
73 }
74
75 #[test]
76 fn format_unicode_message() {
77 let message = "Spinoso Exception 💎🦀";
78 let mut dest = String::new();
79 format_debug_escape_into(&mut dest, message).unwrap();
80 assert_eq!(dest, "Spinoso Exception 💎🦀");
81 }
82
83 #[test]
84 fn format_invalid_utf8_message() {
85 let message = b"oh no! \xFF";
86 let mut dest = String::new();
87 format_debug_escape_into(&mut dest, message).unwrap();
88 assert_eq!(dest, r"oh no! \xFF");
89 }
90
91 #[test]
92 fn format_escape_code_message() {
93 let message = "yes to symbolic \t\n\x7F";
94 let mut dest = String::new();
95 format_debug_escape_into(&mut dest, message).unwrap();
96 assert_eq!(dest, r"yes to symbolic \t\n\x7F");
97 }
98
99 #[test]
100 fn replacement_character() {
101 let message = "This is the replacement character: \u{FFFD}";
102 let mut dest = String::new();
103 format_debug_escape_into(&mut dest, message).unwrap();
104 assert_eq!(dest, "This is the replacement character: \u{FFFD}");
105 }
106
107 #[test]
108 fn as_ref() {
109 let message = b"Danger".to_vec();
110 let mut dest = String::new();
111 format_debug_escape_into(&mut dest, message).unwrap();
112 assert_eq!(dest, "Danger");
113
114 let message = "Danger".to_string();
115 let mut dest = String::new();
116 format_debug_escape_into(&mut dest, message).unwrap();
117 assert_eq!(dest, "Danger");
118 }
119}