From d6d0122cd754ccd17da80584cf89dc6d201cdf4e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 17 Dec 2021 13:19:42 -0500 Subject: [PATCH] Add `encode_to` API In https://github.com/ostreedev/ostree-rs-ext/ we are performing hex encoding in loops and recursively, and it could be helpful for performance to support re-using a buffer instead of allocating a new `String` on the heap. Currently we are using `encode_to_slice`, but then we need to use e.g. `std::str::from_utf8` which unnecessarily performs UTF-8 validation and is also hence fallible even though it doesn't need to be. --- src/lib.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index bc6a69d..70bb4fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -260,6 +260,30 @@ pub fn encode>(data: T) -> String { data.encode_hex() } +/// Encodes `data` as hex string using lowercase characters, appending to target string. +/// +/// This is otherwise the same as [`encode`]. One reason to use this function +/// is that if you are performing multiple encodings on distinct data in +/// a loop, this will allow reusing the allocation of a string. +/// +/// Alternatively, this is also more efficient to use when you have an +/// existing string and just want to append to it. +/// +/// # Example +/// +/// ``` +/// let mut s = "The hex encoding is: ".to_string(); +/// hex::encode_to("Hello world!", &mut s); +/// assert_eq!(s, "The hex encoding is: 48656c6c6f20776f726c6421"); +/// ``` +#[cfg(feature = "alloc")] +pub fn encode_to>(data: T, s: &mut String) { + let data = data.as_ref(); + for c in BytesToHexChars::new(data, HEX_CHARS_LOWER) { + s.push(c); + } +} + /// Encodes `data` as hex string using uppercase characters. /// /// Apart from the characters' casing, this works exactly like `encode()`. @@ -276,6 +300,25 @@ pub fn encode_upper>(data: T) -> String { data.encode_hex_upper() } +/// Encodes `data` as hex string using uppercase characters, appending to target string. +/// +/// This is the same as [`encode_to`], but uses uppercase characters. +/// +/// # Example +/// +/// ``` +/// let mut s = "The hex encoding is: ".to_string(); +/// hex::encode_upper_to("Hello world!", &mut s); +/// assert_eq!(s, "The hex encoding is: 48656C6C6F20776F726C6421"); +/// ``` +#[cfg(feature = "alloc")] +pub fn encode_upper_to>(data: T, s: &mut String) { + let data = data.as_ref(); + for c in BytesToHexChars::new(data, HEX_CHARS_UPPER) { + s.push(c); + } +} + /// Decodes a hex string into raw bytes. /// /// Both, upper and lower case characters are valid in the input string and can