summaryrefslogtreecommitdiffstats
path: root/vendor/crypto-bigint/src/uint/encoding.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/crypto-bigint/src/uint/encoding.rs')
-rw-r--r--vendor/crypto-bigint/src/uint/encoding.rs278
1 files changed, 278 insertions, 0 deletions
diff --git a/vendor/crypto-bigint/src/uint/encoding.rs b/vendor/crypto-bigint/src/uint/encoding.rs
new file mode 100644
index 000000000..a83976238
--- /dev/null
+++ b/vendor/crypto-bigint/src/uint/encoding.rs
@@ -0,0 +1,278 @@
+//! Const-friendly decoding operations for [`UInt`]
+
+#[cfg(all(feature = "der", feature = "generic-array"))]
+mod der;
+
+#[cfg(feature = "rlp")]
+mod rlp;
+
+use super::UInt;
+use crate::{Encoding, Limb, Word};
+
+impl<const LIMBS: usize> UInt<LIMBS> {
+ /// Create a new [`UInt`] from the provided big endian bytes.
+ pub const fn from_be_slice(bytes: &[u8]) -> Self {
+ assert!(
+ bytes.len() == Limb::BYTE_SIZE * LIMBS,
+ "bytes are not the expected size"
+ );
+
+ let mut res = [Limb::ZERO; LIMBS];
+ let mut buf = [0u8; Limb::BYTE_SIZE];
+ let mut i = 0;
+
+ while i < LIMBS {
+ let mut j = 0;
+ while j < Limb::BYTE_SIZE {
+ buf[j] = bytes[i * Limb::BYTE_SIZE + j];
+ j += 1;
+ }
+ res[LIMBS - i - 1] = Limb(Word::from_be_bytes(buf));
+ i += 1;
+ }
+
+ UInt::new(res)
+ }
+
+ /// Create a new [`UInt`] from the provided big endian hex string.
+ pub const fn from_be_hex(hex: &str) -> Self {
+ let bytes = hex.as_bytes();
+
+ assert!(
+ bytes.len() == Limb::BYTE_SIZE * LIMBS * 2,
+ "hex string is not the expected size"
+ );
+
+ let mut res = [Limb::ZERO; LIMBS];
+ let mut buf = [0u8; Limb::BYTE_SIZE];
+ let mut i = 0;
+
+ while i < LIMBS {
+ let mut j = 0;
+ while j < Limb::BYTE_SIZE {
+ let offset = (i * Limb::BYTE_SIZE + j) * 2;
+ buf[j] = decode_hex_byte([bytes[offset], bytes[offset + 1]]);
+ j += 1;
+ }
+ res[LIMBS - i - 1] = Limb(Word::from_be_bytes(buf));
+ i += 1;
+ }
+
+ UInt::new(res)
+ }
+
+ /// Create a new [`UInt`] from the provided little endian bytes.
+ pub const fn from_le_slice(bytes: &[u8]) -> Self {
+ assert!(
+ bytes.len() == Limb::BYTE_SIZE * LIMBS,
+ "bytes are not the expected size"
+ );
+
+ let mut res = [Limb::ZERO; LIMBS];
+ let mut buf = [0u8; Limb::BYTE_SIZE];
+ let mut i = 0;
+
+ while i < LIMBS {
+ let mut j = 0;
+ while j < Limb::BYTE_SIZE {
+ buf[j] = bytes[i * Limb::BYTE_SIZE + j];
+ j += 1;
+ }
+ res[i] = Limb(Word::from_le_bytes(buf));
+ i += 1;
+ }
+
+ UInt::new(res)
+ }
+
+ /// Create a new [`UInt`] from the provided little endian hex string.
+ pub const fn from_le_hex(hex: &str) -> Self {
+ let bytes = hex.as_bytes();
+
+ assert!(
+ bytes.len() == Limb::BYTE_SIZE * LIMBS * 2,
+ "bytes are not the expected size"
+ );
+
+ let mut res = [Limb::ZERO; LIMBS];
+ let mut buf = [0u8; Limb::BYTE_SIZE];
+ let mut i = 0;
+
+ while i < LIMBS {
+ let mut j = 0;
+ while j < Limb::BYTE_SIZE {
+ let offset = (i * Limb::BYTE_SIZE + j) * 2;
+ buf[j] = decode_hex_byte([bytes[offset], bytes[offset + 1]]);
+ j += 1;
+ }
+ res[i] = Limb(Word::from_le_bytes(buf));
+ i += 1;
+ }
+
+ UInt::new(res)
+ }
+
+ /// Serialize this [`UInt`] as big-endian, writing it into the provided
+ /// byte slice.
+ #[inline]
+ #[cfg_attr(docsrs, doc(cfg(feature = "generic-array")))]
+ pub(crate) fn write_be_bytes(&self, out: &mut [u8]) {
+ debug_assert_eq!(out.len(), Limb::BYTE_SIZE * LIMBS);
+
+ for (src, dst) in self
+ .limbs
+ .iter()
+ .rev()
+ .cloned()
+ .zip(out.chunks_exact_mut(Limb::BYTE_SIZE))
+ {
+ dst.copy_from_slice(&src.to_be_bytes());
+ }
+ }
+
+ /// Serialize this [`UInt`] as little-endian, writing it into the provided
+ /// byte slice.
+ #[inline]
+ #[cfg_attr(docsrs, doc(cfg(feature = "generic-array")))]
+ pub(crate) fn write_le_bytes(&self, out: &mut [u8]) {
+ debug_assert_eq!(out.len(), Limb::BYTE_SIZE * LIMBS);
+
+ for (src, dst) in self
+ .limbs
+ .iter()
+ .cloned()
+ .zip(out.chunks_exact_mut(Limb::BYTE_SIZE))
+ {
+ dst.copy_from_slice(&src.to_le_bytes());
+ }
+ }
+}
+
+/// Decode a single byte encoded as two hexadecimal characters.
+const fn decode_hex_byte(bytes: [u8; 2]) -> u8 {
+ let mut i = 0;
+ let mut result = 0u8;
+
+ while i < 2 {
+ result <<= 4;
+ result |= match bytes[i] {
+ b @ b'0'..=b'9' => b - b'0',
+ b @ b'a'..=b'f' => 10 + b - b'a',
+ b @ b'A'..=b'F' => 10 + b - b'A',
+ b => {
+ assert!(
+ matches!(b, b'0'..=b'9' | b'a' ..= b'f' | b'A'..=b'F'),
+ "invalid hex byte"
+ );
+ 0
+ }
+ };
+
+ i += 1;
+ }
+
+ result
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::Limb;
+ use hex_literal::hex;
+
+ #[cfg(feature = "alloc")]
+ use {crate::U128, alloc::format};
+
+ #[cfg(target_pointer_width = "32")]
+ use crate::U64 as UIntEx;
+
+ #[cfg(target_pointer_width = "64")]
+ use crate::U128 as UIntEx;
+
+ #[test]
+ #[cfg(target_pointer_width = "32")]
+ fn from_be_slice() {
+ let bytes = hex!("0011223344556677");
+ let n = UIntEx::from_be_slice(&bytes);
+ assert_eq!(n.limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn from_be_slice() {
+ let bytes = hex!("00112233445566778899aabbccddeeff");
+ let n = UIntEx::from_be_slice(&bytes);
+ assert_eq!(
+ n.limbs(),
+ &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
+ );
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "32")]
+ fn from_le_slice() {
+ let bytes = hex!("7766554433221100");
+ let n = UIntEx::from_le_slice(&bytes);
+ assert_eq!(n.limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn from_le_slice() {
+ let bytes = hex!("ffeeddccbbaa99887766554433221100");
+ let n = UIntEx::from_le_slice(&bytes);
+ assert_eq!(
+ n.limbs(),
+ &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
+ );
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "32")]
+ fn from_be_hex() {
+ let n = UIntEx::from_be_hex("0011223344556677");
+ assert_eq!(n.limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn from_be_hex() {
+ let n = UIntEx::from_be_hex("00112233445566778899aabbccddeeff");
+ assert_eq!(
+ n.limbs(),
+ &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
+ );
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "32")]
+ fn from_le_hex() {
+ let n = UIntEx::from_le_hex("7766554433221100");
+ assert_eq!(n.limbs(), &[Limb(0x44556677), Limb(0x00112233)]);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn from_le_hex() {
+ let n = UIntEx::from_le_hex("ffeeddccbbaa99887766554433221100");
+ assert_eq!(
+ n.limbs(),
+ &[Limb(0x8899aabbccddeeff), Limb(0x0011223344556677)]
+ );
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn hex_upper() {
+ let hex = "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD";
+ let n = U128::from_be_hex(hex);
+ assert_eq!(hex, format!("{:X}", n));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn hex_lower() {
+ let hex = "aaaaaaaabbbbbbbbccccccccdddddddd";
+ let n = U128::from_be_hex(hex);
+ assert_eq!(hex, format!("{:x}", n));
+ }
+}