dialcache/protocol/
text.rs1pub fn replacement_utf8(bytes: &[u8]) -> Vec<u8> {
14 String::from_utf8_lossy(bytes).into_owned().into_bytes()
15}
16
17#[cfg(test)]
18mod tests {
19 use super::replacement_utf8;
20
21 fn decoded(bytes: &[u8]) -> String {
22 String::from_utf8(replacement_utf8(bytes)).expect("replacement output is UTF-8")
23 }
24
25 #[test]
26 fn protocol_replacement_table() {
27 assert_eq!(decoded(&[0x22, 0xFF, 0x22]), "\"\u{FFFD}\"");
29 assert_eq!(decoded(&[0xE2, 0x82]), "\u{FFFD}");
30 assert_eq!(decoded(&[0xE2, 0x82, 0x41]), "\u{FFFD}A");
31 assert_eq!(decoded(&[0xED, 0xA0, 0x80]), "\u{FFFD}\u{FFFD}\u{FFFD}");
32 assert_eq!(
33 decoded(&[0xF4, 0x90, 0x80, 0x80]),
34 "\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}"
35 );
36 assert_eq!(decoded(&[0xEF, 0xBB, 0xBF, 0x61]), "\u{FEFF}a");
37 }
38
39 #[test]
40 fn well_formed_input_is_unchanged() {
41 let text = "\u{80}\u{7FF}\u{800}\u{D7FF}\u{E000}\u{FFFF}\u{10000}\u{10FFFF}\0";
42 assert_eq!(replacement_utf8(text.as_bytes()), text.as_bytes());
43 assert!(replacement_utf8(b"").is_empty());
44 }
45
46 #[test]
47 fn isolated_continuations_and_overlong_forms_replace_separately() {
48 assert_eq!(decoded(&[0x80, 0xBF]), "\u{FFFD}\u{FFFD}");
49 assert_eq!(
50 decoded(&[0xC0, 0xAF, 0xE0, 0x80, 0x80]),
51 "\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}"
52 );
53 assert_eq!(decoded(&[0xF0, 0x9F, 0x98]), "\u{FFFD}");
55 assert_eq!(
57 decoded(&[0xF0, 0x8F, 0x80, 0x80]),
58 "\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}"
59 );
60 assert_eq!(decoded(&[0xE2, 0x82, 0xC3, 0xA9]), "\u{FFFD}\u{E9}");
62 assert_eq!(
64 decoded(&[0xF5, 0x80, 0xFE, 0xFF, 0x41]),
65 "\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}A"
66 );
67 }
68}