diff --git a/Cargo.lock b/Cargo.lock index d2e46eb..f0b4a5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -256,7 +256,7 @@ dependencies = [ name = "cainome-cairo-serde" version = "0.1.0" dependencies = [ - "num-bigint", + "num", "serde", "serde_with", "starknet", @@ -1114,6 +1114,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -1124,6 +1138,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -1139,6 +1162,28 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" diff --git a/Cargo.toml b/Cargo.toml index 559f381..da62d8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ cainome-rs = { path = "crates/rs" } anyhow = "1.0" async-trait = "0.1" -num-bigint = "0.4.6" +num = "0.4.3" camino = { version = "1.1", features = ["serde1"] } convert_case = "0.6" serde = { version = "1.0", default-features = false, features = ["alloc"] } diff --git a/crates/cairo-serde/Cargo.toml b/crates/cairo-serde/Cargo.toml index 7995d95..672e11c 100644 --- a/crates/cairo-serde/Cargo.toml +++ b/crates/cairo-serde/Cargo.toml @@ -10,4 +10,4 @@ starknet.workspace = true thiserror.workspace = true serde.workspace = true serde_with = { version = "3.11.0", default-features = false } -num-bigint.workspace = true +num.workspace = true diff --git a/crates/cairo-serde/src/types/u256.rs b/crates/cairo-serde/src/types/u256.rs index d518e95..bf48225 100644 --- a/crates/cairo-serde/src/types/u256.rs +++ b/crates/cairo-serde/src/types/u256.rs @@ -1,20 +1,62 @@ use crate::CairoSerde; -use num_bigint::{BigInt, BigUint, ParseBigIntError}; +use num::{bigint::ParseBigIntError, BigUint, Num}; use serde_with::{DeserializeAs, DisplayFromStr, SerializeAs}; -use starknet::core::types::Felt; +use starknet::core::types::{Felt, U256 as StarknetU256}; use std::{ cmp::Ordering, fmt::Display, - ops::{Add, BitOr, Sub}, + ops::{Add, BitOr, Mul, Sub}, str::FromStr, }; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub struct U256 { pub low: u128, pub high: u128, } +impl U256 { + pub const ZERO: U256 = Self::from_u128(0); + pub const ONE: U256 = Self::from_u128(1); + pub const TWO: U256 = Self::from_u128(2); + + const fn from_u128(value: u128) -> Self { + U256 { + low: value, + high: 0, + } + } +} + +macro_rules! impl_from_for_u256 { + ($($t:ty),*) => { + $( + impl From<$t> for U256 { + fn from(value: $t) -> Self { + Self::from_u128(value as u128) + } + } + )* + }; +} + +impl_from_for_u256!(u8, u16, u32, u64, u128, usize); + +impl From for U256 { + fn from(value: StarknetU256) -> Self { + Self { + low: value.low(), + high: value.high(), + } + } +} + +impl From for StarknetU256 { + fn from(value: U256) -> Self { + StarknetU256::from_words(value.low, value.high) + } +} + impl PartialOrd for U256 { fn partial_cmp(&self, other: &Self) -> Option { Some(match self.high.cmp(&other.high) { @@ -59,6 +101,14 @@ impl Sub for U256 { } } +impl Mul for U256 { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + (StarknetU256::from(self) * StarknetU256::from(rhs)).into() + } +} + impl BitOr for U256 { type Output = Self; @@ -76,18 +126,22 @@ impl Display for U256 { num += BigUint::from(self.high); num <<= 128; num += BigUint::from(self.low); - write!(f, "{}", num) + write!(f, "0x{}", num.to_str_radix(16)) } } impl FromStr for U256 { type Err = ParseBigIntError; fn from_str(s: &str) -> Result { - let num = BigInt::from_str(s)?; - let num_big_uint = num.to_biguint().unwrap(); + let num = if s.len() >= 2 && &s[0..2] == "0x" { + BigUint::from_str_radix(&s[2..], 16) + } else { + BigUint::from_str(s) + } + .unwrap(); let mask = (BigUint::from(1u128) << 128u32) - BigUint::from(1u128); - let b_low: BigUint = (num_big_uint.clone() >> 0) & mask.clone(); - let b_high: BigUint = (num_big_uint.clone() >> 128) & mask.clone(); + let b_low: BigUint = (num.clone() >> 0) & mask.clone(); + let b_high: BigUint = (num.clone() >> 128) & mask.clone(); let mut low = 0; let mut high = 0; @@ -343,7 +397,7 @@ mod tests { high: 0_u128, }; println!("{}", u256); - assert_eq!(format!("{}", u256), "12"); + assert_eq!(format!("{}", u256), "0xc"); } #[test]