diff --git a/src/uint.rs b/src/uint.rs index d61f01d..3b61899 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -776,9 +776,7 @@ macro_rules! construct_uint { pub fn overflowing_neg(self) -> ($name, bool) { (!self, true) } - } - impl $name { /// Multiplication by u32 #[allow(dead_code)] // not used when multiplied with inline assembly fn mul_u32(self, other: u32) -> Self { @@ -803,6 +801,33 @@ macro_rules! construct_uint { ($name(ret), carry > 0) } + + /// Converts from big endian representation bytes in memory + /// Can also be used as (&slice).into(), as it is default `From` + /// slice implementation for U256 + pub fn from_big_endian(slice: &[u8]) -> Self { + assert!($n_words * 8 >= slice.len()); + + let mut ret = [0; $n_words]; + for i in 0..slice.len() { + let rev = slice.len() - 1 - i; + let pos = rev / 8; + ret[pos] += (slice[i] as u64) << ((rev % 8) * 8); + } + $name(ret) + } + + /// Converts from little endian representation bytes in memory + pub fn from_little_endian(slice: &[u8]) -> Self { + assert!($n_words * 8 >= slice.len()); + + let mut ret = [0; $n_words]; + for i in 0..slice.len() { + let pos = i / 8; + ret[pos] += (slice[i] as u64) << ((i % 8) * 8); + } + $name(ret) + } } impl Default for $name { @@ -839,17 +864,10 @@ macro_rules! construct_uint { impl_map_from!($name, i32, i64); impl_map_from!($name, isize, i64); + // Converts from big endian representation of U256 impl<'a> From<&'a [u8]> for $name { fn from(bytes: &[u8]) -> $name { - assert!($n_words * 8 >= bytes.len()); - - let mut ret = [0; $n_words]; - for i in 0..bytes.len() { - let rev = bytes.len() - 1 - i; - let pos = rev / 8; - ret[pos] += (bytes[i] as u64) << ((rev % 8) * 8); - } - $name(ret) + Self::from_big_endian(bytes) } } @@ -1429,6 +1447,66 @@ impl From for u32 { } } +impl<'a> From<&'a [u8; 32]> for U256 { + fn from(bytes: &[u8; 32]) -> Self { + bytes[..].into() + } +} + +impl From<[u8; 32]> for U256 { + fn from(bytes: [u8; 32]) -> Self { + bytes[..].as_ref().into() + } +} + +impl From for [u8; 32] { + fn from(number: U256) -> Self { + let mut arr = [0u8; 32]; + number.to_big_endian(&mut arr); + arr + } +} + +impl<'a> From<&'a [u8; 16]> for U128 { + fn from(bytes: &[u8; 16]) -> Self { + bytes[..].into() + } +} + +impl From<[u8; 16]> for U128 { + fn from(bytes: [u8; 16]) -> Self { + bytes[..].as_ref().into() + } +} + +impl From for [u8; 16] { + fn from(number: U128) -> Self { + let mut arr = [0u8; 16]; + number.to_big_endian(&mut arr); + arr + } +} + +impl<'a> From<&'a [u8; 64]> for U512 { + fn from(bytes: &[u8; 64]) -> Self { + bytes[..].into() + } +} + +impl From<[u8; 64]> for U512 { + fn from(bytes: [u8; 64]) -> Self { + bytes[..].as_ref().into() + } +} + +impl From for [u8; 64] { + fn from(number: U512) -> Self { + let mut arr = [0u8; 64]; + number.to_big_endian(&mut arr); + arr + } +} + #[cfg(feature="heapsizeof")] known_heap_size!(0, U128, U256); @@ -2304,4 +2382,49 @@ mod tests { number.to_little_endian(&mut result); assert_eq!(expected, result); } -} + + #[test] + fn slice_roundtrip() { + let raw = [ + 1u8, 2, 3, 5, 7, 11, 13, 17, + 19, 23, 29, 31, 37, 41, 43, 47, + 53, 59, 61, 67, 71, 73, 79, 83, + 89, 97, 101, 103, 107, 109, 113, 127 + ]; + + let u256: U256 = (&raw[..]).into(); + + let mut new_raw = [0u8; 32]; + + u256.to_big_endian(&mut new_raw); + + assert_eq!(&raw, &new_raw); + } + + #[test] + fn slice_roundtrip_le() { + let raw = [ + 1u8, 2, 3, 5, 7, 11, 13, 17, + 19, 23, 29, 31, 37, 41, 43, 47, + 53, 59, 61, 67, 71, 73, 79, 83, + 89, 97, 101, 103, 107, 109, 113, 127 + ]; + + let u256 = U256::from_little_endian(&raw[..]); + + let mut new_raw = [0u8; 32]; + + u256.to_little_endian(&mut new_raw); + + assert_eq!(&raw, &new_raw); + } + + #[test] + fn fixed_arrays_roundtrip() { + let raw: U256 = "7094875209347850239487502394881".into(); + let array: [u8; 32] = raw.into(); + let new_raw = array.into(); + + assert_eq!(raw, new_raw); + } + }