From 43a97878ce14b72f0981164f87f2e35e14151312 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:22:09 +0200 Subject: Adding upstream version 110.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/generic-array/src/hex.rs | 105 ++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 third_party/rust/generic-array/src/hex.rs (limited to 'third_party/rust/generic-array/src/hex.rs') diff --git a/third_party/rust/generic-array/src/hex.rs b/third_party/rust/generic-array/src/hex.rs new file mode 100644 index 0000000000..33c796f3c9 --- /dev/null +++ b/third_party/rust/generic-array/src/hex.rs @@ -0,0 +1,105 @@ +//! Generic array are commonly used as a return value for hash digests, so +//! it's a good idea to allow to hexlify them easily. This module implements +//! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits. +//! +//! Example: +//! +//! ```rust +//! # #[macro_use] +//! # extern crate generic_array; +//! # extern crate typenum; +//! # fn main() { +//! let array = arr![u8; 10, 20, 30]; +//! assert_eq!(format!("{:x}", array), "0a141e"); +//! # } +//! ``` +//! + +use core::{fmt, str, ops::Add, cmp::min}; + +use typenum::*; + +use crate::{ArrayLength, GenericArray}; + +static LOWER_CHARS: &'static [u8] = b"0123456789abcdef"; +static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF"; + +impl> fmt::LowerHex for GenericArray +where + T: Add, + >::Output: ArrayLength, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let max_digits = f.precision().unwrap_or_else(|| self.len() * 2); + let max_hex = (max_digits >> 1) + (max_digits & 1); + + if T::USIZE < 1024 { + // For small arrays use a stack allocated + // buffer of 2x number of bytes + let mut res = GenericArray::>::default(); + + self.iter().take(max_hex).enumerate().for_each(|(i, c)| { + res[i * 2] = LOWER_CHARS[(c >> 4) as usize]; + res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize]; + }); + + f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?; + } else { + // For large array use chunks of up to 1024 bytes (2048 hex chars) + let mut buf = [0u8; 2048]; + let mut digits_left = max_digits; + + for chunk in self[..max_hex].chunks(1024) { + chunk.iter().enumerate().for_each(|(i, c)| { + buf[i * 2] = LOWER_CHARS[(c >> 4) as usize]; + buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize]; + }); + + let n = min(chunk.len() * 2, digits_left); + f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?; + digits_left -= n; + } + } + Ok(()) + } +} + +impl> fmt::UpperHex for GenericArray +where + T: Add, + >::Output: ArrayLength, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let max_digits = f.precision().unwrap_or_else(|| self.len() * 2); + let max_hex = (max_digits >> 1) + (max_digits & 1); + + if T::USIZE < 1024 { + // For small arrays use a stack allocated + // buffer of 2x number of bytes + let mut res = GenericArray::>::default(); + + self.iter().take(max_hex).enumerate().for_each(|(i, c)| { + res[i * 2] = UPPER_CHARS[(c >> 4) as usize]; + res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize]; + }); + + f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?; + } else { + // For large array use chunks of up to 1024 bytes (2048 hex chars) + let mut buf = [0u8; 2048]; + let mut digits_left = max_digits; + + for chunk in self[..max_hex].chunks(1024) { + chunk.iter().enumerate().for_each(|(i, c)| { + buf[i * 2] = UPPER_CHARS[(c >> 4) as usize]; + buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize]; + }); + + let n = min(chunk.len() * 2, digits_left); + f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?; + digits_left -= n; + } + } + Ok(()) + } +} -- cgit v1.2.3