From: Matt Corallo Date: Fri, 9 Aug 2024 01:26:21 +0000 (+0000) Subject: Move `UntrustedString` and `PrintableString` to `lightning-types` X-Git-Tag: v0.0.124-beta~14^2~6 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=3b3774ee693c417b5131f79b0c34cca798b4774a;p=rust-lightning Move `UntrustedString` and `PrintableString` to `lightning-types` `lightning-invoice` currently has a dependency on the entire `lightning` crate just because it wants to use some of the useful types from it. This is obviously backwards and leads to some awkwardness like the BOLT 11 invoice signing API in the `lightning` crate taking a `[u5]` rather than a `Bolt11Invoice`. This takes one more step, moving the `UntrustedString` and `PrintableString` types to `lightning-types`. --- diff --git a/lightning-types/src/lib.rs b/lightning-types/src/lib.rs index bcfb2b62d..1539401d3 100644 --- a/lightning-types/src/lib.rs +++ b/lightning-types/src/lib.rs @@ -26,3 +26,4 @@ extern crate core; pub mod features; pub mod payment; pub mod routing; +pub mod string; diff --git a/lightning-types/src/string.rs b/lightning-types/src/string.rs new file mode 100644 index 000000000..ae5395a52 --- /dev/null +++ b/lightning-types/src/string.rs @@ -0,0 +1,53 @@ +// 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 alloc::string::String; +use core::fmt; + +/// Struct to `Display` fields in a safe way using `PrintableString` +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] +pub struct UntrustedString(pub String); + +impl fmt::Display for UntrustedString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + PrintableString(&self.0).fmt(f) + } +} + +/// A string that displays only printable characters, replacing control characters with +/// [`core::char::REPLACEMENT_CHARACTER`]. +#[derive(Debug, PartialEq)] +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}", + ); + } +} diff --git a/lightning/src/util/mod.rs b/lightning/src/util/mod.rs index a81a36c55..cfcea8379 100644 --- a/lightning/src/util/mod.rs +++ b/lightning/src/util/mod.rs @@ -21,7 +21,6 @@ pub mod message_signing; pub mod invoice; pub mod persist; pub mod scid_utils; -pub mod string; pub mod sweep; pub mod wakers; #[cfg(fuzzing)] @@ -54,3 +53,7 @@ pub mod test_utils; #[cfg(any(test, feature = "_test_utils"))] pub mod test_channel_signer; +pub mod string { + //! Utilities to wrap untrusted strings and handle them (more) safely + pub use lightning_types::string::{PrintableString, UntrustedString}; +} diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 3d3d97252..29c52f6a0 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -627,6 +627,18 @@ impl<'a> From<&'a String> for WithoutLength<&'a String> { fn from(s: &'a String) -> Self { Self(s) } } +impl Writeable for UntrustedString { + fn write(&self, w: &mut W) -> Result<(), io::Error> { + self.0.write(w) + } +} + +impl Readable for UntrustedString { + fn read(r: &mut R) -> Result { + let s: String = Readable::read(r)?; + Ok(Self(s)) + } +} impl Writeable for WithoutLength<&UntrustedString> { #[inline] diff --git a/lightning/src/util/string.rs b/lightning/src/util/string.rs deleted file mode 100644 index ab12486a0..000000000 --- a/lightning/src/util/string.rs +++ /dev/null @@ -1,71 +0,0 @@ -// 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; -use crate::io::{self, Read}; -use crate::ln::msgs; -use crate::util::ser::{Writeable, Writer, Readable}; - -#[allow(unused_imports)] -use crate::prelude::*; - -/// Struct to `Display` fields in a safe way using `PrintableString` -#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] -pub struct UntrustedString(pub String); - -impl Writeable for UntrustedString { - fn write(&self, w: &mut W) -> Result<(), io::Error> { - self.0.write(w) - } -} - -impl Readable for UntrustedString { - fn read(r: &mut R) -> Result { - let s: String = Readable::read(r)?; - Ok(Self(s)) - } -} - -impl fmt::Display for UntrustedString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - PrintableString(&self.0).fmt(f) - } -} - -/// A string that displays only printable characters, replacing control characters with -/// [`core::char::REPLACEMENT_CHARACTER`]. -#[derive(Debug, PartialEq)] -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}", - ); - } -}