#[allow(clippy::useless_attribute)]
#[allow(clippy::wildcard_imports)]
use std::prelude::v1::*;
use crate::U256;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::u64;
impl U256 {
pub fn from_bytes_be(n: &[u8; 32]) -> Self {
Self::from_limbs([
u64::from_be_bytes([n[24], n[25], n[26], n[27], n[28], n[29], n[30], n[31]]),
u64::from_be_bytes([n[16], n[17], n[18], n[19], n[20], n[21], n[22], n[23]]),
u64::from_be_bytes([n[8], n[9], n[10], n[11], n[12], n[13], n[14], n[15]]),
u64::from_be_bytes([n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]]),
])
}
pub fn to_bytes_be(&self) -> [u8; 32] {
let mut r = [0; 32];
let mut n = self.clone();
#[allow(clippy::cast_possible_truncation)]
for i in (0..32).rev() {
r[i] = n.limb(0) as u8;
n >>= 8;
}
r
}
}
#[cfg(feature = "serde")]
impl Serialize for U256 {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
if serializer.is_human_readable() {
self.to_hex_string().serialize(serializer)
} else {
self.to_bytes_be().serialize(serializer)
}
}
}
#[cfg(feature = "serde")]
impl<'a> Deserialize<'a> for U256 {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
if deserializer.is_human_readable() {
let string = String::deserialize(deserializer)?;
Ok(U256::from_hex_str(&string))
} else {
<[u8; 32]>::deserialize(deserializer).map(|b| U256::from_bytes_be(&b))
}
}
}
impl From<bool> for U256 {
fn from(n: bool) -> Self {
Self::from_limbs([u64::from(n), 0, 0, 0])
}
}
macro_rules! impl_from_uint {
($type:ty) => {
impl From<$type> for U256 {
#[allow(trivial_numeric_casts)]
fn from(n: $type) -> Self {
Self::from_limbs([n as u64, 0, 0, 0])
}
}
};
}
impl_from_uint!(u8);
impl_from_uint!(u16);
impl_from_uint!(u32);
impl_from_uint!(u64);
impl_from_uint!(usize);
impl From<u128> for U256 {
fn from(n: u128) -> Self {
#[allow(clippy::cast_possible_truncation)]
Self::from_limbs([n as u64, (n >> 64) as u64, 0, 0])
}
}
macro_rules! impl_from_int {
($t:ty) => {
impl From<$t> for U256 {
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::cast_possible_truncation)]
fn from(n: $t) -> Self {
if n >= 0 {
Self::from_limbs([n as u64, 0, 0, 0])
} else {
Self::from_limbs([
n as u64,
u64::max_value(),
u64::max_value(),
u64::max_value(),
])
}
}
}
};
}
impl_from_int!(i8);
impl_from_int!(i16);
impl_from_int!(i32);
impl_from_int!(i64);
impl_from_int!(isize);
impl From<i128> for U256 {
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::cast_possible_truncation)]
fn from(n: i128) -> Self {
if n >= 0 {
Self::from_limbs([n as u64, (n >> 64) as u64, 0, 0])
} else {
Self::from_limbs([
n as u64,
(n >> 64) as u64,
u64::max_value(),
u64::max_value(),
])
}
}
}
macro_rules! as_int {
($name:ident, $type:ty) => {
#[allow(trivial_numeric_casts)]
pub fn $name(&self) -> $type {
self.limb(0) as $type
}
};
}
#[rustfmt::skip]
impl U256 {
as_int!(as_u8, u8);
as_int!(as_u16, u16);
as_int!(as_u32, u32);
as_int!(as_u64, u64);
as_int!(as_usize, usize);
as_int!(as_i8, i8);
as_int!(as_i16, i16);
as_int!(as_i32, i32);
as_int!(as_i64, i64);
as_int!(as_isize, isize);
#[allow(clippy::cast_lossless)]
pub fn as_u128(&self) -> u128 {
(self.limb(0) as u128) | ((self.limb(1) as u128) << 64)
}
#[allow(clippy::cast_lossless)]
pub fn as_i128(&self) -> i128 {
(self.limb(0) as i128) | ((self.limb(1) as i128) << 64)
}
}
#[cfg(test)]
mod tests {
use super::*;
use num_traits::identities::{One, Zero};
use proptest::prelude::*;
#[test]
fn test_bool() {
assert_eq!(U256::from(true), U256::one());
assert_eq!(U256::from(false), U256::zero());
}
#[cfg(feature = "serde")]
mod serde {
use super::*;
#[test]
fn test_one() {
let one = U256::one();
let serialized = serde_json::to_string(&one).unwrap();
assert_eq!(
serialized,
"\"0x0000000000000000000000000000000000000000000000000000000000000001\""
);
}
#[test]
fn test_json() {
proptest!(|(x: U256)| {
let serialized = serde_json::to_string(&x)?;
let deserialized: U256 = serde_json::from_str(&serialized)?;
prop_assert_eq!(deserialized, x);
});
}
#[test]
fn test_json_value() {
proptest!(|(x: U256)| {
let serialized = serde_json::to_value(&x)?;
let deserialized: U256 = serde_json::from_value(serialized)?;
prop_assert_eq!(deserialized, x);
});
}
#[test]
fn test_bincode() {
proptest!(|(x: U256)| {
let serialized = bincode::serialize(&x)?;
let deserialized: U256 = bincode::deserialize(&serialized)?;
prop_assert_eq!(deserialized, x);
});
}
}
#[cfg(feature = "parity_codec")]
mod parity_codec {
use super::*;
use parity_scale_codec::{Decode, Encode};
#[test]
fn test_one() {
let one = U256::one();
let serialized = one.encode();
assert_eq!(
hex::encode(serialized),
"0100000000000000000000000000000000000000000000000000000000000000"
);
}
#[test]
fn test_roundtrip() {
proptest!(|(x: U256)| {
let serialized = x.encode();
let mut slice = serialized.as_slice();
let deserialized: U256 = U256::decode(&mut slice)?;
prop_assert_eq!(slice.len(), 0); prop_assert_eq!(deserialized, x);
});
}
#[test]
fn test_little_endian() {
proptest!(|(x: U256)| {
let serialized = x.encode();
let little_endian: Vec<u8> = x.to_bytes_be().iter().rev().cloned().collect();
prop_assert_eq!(serialized, little_endian);
});
}
}
}