diff --git a/internals/src/hex/buf_encoder.rs b/internals/src/hex/buf_encoder.rs deleted file mode 100644 index 2d6793d980..0000000000 --- a/internals/src/hex/buf_encoder.rs +++ /dev/null @@ -1,396 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -//! Implements a buffered encoder. -//! -//! The main type of this module is [`BufEncoder`] which provides buffered hex encoding. Such is -//! faster than the usual `write!(f, "{02x}", b)?` in a for loop because it reduces dynamic -//! dispatch and decreases the number of allocations if a `String` is being created. - -use core::borrow::Borrow; - -pub use out_bytes::OutBytes; - -use super::Case; - -/// Trait for types that can be soundly converted to `OutBytes`. -/// -/// To protect the API from future breakage this sealed trait guards which types can be used with -/// the `Encoder`. Currently it is implemented for byte arrays of various interesting lengths. -/// -/// ## Safety -/// -/// This is not `unsafe` yet but the `as_out_bytes` should always return the same reference if the -/// same reference is supplied. IOW the returned memory address and length should be the same if -/// the input memory address and length are the same. -/// -/// If the trait ever becomes `unsafe` this will be required for soundness. -pub trait AsOutBytes: out_bytes::Sealed { - /// Performs the conversion. - fn as_out_bytes(&self) -> &OutBytes; - - /// Performs the conversion. - fn as_mut_out_bytes(&mut self) -> &mut OutBytes; -} - -/// A buffer with compile-time-known length. -/// -/// This is essentially `Default + AsOutBytes` but supports lengths 1.41 doesn't. -pub trait FixedLenBuf: Sized + AsOutBytes { - /// Creates an uninitialized buffer. - /// - /// The current implementtions initialize the buffer with zeroes but it should be treated a - /// uninitialized anyway. - fn uninit() -> Self; -} - -/// Implements `OutBytes` -/// -/// This prevents the rest of the crate from accessing the field of `OutBytes`. -mod out_bytes { - use super::AsOutBytes; - - /// A byte buffer that can only be written-into. - /// - /// You shouldn't concern yourself with this, just call `BufEncoder::new` with your array. - /// - /// This prepares the API for potential future support of `[MaybeUninit]`. We don't want to use - /// `unsafe` until it's proven to be needed but if it does we have an easy, compatible upgrade - /// option. - /// - /// Warning: `repr(transparent)` is an internal implementation detail and **must not** be - /// relied on! - #[repr(transparent)] - pub struct OutBytes([u8]); - - impl OutBytes { - /// Returns the first `len` bytes as initialized. - /// - /// Not `unsafe` because we don't use `unsafe` (yet). - /// - /// ## Panics - /// - /// The method panics if `len` is out of bounds. - #[track_caller] - pub(crate) fn assume_init(&self, len: usize) -> &[u8] { &self.0[..len] } - - /// Writes given bytes into the buffer. - /// - /// ## Panics - /// - /// The method panics if pos is out of bounds or `bytes` don't fit into the buffer. - #[track_caller] - pub(crate) fn write(&mut self, pos: usize, bytes: &[u8]) { - self.0[pos..(pos + bytes.len())].copy_from_slice(bytes); - } - - /// Returns the length of the buffer. - pub(crate) fn len(&self) -> usize { self.0.len() } - - fn from_bytes(slice: &[u8]) -> &Self { - // SAFETY: copied from std - // conversion of reference to pointer of the same referred type is always sound, - // including in unsized types. - // Thanks to repr(transparent) the types have the same layout making the other - // conversion sound. - // The pointer was just created from a reference that's still alive so dereferencing is - // sound. - unsafe { &*(slice as *const [u8] as *const Self) } - } - - fn from_mut_bytes(slice: &mut [u8]) -> &mut Self { - // SAFETY: copied from std - // conversion of reference to pointer of the same referred type is always sound, - // including in unsized types. - // Thanks to repr(transparent) the types have the same layout making the other - // conversion sound. - // The pointer was just created from a reference that's still alive so dereferencing is - // sound. - unsafe { &mut *(slice as *mut [u8] as *mut Self) } - } - } - - macro_rules! impl_from_array { - ($($len:expr),* $(,)?) => { - $( - impl super::FixedLenBuf for [u8; $len] { - fn uninit() -> Self { - [0u8; $len] - } - } - - impl AsOutBytes for [u8; $len] { - fn as_out_bytes(&self) -> &OutBytes { - OutBytes::from_bytes(self) - } - - fn as_mut_out_bytes(&mut self) -> &mut OutBytes { - OutBytes::from_mut_bytes(self) - } - } - - impl Sealed for [u8; $len] {} - - impl<'a> super::super::display::DisplayHex for &'a [u8; $len / 2] { - type Display = super::super::display::DisplayArray, [u8; $len]>; - fn as_hex(self) -> Self::Display { - super::super::display::DisplayArray::new(self.iter()) - } - - fn hex_reserve_suggestion(self) -> usize { - $len - } - } - )* - } - } - - impl AsOutBytes for &'_ mut T { - fn as_out_bytes(&self) -> &OutBytes { (**self).as_out_bytes() } - - fn as_mut_out_bytes(&mut self) -> &mut OutBytes { (**self).as_mut_out_bytes() } - } - - impl Sealed for &'_ mut T {} - - impl AsOutBytes for OutBytes { - fn as_out_bytes(&self) -> &OutBytes { self } - - fn as_mut_out_bytes(&mut self) -> &mut OutBytes { self } - } - - impl Sealed for OutBytes {} - - // As a sanity check we only provide conversions for even, non-empty arrays. - // Weird lengths 66 and 130 are provided for serialized public keys. - impl_from_array!( - 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 40, 64, 66, 128, 130, 256, 512, - 1024, 2048, 4096, 8192 - ); - - /// Prevents outside crates from implementing the trait - pub trait Sealed {} -} - -/// Hex-encodes bytes into the provided buffer. -/// -/// This is an important building block for fast hex-encoding. Because string writing tools -/// provided by `core::fmt` involve dynamic dispatch and don't allow reserving capacity in strings -/// buffering the hex and then formatting it is significantly faster. -pub struct BufEncoder { - buf: T, - pos: usize, -} - -impl BufEncoder { - /// Creates an empty `BufEncoder`. - /// - /// This is usually used with uninitialized (zeroed) byte array allocated on stack. - /// This can only be constructed with an even-length, non-empty array. - #[inline] - pub fn new(buf: T) -> Self { BufEncoder { buf, pos: 0 } } - - /// Encodes `byte` as hex in given `case` and appends it to the buffer. - /// - /// ## Panics - /// - /// The method panics if the buffer is full. - #[inline] - #[track_caller] - pub fn put_byte(&mut self, byte: u8, case: Case) { - self.buf.as_mut_out_bytes().write(self.pos, &super::byte_to_hex(byte, case.table())); - self.pos += 2; - } - - /// Encodes `bytes` as hex in given `case` and appends them to the buffer. - /// - /// ## Panics - /// - /// The method panics if the bytes wouldn't fit the buffer. - #[inline] - #[track_caller] - pub fn put_bytes(&mut self, bytes: I, case: Case) - where - I: IntoIterator, - I::Item: Borrow, - { - self.put_bytes_inner(bytes.into_iter(), case) - } - - #[inline] - #[track_caller] - fn put_bytes_inner(&mut self, bytes: I, case: Case) - where - I: Iterator, - I::Item: Borrow, - { - // May give the compiler better optimization opportunity - if let Some(max) = bytes.size_hint().1 { - assert!(max <= self.space_remaining()); - } - for byte in bytes { - self.put_byte(*byte.borrow(), case); - } - } - - /// Encodes as many `bytes` as fit into the buffer as hex and return the remainder. - /// - /// This method works just like `put_bytes` but instead of panicking it returns the unwritten - /// bytes. The method returns an empty slice if all bytes were written - #[must_use = "this may write only part of the input buffer"] - #[inline] - #[track_caller] - pub fn put_bytes_min<'a>(&mut self, bytes: &'a [u8], case: Case) -> &'a [u8] { - let to_write = self.space_remaining().min(bytes.len()); - self.put_bytes(&bytes[..to_write], case); - &bytes[to_write..] - } - - /// Returns true if no more bytes can be written into the buffer. - #[inline] - pub fn is_full(&self) -> bool { self.pos == self.buf.as_out_bytes().len() } - - /// Returns the written bytes as a hex `str`. - #[inline] - pub fn as_str(&self) -> &str { - core::str::from_utf8(self.buf.as_out_bytes().assume_init(self.pos)) - .expect("we only write ASCII") - } - - /// Resets the buffer to become empty. - #[inline] - pub fn clear(&mut self) { self.pos = 0; } - - /// How many bytes can be written to this buffer. - /// - /// Note that this returns the number of bytes before encoding, not number of hex digits. - #[inline] - pub fn space_remaining(&self) -> usize { (self.buf.as_out_bytes().len() - self.pos) / 2 } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn empty() { - let mut buf = [0u8; 2]; - let encoder = BufEncoder::new(&mut buf); - assert_eq!(encoder.as_str(), ""); - assert!(!encoder.is_full()); - } - - #[test] - fn single_byte_exact_buf() { - let mut buf = [0u8; 2]; - let mut encoder = BufEncoder::new(&mut buf); - assert_eq!(encoder.space_remaining(), 1); - encoder.put_byte(42, Case::Lower); - assert_eq!(encoder.as_str(), "2a"); - assert_eq!(encoder.space_remaining(), 0); - assert!(encoder.is_full()); - encoder.clear(); - assert_eq!(encoder.space_remaining(), 1); - assert!(!encoder.is_full()); - encoder.put_byte(42, Case::Upper); - assert_eq!(encoder.as_str(), "2A"); - assert_eq!(encoder.space_remaining(), 0); - assert!(encoder.is_full()); - } - - #[test] - fn single_byte_oversized_buf() { - let mut buf = [0u8; 4]; - let mut encoder = BufEncoder::new(&mut buf); - assert_eq!(encoder.space_remaining(), 2); - encoder.put_byte(42, Case::Lower); - assert_eq!(encoder.space_remaining(), 1); - assert_eq!(encoder.as_str(), "2a"); - assert!(!encoder.is_full()); - encoder.clear(); - assert_eq!(encoder.space_remaining(), 2); - encoder.put_byte(42, Case::Upper); - assert_eq!(encoder.as_str(), "2A"); - assert_eq!(encoder.space_remaining(), 1); - assert!(!encoder.is_full()); - } - - #[test] - fn two_bytes() { - let mut buf = [0u8; 4]; - let mut encoder = BufEncoder::new(&mut buf); - encoder.put_byte(42, Case::Lower); - assert_eq!(encoder.space_remaining(), 1); - encoder.put_byte(255, Case::Lower); - assert_eq!(encoder.space_remaining(), 0); - assert_eq!(encoder.as_str(), "2aff"); - assert!(encoder.is_full()); - encoder.clear(); - assert!(!encoder.is_full()); - encoder.put_byte(42, Case::Upper); - encoder.put_byte(255, Case::Upper); - assert_eq!(encoder.as_str(), "2AFF"); - assert!(encoder.is_full()); - } - - #[test] - fn put_bytes_min() { - let mut buf = [0u8; 2]; - let mut encoder = BufEncoder::new(&mut buf); - let remainder = encoder.put_bytes_min(b"", Case::Lower); - assert_eq!(remainder, b""); - assert_eq!(encoder.as_str(), ""); - let remainder = encoder.put_bytes_min(b"*", Case::Lower); - assert_eq!(remainder, b""); - assert_eq!(encoder.as_str(), "2a"); - encoder.clear(); - let remainder = encoder.put_bytes_min(&[42, 255], Case::Lower); - assert_eq!(remainder, &[255]); - assert_eq!(encoder.as_str(), "2a"); - } - - #[test] - fn same_as_fmt() { - use core::fmt::{self, Write}; - - struct Writer { - buf: [u8; 2], - pos: usize, - } - - impl Writer { - fn as_str(&self) -> &str { core::str::from_utf8(&self.buf[..self.pos]).unwrap() } - } - - impl Write for Writer { - fn write_str(&mut self, s: &str) -> fmt::Result { - assert!(self.pos <= 2); - if s.len() > 2 - self.pos { - Err(fmt::Error) - } else { - self.buf[self.pos..(self.pos + s.len())].copy_from_slice(s.as_bytes()); - self.pos += s.len(); - Ok(()) - } - } - } - - let mut writer = Writer { buf: [0u8; 2], pos: 0 }; - let mut buf = [0u8; 2]; - let mut encoder = BufEncoder::new(&mut buf); - - for i in 0..=255 { - write!(writer, "{:02x}", i).unwrap(); - encoder.put_byte(i, Case::Lower); - assert_eq!(encoder.as_str(), writer.as_str()); - writer.pos = 0; - encoder.clear(); - } - for i in 0..=255 { - write!(writer, "{:02X}", i).unwrap(); - encoder.put_byte(i, Case::Upper); - assert_eq!(encoder.as_str(), writer.as_str()); - writer.pos = 0; - encoder.clear(); - } - } -} diff --git a/internals/src/hex/display.rs b/internals/src/hex/display.rs deleted file mode 100644 index 85da1684b5..0000000000 --- a/internals/src/hex/display.rs +++ /dev/null @@ -1,303 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -//! Helpers for displaying bytes as hex strings. -//! -//! This module provides a trait for displaying things as hex as well as an implementation for -//! `&[u8]`. - -use core::borrow::Borrow; -use core::fmt; - -use super::buf_encoder::{BufEncoder, OutBytes}; -use super::Case; -use crate::hex::buf_encoder::FixedLenBuf; -#[cfg(feature = "alloc")] -use crate::prelude::*; - -/// Extension trait for types that can be displayed as hex. -/// -/// Types that have a single, obvious text representation being hex should **not** implement this -/// trait and simply implement `Display` instead. -/// -/// This trait should be generally implemented for references only. We would prefer to use GAT but -/// that is beyond our MSRV. As a lint we require the `IsRef` trait which is implemented for all -/// references. -pub trait DisplayHex: Copy + sealed::IsRef { - /// The type providing [`fmt::Display`] implementation. - /// - /// This is usually a wrapper type holding a reference to `Self`. - type Display: fmt::LowerHex + fmt::UpperHex; - - /// Display `Self` as a continuous sequence of ASCII hex chars. - fn as_hex(self) -> Self::Display; - - /// Create a lower-hex-encoded string. - /// - /// A shorthand for `to_hex_string(Case::Lower)`, so that `Case` doesn't need to be imported. - /// - /// This may be faster than `.display_hex().to_string()` because it uses `reserve_suggestion`. - #[cfg(feature = "alloc")] - fn to_lower_hex_string(self) -> String { self.to_hex_string(Case::Lower) } - - /// Create an upper-hex-encoded string. - /// - /// A shorthand for `to_hex_string(Case::Upper)`, so that `Case` doesn't need to be imported. - /// - /// This may be faster than `.display_hex().to_string()` because it uses `reserve_suggestion`. - #[cfg(feature = "alloc")] - fn to_upper_hex_string(self) -> String { self.to_hex_string(Case::Upper) } - - /// Create a hex-encoded string. - /// - /// This may be faster than `.display_hex().to_string()` because it uses `reserve_suggestion`. - #[cfg(feature = "alloc")] - fn to_hex_string(self, case: Case) -> String { - let mut string = String::new(); - self.append_hex_to_string(case, &mut string); - string - } - - /// Appends hex-encoded content to an existing `String`. - /// - /// This may be faster than `write!(string, "{:x}", self.display_hex())` because it uses - /// `reserve_sugggestion`. - #[cfg(feature = "alloc")] - fn append_hex_to_string(self, case: Case, string: &mut String) { - use fmt::Write; - - string.reserve(self.hex_reserve_suggestion()); - match case { - Case::Lower => write!(string, "{:x}", self.as_hex()), - Case::Upper => write!(string, "{:X}", self.as_hex()), - } - .unwrap_or_else(|_| { - let name = core::any::type_name::(); - // We don't expect `std` to ever be buggy, so the bug is most likely in the `Display` - // impl of `Self::Display`. - panic!("The implementation of Display for {} returned an error when it shouldn't", name) - }) - } - - /// Hints how much bytes to reserve when creating a `String`. - /// - /// Implementors that know the number of produced bytes upfront should override this. - /// Defaults to 0. - /// - // We prefix the name with `hex_` to avoid potential collision with other methods. - fn hex_reserve_suggestion(self) -> usize { 0 } -} - -mod sealed { - /// Trait marking a shared reference. - pub trait IsRef: Copy {} - - impl IsRef for &'_ T {} -} - -impl<'a> DisplayHex for &'a [u8] { - type Display = DisplayByteSlice<'a>; - - #[inline] - fn as_hex(self) -> Self::Display { DisplayByteSlice { bytes: self } } - - #[inline] - fn hex_reserve_suggestion(self) -> usize { - // Since the string wouldn't fit into address space if this overflows (actually even for - // smaller amounts) it's better to panic right away. It should also give the optimizer - // better opportunities. - self.len().checked_mul(2).expect("the string wouldn't fit into address space") - } -} - -#[cfg(feature = "alloc")] -impl<'a> DisplayHex for &'a alloc::vec::Vec { - type Display = DisplayByteSlice<'a>; - - #[inline] - fn as_hex(self) -> Self::Display { DisplayByteSlice { bytes: self } } - - #[inline] - fn hex_reserve_suggestion(self) -> usize { - // Since the string wouldn't fit into address space if this overflows (actually even for - // smaller amounts) it's better to panic right away. It should also give the optimizer - // better opportunities. - self.len().checked_mul(2).expect("the string wouldn't fit into address space") - } -} - -/// Displays byte slice as hex. -/// -/// Created by [`<&[u8] as DisplayHex>::as_hex`](DisplayHex::as_hex). -pub struct DisplayByteSlice<'a> { - // pub because we want to keep lengths in sync - pub(crate) bytes: &'a [u8], -} - -impl<'a> DisplayByteSlice<'a> { - fn display(&self, f: &mut fmt::Formatter, case: Case) -> fmt::Result { - let mut buf = [0u8; 1024]; - let mut encoder = super::BufEncoder::new(&mut buf); - - let mut chunks = self.bytes.chunks_exact(512); - for chunk in &mut chunks { - encoder.put_bytes(chunk, case); - f.write_str(encoder.as_str())?; - encoder.clear(); - } - encoder.put_bytes(chunks.remainder(), case); - f.write_str(encoder.as_str()) - } -} - -impl<'a> fmt::LowerHex for DisplayByteSlice<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.display(f, Case::Lower) } -} - -impl<'a> fmt::UpperHex for DisplayByteSlice<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.display(f, Case::Upper) } -} - -/// Displays byte array as hex. -/// -/// Created by [`<&[u8; LEN] as DisplayHex>::as_hex`](DisplayHex::as_hex). -pub struct DisplayArray -where - A::Item: Borrow, -{ - array: A, - _buffer_marker: core::marker::PhantomData, -} - -impl DisplayArray -where - A::Item: Borrow, -{ - /// Creates the wrapper. - pub fn new(array: A) -> Self { DisplayArray { array, _buffer_marker: Default::default() } } - - fn display(&self, f: &mut fmt::Formatter, case: Case) -> fmt::Result { - let mut buf = B::uninit(); - let mut encoder = super::BufEncoder::new(&mut buf); - encoder.put_bytes(self.array.clone(), case); - f.pad_integral(true, "0x", encoder.as_str()) - } -} - -impl fmt::LowerHex for DisplayArray -where - A::Item: Borrow, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.display(f, Case::Lower) } -} - -impl fmt::UpperHex for DisplayArray -where - A::Item: Borrow, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.display(f, Case::Upper) } -} - -/// Format known-length array as hex. -/// -/// This supports all formatting options of formatter and may be faster than calling -/// `display_as_hex()` on an arbitrary `&[u8]`. Note that the implementation intentionally keeps -/// leading zeros even when not requested. This is designed to display values such as hashes and -/// keys and removing leading zeros would be confusing. -/// -/// ## Parameters -/// -/// * `$formatter` - a [`fmt::Formatter`]. -/// * `$len` known length of `$bytes`, must be a const expression. -/// * `$bytes` - bytes to be encoded, most likely a reference to an array. -/// * `$case` - value of type [`Case`] determining whether to format as lower or upper case. -/// -/// ## Panics -/// -/// This macro panics if `$len` is not equal to `$bytes.len()`. It also fails to compile if `$len` -/// is more than half of `usize::MAX`. -#[macro_export] -macro_rules! fmt_hex_exact { - ($formatter:expr, $len:expr, $bytes:expr, $case:expr) => {{ - // statically check $len - #[allow(deprecated)] - const _: () = [()][($len > usize::MAX / 2) as usize]; - assert_eq!($bytes.len(), $len); - let mut buf = [0u8; $len * 2]; - let buf = $crate::hex::buf_encoder::AsOutBytes::as_mut_out_bytes(&mut buf); - $crate::hex::display::fmt_hex_exact_fn($formatter, buf, $bytes, $case) - }}; -} -pub use fmt_hex_exact; - -// Implementation detail of `write_hex_exact` macro to de-duplicate the code -#[doc(hidden)] -#[inline] -pub fn fmt_hex_exact_fn( - f: &mut fmt::Formatter, - buf: &mut OutBytes, - bytes: I, - case: Case, -) -> fmt::Result -where - I: IntoIterator, - I::Item: Borrow, -{ - let mut encoder = BufEncoder::new(buf); - encoder.put_bytes(bytes, case); - f.pad_integral(true, "0x", encoder.as_str()) -} - -#[cfg(test)] -mod tests { - #[cfg(feature = "alloc")] - use super::*; - - #[cfg(feature = "alloc")] - mod alloc { - use super::*; - - fn check_encoding(bytes: &[u8]) { - use core::fmt::Write; - - let s1 = bytes.to_lower_hex_string(); - let mut s2 = String::with_capacity(bytes.len() * 2); - for b in bytes { - write!(s2, "{:02x}", b).unwrap(); - } - assert_eq!(s1, s2); - } - - #[test] - fn empty() { check_encoding(b""); } - - #[test] - fn single() { check_encoding(b"*"); } - - #[test] - fn two() { check_encoding(b"*x"); } - - #[test] - fn just_below_boundary() { check_encoding(&[42; 512]); } - - #[test] - fn just_above_boundary() { check_encoding(&[42; 513]); } - - #[test] - fn just_above_double_boundary() { check_encoding(&[42; 1025]); } - - #[test] - fn fmt_exact_macro() { - use crate::alloc::string::ToString; - - struct Dummy([u8; 32]); - - impl fmt::Display for Dummy { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt_hex_exact!(f, 32, &self.0, Case::Lower) - } - } - - assert_eq!(Dummy([42; 32]).to_string(), "2a".repeat(32)); - } - } -} diff --git a/internals/src/hex/mod.rs b/internals/src/hex/mod.rs deleted file mode 100644 index 54fd04654d..0000000000 --- a/internals/src/hex/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -//! Helpers for encoding bytes as hex strings. - -pub mod buf_encoder; -pub mod display; - -pub use buf_encoder::BufEncoder; - -/// Reexports of extension traits. -pub mod exts { - pub use super::display::DisplayHex; -} - -/// Possible case of hex. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum Case { - /// Produce lower-case chars (`[0-9a-f]`). - /// - /// This is the default. - Lower, - - /// Produce upper-case chars (`[0-9A-F]`). - Upper, -} - -impl Default for Case { - fn default() -> Self { Case::Lower } -} - -impl Case { - /// Returns the encoding table. - /// - /// The returned table may only contain displayable ASCII chars. - #[inline] - #[rustfmt::skip] - pub(crate) fn table(self) -> &'static [u8; 16] { - static LOWER: [u8; 16] = [b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f']; - static UPPER: [u8; 16] = [b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F']; - - match self { - Case::Lower => &LOWER, - Case::Upper => &UPPER, - } - } -} - -/// Encodes single byte as two ASCII chars using the given table. -/// -/// The function guarantees only returning values from the provided table. -#[inline] -pub(crate) fn byte_to_hex(byte: u8, table: &[u8; 16]) -> [u8; 2] { - [table[usize::from(byte.wrapping_shr(4))], table[usize::from(byte & 0x0F)]] -} diff --git a/internals/src/lib.rs b/internals/src/lib.rs index f85e0b8f56..a024e273a4 100644 --- a/internals/src/lib.rs +++ b/internals/src/lib.rs @@ -19,13 +19,6 @@ extern crate alloc; extern crate std; pub mod error; -pub mod hex; pub mod macros; mod parse; pub mod serde; - -/// Mainly reexports based on features. -pub(crate) mod prelude { - #[cfg(feature = "alloc")] - pub(crate) use alloc::string::String; -}