lightning_types/
string.rs1use alloc::string::String;
13use core::fmt;
14
15use crate::unicode::*;
16
17#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
19pub struct UntrustedString(pub String);
20
21impl fmt::Display for UntrustedString {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 PrintableString(&self.0).fmt(f)
24 }
25}
26
27#[derive(Debug, PartialEq)]
30pub struct PrintableString<'a>(pub &'a str);
31
32impl<'a> fmt::Display for PrintableString<'a> {
33 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
34 use core::fmt::Write;
35 for c in self.0.chars() {
36 let is_other = is_unicode_general_category_other(c);
37 let is_unassigned = is_unicode_general_category_unassigned(c);
38 let c = if c.is_control() || is_other || is_unassigned {
39 core::char::REPLACEMENT_CHARACTER
40 } else {
41 c
42 };
43 f.write_char(c)?;
44 }
45
46 Ok(())
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::PrintableString;
53
54 #[test]
55 fn displays_printable_string() {
56 assert_eq!(
57 format!("{}", PrintableString("I \u{1F496} LDK!\t\u{26A1}")),
58 "I \u{1F496} LDK!\u{FFFD}\u{26A1}",
59 );
60 }
61
62 #[test]
63 fn sanitizes_unicode_bidi_override_characters() {
64 let rendered = format!("{}", PrintableString("safe\u{202E}cipsxe.exe"));
71 assert!(
72 !rendered.contains('\u{202E}'),
73 "PrintableString left a U+202E RLO override in its output: {:?}",
74 rendered
75 );
76
77 assert_eq!(format!("{}", PrintableString("x\u{1343F}y\u{13440}z")), "x\u{FFFD}y\u{13440}z");
80 }
81}