From: Jeffrey Czyz Date: Thu, 6 Oct 2022 18:44:35 +0000 (-0500) Subject: Add PrintableString utility X-Git-Tag: v0.0.113~52^2~4 X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=48bb9edba1cd4f6c876bb35f82b374f20502abfb;p=rust-lightning Add PrintableString utility Strings defined by third parties may contain control characters. Provide a wrapper such that these are replaced when displayed. Useful in node aliases and offer fields. --- diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index 6b0f88d09..00846a7ba 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -31,6 +31,7 @@ use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, MaybeReadable} use crate::util::logger::{Logger, Level}; use crate::util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider}; use crate::util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK}; +use crate::util::string::PrintableString; use crate::io; use crate::io_extras::{copy, sink}; @@ -1022,23 +1023,17 @@ pub struct NodeAlias(pub [u8; 32]); impl fmt::Display for NodeAlias { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let control_symbol = core::char::REPLACEMENT_CHARACTER; let first_null = self.0.iter().position(|b| *b == 0).unwrap_or(self.0.len()); let bytes = self.0.split_at(first_null).0; match core::str::from_utf8(bytes) { - Ok(alias) => { - for c in alias.chars() { - let mut bytes = [0u8; 4]; - let c = if !c.is_control() { c } else { control_symbol }; - f.write_str(c.encode_utf8(&mut bytes))?; - } - }, + Ok(alias) => PrintableString(alias).fmt(f)?, Err(_) => { + use core::fmt::Write; for c in bytes.iter().map(|b| *b as char) { // Display printable ASCII characters - let mut bytes = [0u8; 4]; + let control_symbol = core::char::REPLACEMENT_CHARACTER; let c = if c >= '\x20' && c <= '\x7e' { c } else { control_symbol }; - f.write_str(c.encode_utf8(&mut bytes))?; + f.write_char(c)?; } }, }; diff --git a/lightning/src/util/mod.rs b/lightning/src/util/mod.rs index 9ffe1b749..730131f22 100644 --- a/lightning/src/util/mod.rs +++ b/lightning/src/util/mod.rs @@ -21,6 +21,7 @@ pub mod ser; pub mod message_signing; pub mod invoice; pub mod persist; +pub mod string; pub mod wakers; pub(crate) mod atomic_counter; diff --git a/lightning/src/util/string.rs b/lightning/src/util/string.rs new file mode 100644 index 000000000..1af04e085 --- /dev/null +++ b/lightning/src/util/string.rs @@ -0,0 +1,41 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Utilities for strings. + +use core::fmt; + +/// A string that displays only printable characters, replacing control characters with +/// [`core::char::REPLACEMENT_CHARACTER`]. +pub struct PrintableString<'a>(pub &'a str); + +impl<'a> fmt::Display for PrintableString<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + use core::fmt::Write; + for c in self.0.chars() { + let c = if c.is_control() { core::char::REPLACEMENT_CHARACTER } else { c }; + f.write_char(c)?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::PrintableString; + + #[test] + fn displays_printable_string() { + assert_eq!( + format!("{}", PrintableString("I \u{1F496} LDK!\t\u{26A1}")), + "I \u{1F496} LDK!\u{FFFD}\u{26A1}", + ); + } +}