From 3851eb83690bae8b93279947855e7c29cb405f48 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sat, 25 Apr 2026 03:20:46 +0200 Subject: [PATCH] feat!: ban BITS == 0 --- src/add.rs | 6 ----- src/algorithms/gcd/matrix.rs | 3 --- src/algorithms/gcd/mod.rs | 5 +--- src/aliases.rs | 3 +-- src/base_convert.rs | 23 ------------------ src/bits.rs | 20 ---------------- src/bytes.rs | 7 ------ src/cmp.rs | 1 - src/const_for.rs | 9 +++----- src/from.rs | 28 ++++------------------ src/lib.rs | 6 ++--- src/modular.rs | 8 +------ src/mul.rs | 13 ++--------- src/pow.rs | 9 -------- src/root.rs | 2 +- src/special.rs | 1 - src/support/alloy_rlp.rs | 6 +---- src/support/bincode_2.rs | 10 -------- src/support/fastrlp_03.rs | 6 +---- src/support/fastrlp_04.rs | 6 +---- src/support/postgres.rs | 45 +++++++++++++----------------------- src/support/pyo3.rs | 5 +--- src/support/rlp.rs | 3 +-- src/support/serde.rs | 12 ++-------- 24 files changed, 38 insertions(+), 199 deletions(-) diff --git a/src/add.rs b/src/add.rs index 50ed0fc4..bec3344b 100644 --- a/src/add.rs +++ b/src/add.rs @@ -59,9 +59,6 @@ impl Uint { #[inline] #[must_use] pub const fn overflowing_add(mut self, rhs: Self) -> (Self, bool) { - if BITS == 0 { - return (Self::ZERO, false); - } let mut carry = false; let mut i = 0; while i < LIMBS { @@ -92,9 +89,6 @@ impl Uint { #[inline] #[must_use] pub const fn overflowing_sub(mut self, rhs: Self) -> (Self, bool) { - if BITS == 0 { - return (Self::ZERO, false); - } let mut borrow = false; let mut i = 0; while i < LIMBS { diff --git a/src/algorithms/gcd/matrix.rs b/src/algorithms/gcd/matrix.rs index ee8d330f..820767ec 100644 --- a/src/algorithms/gcd/matrix.rs +++ b/src/algorithms/gcd/matrix.rs @@ -41,9 +41,6 @@ impl Matrix { a: &mut Uint, b: &mut Uint, ) { - if BITS == 0 { - return; - } // OPT: We can avoid the temporary if we implement a dedicated matrix // multiplication. let (c, d) = if self.4 { diff --git a/src/algorithms/gcd/mod.rs b/src/algorithms/gcd/mod.rs index a24cae1f..48bd4ec8 100644 --- a/src/algorithms/gcd/mod.rs +++ b/src/algorithms/gcd/mod.rs @@ -68,9 +68,6 @@ pub fn gcd_extended( Uint, bool, ) { - if BITS == 0 { - return (Uint::ZERO, Uint::ZERO, Uint::ZERO, false); - } let swapped = a < b; if swapped { swap(&mut a, &mut b); @@ -142,7 +139,7 @@ pub fn inv_mod( num: Uint, modulus: Uint, ) -> Option> { - if BITS == 0 || modulus.is_zero() { + if modulus.is_zero() { return None; } let mut a = modulus; diff --git a/src/aliases.rs b/src/aliases.rs index 3a30d903..09963601 100644 --- a/src/aliases.rs +++ b/src/aliases.rs @@ -2,6 +2,7 @@ use crate::{Bits, Uint}; /// [`Uint`] for `0` bits. Always zero. Similar to `()`. +#[deprecated = "do not use"] pub type U0 = Uint<0, 0>; /// [`Uint`] for `1` bit. Similar to [`bool`]. @@ -30,7 +31,6 @@ macro_rules! bit_alias { } bit_alias! { - B0(0, 0); B1(1, 1); B8(8, 1); B16(16, 1); @@ -70,7 +70,6 @@ mod tests { #[test] const fn instantiate_consts() { - let _ = (U0::ZERO, U0::MAX, B0::ZERO); let _ = (U1::ZERO, U1::MAX, B1::ZERO); let _ = (U8::ZERO, U8::MAX, B8::ZERO); let _ = (U16::ZERO, U16::MAX, B16::ZERO); diff --git a/src/base_convert.rs b/src/base_convert.rs index f88af451..2c8b4706 100644 --- a/src/base_convert.rs +++ b/src/base_convert.rs @@ -137,17 +137,6 @@ impl Uint { if base < 2 { return Err(BaseConvertError::InvalidBase(base)); } - if BITS == 0 { - for digit in digits { - if digit >= base { - return Err(BaseConvertError::InvalidDigit(digit, base)); - } - if digit != 0 { - return Err(BaseConvertError::Overflow); - } - } - return Ok(Self::ZERO); - } let mut iter = digits.into_iter(); let mut result = Self::ZERO; @@ -533,18 +522,6 @@ mod tests { #[test] fn test_from_base_be_overflow() { - assert_eq!( - Uint::<0, 0>::from_base_be(10, core::iter::empty()), - Ok(Uint::<0, 0>::ZERO) - ); - assert_eq!( - Uint::<0, 0>::from_base_be(10, core::iter::once(0)), - Ok(Uint::<0, 0>::ZERO) - ); - assert_eq!( - Uint::<0, 0>::from_base_be(10, core::iter::once(1)), - Err(BaseConvertError::Overflow) - ); assert_eq!( Uint::<1, 1>::from_base_be(10, [1, 0, 0].into_iter()), Err(BaseConvertError::Overflow) diff --git a/src/bits.rs b/src/bits.rs index ccc447bd..88413668 100644 --- a/src/bits.rs +++ b/src/bits.rs @@ -124,9 +124,6 @@ impl Uint { #[inline] #[must_use] pub const fn not(mut self) -> Self { - if BITS == 0 { - return Self::ZERO; - } let mut i = 0; while i < LIMBS { self.limbs[i] = !self.limbs[i]; @@ -350,9 +347,6 @@ impl Uint { /// See [`overflowing_shl`](Self::overflowing_shl) for details. #[inline] pub(crate) fn overflowing_shl_big(self, rhs: Self) -> (Self, bool) { - if BITS == 0 { - return (Self::ZERO, false); - } let Ok(rhs) = u64::try_from(rhs) else { return (Self::ZERO, true); }; @@ -433,9 +427,6 @@ impl Uint { /// See [`overflowing_shr`](Self::overflowing_shr) for details. #[inline] pub(crate) fn overflowing_shr_big(self, rhs: Self) -> (Self, bool) { - if BITS == 0 { - return (Self::ZERO, false); - } let Ok(rhs) = u64::try_from(rhs) else { return (Self::ZERO, true); }; @@ -465,9 +456,6 @@ impl Uint { #[inline] #[must_use] pub const fn arithmetic_shr(self, rhs: usize) -> Self { - if BITS == 0 { - return Self::ZERO; - } let sign = self.bit(BITS - 1); let mut r = self.wrapping_shr(rhs); if sign { @@ -482,9 +470,6 @@ impl Uint { #[inline] #[must_use] pub const fn rotate_left(self, rhs: usize) -> Self { - if BITS == 0 { - return Self::ZERO; - } let rhs = rhs % BITS; // (self << rhs) | (self >> (BITS - rhs)) self.wrapping_shl(rhs).bitor(self.wrapping_shr(BITS - rhs)) @@ -495,9 +480,6 @@ impl Uint { #[inline(always)] #[must_use] pub const fn rotate_right(self, rhs: usize) -> Self { - if BITS == 0 { - return Self::ZERO; - } let rhs = rhs % BITS; self.rotate_left(BITS - rhs) } @@ -764,7 +746,6 @@ mod tests { #[test] fn test_leading_zeros() { - assert_eq!(Uint::<0, 0>::ZERO.leading_zeros(), 0); assert_eq!(Uint::<1, 1>::ZERO.leading_zeros(), 1); assert_eq!(Uint::<1, 1>::ONE.leading_zeros(), 0); const_for!(BITS in NON_ZERO { @@ -802,7 +783,6 @@ mod tests { #[test] fn test_leading_ones() { - assert_eq!(Uint::<0, 0>::ZERO.leading_ones(), 0); assert_eq!(Uint::<1, 1>::ZERO.leading_ones(), 0); assert_eq!(Uint::<1, 1>::ONE.leading_ones(), 1); } diff --git a/src/bytes.rs b/src/bytes.rs index f6a4261d..6863d5ff 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -505,7 +505,6 @@ mod tests { assert!(matches!(K.to_be_bytes::<{ KBE.len() }>(), KBE)); assert!(matches!(K.to_le_bytes::<{ KLE.len() }>(), KLE)); - assert!(matches!(Uint::<0, 0>::ZERO.to_be_bytes::<0>(), [])); assert!(matches!(Uint::<1, 1>::ZERO.to_be_bytes::<1>(), [0])); assert!(matches!( Uint::<1, 1>::from_limbs([1]).to_be_bytes::<1>(), @@ -516,8 +515,6 @@ mod tests { [0x12, 0x34] )); - assert!(matches!(Uint::<0, 0>::ZERO.to_be_bytes::<0>(), [])); - assert!(matches!(Uint::<0, 0>::ZERO.to_le_bytes::<0>(), [])); assert!(matches!(Uint::<1, 1>::ZERO.to_be_bytes::<1>(), [0])); assert!(matches!(Uint::<1, 1>::ZERO.to_le_bytes::<1>(), [0])); assert!(matches!( @@ -549,8 +546,6 @@ mod tests { #[test] fn test_from_bytes() { - assert_eq!(Uint::<0, 0>::from_be_bytes([]), Uint::ZERO); - assert_eq!(Uint::<0, 0>::from_le_bytes([]), Uint::ZERO); assert_eq!( Uint::<12, 1>::from_be_bytes([0x01, 0x23]), Uint::from(0x0123) @@ -597,8 +592,6 @@ mod tests { #[test] fn test_to_bytes() { - assert_eq!(Uint::<0, 0>::ZERO.to_le_bytes(), [0_u8; 0]); - assert_eq!(Uint::<0, 0>::ZERO.to_be_bytes(), [0_u8; 0]); assert_eq!(Uint::<12, 1>::from(0x0123_u64).to_le_bytes(), [0x23, 0x01]); assert_eq!(Uint::<12, 1>::from(0x0123_u64).to_be_bytes(), [0x01, 0x23]); assert_eq!(Uint::<16, 1>::from(0x1234_u64).to_le_bytes(), [0x34, 0x12]); diff --git a/src/cmp.rs b/src/cmp.rs index 6d114275..e54bfe15 100644 --- a/src/cmp.rs +++ b/src/cmp.rs @@ -123,7 +123,6 @@ mod tests { #[test] fn test_is_zero() { - assert!(Uint::<0, 0>::ZERO.is_zero()); assert!(Uint::<1, 1>::ZERO.is_zero()); assert!(Uint::<7, 1>::ZERO.is_zero()); assert!(Uint::<64, 1>::ZERO.is_zero()); diff --git a/src/const_for.rs b/src/const_for.rs index a6f204dd..b994d3c1 100644 --- a/src/const_for.rs +++ b/src/const_for.rs @@ -4,7 +4,7 @@ /// /// ```rust /// # use ruint::{const_for, nlimbs, Uint}; -/// const_for!(BITS in [0, 10, 100] { +/// const_for!(BITS in [10, 100] { /// const LIMBS: usize = nlimbs(BITS); /// println!("{:?}", Uint::::MAX); /// }); @@ -14,19 +14,17 @@ /// /// ```rust /// # use ruint::{const_for, Uint}; -/// println!("{:?}", Uint::<0, 0>::MAX); /// println!("{:?}", Uint::<10, 1>::MAX); /// println!("{:?}", Uint::<100, 2>::MAX); /// ``` /// -/// It comes with two built-in lists: `NON_ZERO` which is equivalent to +/// It comes with two built-in lists, `SIZES` and `NON_ZERO` (which are +/// currently equivalent), defined as /// /// ```text /// [1, 2, 63, 64, 65, 127, 128, 129, 256, 384, 512, 4096] /// ``` /// -/// and `SIZES` which is the same but also has `0` as a value. -/// /// In combination with [`proptest!`][proptest::proptest] this allows for /// testing over a large range of [`Uint`][crate::Uint] types and values: /// @@ -49,7 +47,6 @@ macro_rules! const_for { })* }; ($C:ident in SIZES $x:block) => { - $crate::const_for!($C in [0] $x); $crate::const_for!($C in NON_ZERO $x); }; ($C:ident in NON_ZERO $x:block) => { diff --git a/src/from.rs b/src/from.rs index e92e8eb9..469e5160 100644 --- a/src/from.rs +++ b/src/from.rs @@ -128,7 +128,7 @@ impl Uint { /// Saturates at the maximum value of the [`Uint`] if the value is too /// large. pub(crate) const fn const_from_u64(x: u64) -> Self { - if BITS == 0 || (BITS < 64 && x >= 1 << BITS) { + if BITS < 64 && x >= 1 << BITS { return Self::MAX; } let mut limbs = [0; LIMBS]; @@ -603,12 +603,8 @@ impl TryFrom for Uint { // Positive and exponent indicates |value| < 1 if exponent < exponent_bias { - return if BITS == 0 { - Err(ToUintError::ValueTooLarge(BITS, Self::ZERO)) - } else { - // We already handled value < 0.5 above; here 0.5 <= value < 1.0 → 1. - Ok(Self::ONE) - }; + // We already handled value < 0.5 above; here 0.5 <= value < 1.0 → 1. + return Ok(Self::ONE); } exponent -= exponent_bias; @@ -636,11 +632,7 @@ impl TryFrom for Uint { // Match old impl: if rounding bumps us across 2^BITS (only possible when // exponent == BITS - 1), report ValueTooLarge with the wrapped payload. - if sign == Sign::Positive - && fixint_bits > 0 - && exponent == fixint_bits - 1 - && r == Self::ZERO - { + if sign == Sign::Positive && exponent == fixint_bits - 1 && r == Self::ZERO { return Err(ToUintError::ValueTooLarge(BITS, r)); } @@ -687,9 +679,6 @@ impl TryFrom<&Uint> for bool #[inline] fn try_from(value: &Uint) -> Result { - if BITS == 0 { - return Ok(false); - } if value.gt_u64_max() || value.limbs[0] > 1 { return Err(Self::Error::Overflow(BITS, value.bit(0), true)); } @@ -707,9 +696,6 @@ macro_rules! to_int { #[inline] #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)] fn try_from(value: &Uint) -> Result { - if BITS == 0 { - return Ok(0); - } if value.gt_u64_max() || value.limbs[0] > (Self::MAX as u64) { return Err(Self::Error::Overflow( BITS, @@ -876,11 +862,6 @@ mod test { #[test] fn test_u64() { - assert_eq!(Uint::<0, 0>::try_from(0_u64), Ok(Uint::ZERO)); - assert_eq!( - Uint::<0, 0>::try_from(1_u64), - Err(ToUintError::ValueTooLarge(0, Uint::ZERO)) - ); const_for!(BITS in NON_ZERO { const LIMBS: usize = nlimbs(BITS); assert_eq!(Uint::::try_from(0_u64), Ok(Uint::ZERO)); @@ -929,7 +910,6 @@ mod test { #[test] fn test_f64() { - assert_eq!(Uint::<0, 0>::try_from(0.0_f64), Ok(Uint::ZERO)); const_for!(BITS in NON_ZERO { const LIMBS: usize = nlimbs(BITS); assert_eq!(Uint::::try_from(0.0_f64), Ok(Uint::ZERO)); diff --git a/src/lib.rs b/src/lib.rs index 780125cc..867ace8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -154,6 +154,7 @@ pub struct Uint { impl Uint { /// The size of this integer type in 64-bit limbs. pub const LIMBS: usize = { + assert!(BITS > 0, "Can not construct Uint<0, 0>"); let limbs = nlimbs(BITS); assert!( LIMBS == limbs, @@ -165,7 +166,7 @@ impl Uint { /// Bit mask for the last limb. pub const MASK: u64 = mask(BITS); - const SHOULD_MASK: bool = BITS > 0 && Self::MASK != u64::MAX; + const SHOULD_MASK: bool = Self::MASK != u64::MAX; /// The size of this integer type in bits. pub const BITS: usize = BITS; @@ -175,8 +176,6 @@ impl Uint { pub const ZERO: Self = Self::from_limbs([0; LIMBS]); /// The value one. This is useful to have as a constant for use in const fn. - /// - /// Zero if `BITS` is zero. pub const ONE: Self = Self::const_from_u64(1); /// The smallest value that can be represented by this integer type. @@ -380,7 +379,6 @@ mod test { #[test] fn test_max() { - assert_eq!(Uint::<0, 0>::MAX, Uint::ZERO); assert_eq!(Uint::<1, 1>::MAX, Uint::from_limbs([1])); assert_eq!(Uint::<7, 1>::MAX, Uint::from_limbs([127])); assert_eq!(Uint::<64, 1>::MAX, Uint::from_limbs([u64::MAX])); diff --git a/src/modular.rs b/src/modular.rs index 1beccaca..b3925617 100644 --- a/src/modular.rs +++ b/src/modular.rs @@ -113,7 +113,7 @@ impl Uint { #[inline] #[must_use] pub fn pow_mod(mut self, mut exp: Self, modulus: Self) -> Self { - if BITS == 0 || modulus <= Self::ONE { + if modulus <= Self::ONE { return Self::ZERO; } @@ -184,9 +184,6 @@ impl Uint { #[inline] #[must_use] pub fn mul_redc(self, other: Self, modulus: Self, inv: u64) -> Self { - if BITS == 0 { - return Self::ZERO; - } let result = algorithms::mul_redc(self.limbs, other.limbs, modulus.limbs, inv); let result = Self::from_limbs(result); debug_assert!(result < modulus); @@ -199,9 +196,6 @@ impl Uint { #[inline] #[must_use] pub fn square_redc(self, modulus: Self, inv: u64) -> Self { - if BITS == 0 { - return Self::ZERO; - } let result = algorithms::square_redc(self.limbs, modulus.limbs, inv); let result = Self::from_limbs(result); debug_assert!(result < modulus); diff --git a/src/mul.rs b/src/mul.rs index 6d4db25b..b15e66f1 100644 --- a/src/mul.rs +++ b/src/mul.rs @@ -72,7 +72,7 @@ impl Uint { #[inline] #[must_use] pub fn inv_ring(self) -> Option { - if BITS == 0 || self.limbs[0] & 1 == 0 { + if self.limbs[0] & 1 == 0 { return None; } @@ -118,7 +118,6 @@ impl Uint { /// ``` /// # use ruint::{Uint, uint}; /// # uint!{ - /// assert_eq!(0_U0.widening_mul(0_U0), 0_U0); /// assert_eq!(1_U1.widening_mul(1_U1), 1_U2); /// assert_eq!(3_U2.widening_mul(7_U3), 21_U5); /// # } @@ -139,9 +138,7 @@ impl Uint { assert_eq!(LIMBS_RES, nlimbs(BITS_RES)); let mut result = Uint::::ZERO; algorithms::addmul(&mut result.limbs, self.as_limbs(), rhs.as_limbs()); - if LIMBS_RES > 0 { - debug_assert!(result.limbs[LIMBS_RES - 1] <= Uint::::MASK); - } + debug_assert!(result.limbs[LIMBS_RES - 1] <= Uint::::MASK); result } @@ -153,9 +150,6 @@ impl Product for Uint where I: Iterator, { - if BITS == 0 { - return Self::ZERO; - } iter.fold(Self::ONE, Self::wrapping_mul) } } @@ -166,9 +160,6 @@ impl<'a, const BITS: usize, const LIMBS: usize> Product<&'a Self> for Uint, { - if BITS == 0 { - return Self::ZERO; - } iter.copied().fold(Self::ONE, Self::wrapping_mul) } } diff --git a/src/pow.rs b/src/pow.rs index 084e9329..806889b8 100644 --- a/src/pow.rs +++ b/src/pow.rs @@ -39,7 +39,6 @@ impl Uint { /// ``` /// # use ruint::{Uint, uint}; /// # uint!{ - /// assert_eq!(0_U0.overflowing_pow(0_U0), (0_U0, false)); /// assert_eq!(0_U1.overflowing_pow(0_U1), (1_U1, false)); /// assert_eq!(0_U1.overflowing_pow(1_U1), (0_U1, false)); /// assert_eq!(1_U1.overflowing_pow(0_U1), (1_U1, false)); @@ -49,10 +48,6 @@ impl Uint { #[inline] #[must_use] pub fn overflowing_pow(mut self, mut exp: Self) -> (Self, bool) { - if BITS == 0 { - return (self, false); - } - // Exponentiation by squaring let mut overflow = false; let mut base_overflow = false; @@ -95,10 +90,6 @@ impl Uint { #[inline] #[must_use] pub fn wrapping_pow(mut self, mut exp: Self) -> Self { - if BITS == 0 { - return self; - } - // Exponentiation by squaring let mut result = Self::ONE; while !exp.is_zero() { diff --git a/src/root.rs b/src/root.rs index 8fca5efc..39ef9dc8 100644 --- a/src/root.rs +++ b/src/root.rs @@ -30,7 +30,7 @@ impl Uint { pub fn root(self, degree: usize) -> Self { assert!(degree > 0, "degree must be greater than zero"); - // Handle zero case (including BITS == 0). + // Handle zero case. if self.is_zero() { return Self::ZERO; } diff --git a/src/special.rs b/src/special.rs index 42069553..9d6e26d6 100644 --- a/src/special.rs +++ b/src/special.rs @@ -107,7 +107,6 @@ impl Uint { /// ``` /// # use ruint::{Uint, uint}; /// # uint!{ - /// assert_eq!(0_U0.checked_next_multiple_of(0_U0), None); /// assert_eq!(0_U1.checked_next_multiple_of(0_U1), None); /// assert_eq!(0_U1.checked_next_multiple_of(1_U1), Some(0_U1)); /// assert_eq!(1_U1.checked_next_multiple_of(0_U1), None); diff --git a/src/support/alloy_rlp.rs b/src/support/alloy_rlp.rs index 136ecce3..616b357a 100644 --- a/src/support/alloy_rlp.rs +++ b/src/support/alloy_rlp.rs @@ -116,10 +116,7 @@ unsafe impl MaxEncodedLenAssoc for Uint - assert_eq!(encode(U0::from(0))[..], hex!("80")); assert_eq!(encode(U256::from(0))[..], hex!("80")); assert_eq!(encode(U256::from(15))[..], hex!("0f")); assert_eq!(encode(U256::from(1024))[..], hex!("820400")); diff --git a/src/support/bincode_2.rs b/src/support/bincode_2.rs index dbaae886..ce12841e 100644 --- a/src/support/bincode_2.rs +++ b/src/support/bincode_2.rs @@ -12,10 +12,6 @@ use bincode_2::{ impl Encode for Uint { fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { - if BITS == 0 { - return Ok(()); - } - #[cfg(target_endian = "little")] return Encode::encode(self.as_le_slice(), encoder); @@ -39,9 +35,6 @@ impl Encode for Uint { impl Decode for Uint { fn decode>(decoder: &mut D) -> Result { - if BITS == 0 { - return Ok(Self::ZERO); - } let len = decode_slice_len(decoder)?; if len != Self::BYTES { return Err(DecodeError::ArrayLengthMismatch { @@ -68,9 +61,6 @@ impl<'de, Context, const BITS: usize, const LIMBS: usize> BorrowDecode<'de, Cont fn borrow_decode>( decoder: &mut D, ) -> Result { - if BITS == 0 { - return Ok(Self::ZERO); - } let bytes: &'de [u8] = BorrowDecode::borrow_decode(decoder)?; if bytes.len() != Self::BYTES { return Err(DecodeError::ArrayLengthMismatch { diff --git a/src/support/fastrlp_03.rs b/src/support/fastrlp_03.rs index 7791d111..89cfb7ff 100644 --- a/src/support/fastrlp_03.rs +++ b/src/support/fastrlp_03.rs @@ -123,10 +123,7 @@ unsafe impl MaxEncodedLenAssoc for Uint - assert_eq!(encode(U0::from(0))[..], hex!("80")); assert_eq!(encode(U256::from(0))[..], hex!("80")); assert_eq!(encode(U256::from(15))[..], hex!("0f")); assert_eq!(encode(U256::from(1024))[..], hex!("820400")); diff --git a/src/support/fastrlp_04.rs b/src/support/fastrlp_04.rs index 3f439139..794cfdca 100644 --- a/src/support/fastrlp_04.rs +++ b/src/support/fastrlp_04.rs @@ -123,10 +123,7 @@ unsafe impl MaxEncodedLenAssoc for Uint - assert_eq!(encode(U0::from(0))[..], hex!("80")); assert_eq!(encode(U256::from(0))[..], hex!("80")); assert_eq!(encode(U256::from(15))[..], hex!("0f")); assert_eq!(encode(U256::from(1024))[..], hex!("820400")); diff --git a/src/support/postgres.rs b/src/support/postgres.rs index d1d8f4e4..79cf59ee 100644 --- a/src/support/postgres.rs +++ b/src/support/postgres.rs @@ -100,32 +100,23 @@ impl ToSql for Uint { Type::BYTEA => out.put_slice(&self.to_be_bytes_vec()), Type::BIT | Type::VARBIT => { // Bit in little-endian so the the first bit is the least significant. - // Length must be at least one bit. - if BITS == 0 { - if *ty == Type::BIT { - // `bit(0)` is not a valid type, but varbit can be empty. - return Err(Box::new(WrongType::new::(ty.clone()))); - } - out.put_i32(0); - } else { - // Bits are output in big-endian order, but padded at the - // least significant end. - let padding = 8 - rem_up(BITS, 8); - out.put_i32(Self::BITS.try_into()?); - let bytes = self.as_le_bytes(); - let mut bytes = bytes.iter().rev(); - let mut shifted = bytes.next().unwrap() << padding; - for byte in bytes { - shifted |= if padding > 0 { - byte >> (8 - padding) - } else { - 0 - }; - out.put_u8(shifted); - shifted = byte << padding; - } + // Bits are output in big-endian order, but padded at the + // least significant end. + let padding = 8 - rem_up(BITS, 8); + out.put_i32(Self::BITS.try_into()?); + let bytes = self.as_le_bytes(); + let mut bytes = bytes.iter().rev(); + let mut shifted = bytes.next().unwrap() << padding; + for byte in bytes { + shifted |= if padding > 0 { + byte >> (8 - padding) + } else { + 0 + }; out.put_u8(shifted); + shifted = byte << padding; } + out.put_u8(shifted); } // Hex strings @@ -447,11 +438,7 @@ mod tests { // Fetch ground truth value from Postgres let expr = match *ty { - Type::BIT => format!( - "B'{value:b}'::bit({bits})", - value = value, - bits = if BITS == 0 { 1 } else { BITS }, - ), + Type::BIT => format!("B'{value:b}'::bit({BITS})"), Type::VARBIT => format!("B'{value:b}'::varbit"), Type::BYTEA => format!("'\\x{value:x}'::bytea"), Type::CHAR => format!("'{value:#x}'::char({})", 2 + 2 * nbytes(BITS)), diff --git a/src/support/pyo3.rs b/src/support/pyo3.rs index b0448f77..dbf83402 100644 --- a/src/support/pyo3.rs +++ b/src/support/pyo3.rs @@ -132,7 +132,7 @@ impl<'a, const BITS: usize, const LIMBS: usize> FromPyObject<'a> for Uint| { let obj = (-1_i64).into_pyobject(py).unwrap(); - assert!(U0::extract_bound(&obj).is_err()); assert!(U256::extract_bound(&obj).is_err()); let obj = (1000_i64).into_pyobject(py).unwrap(); - assert!(U0::extract_bound(&obj).is_err()); assert!(U8::extract_bound(&obj).is_err()); let obj = U512::MAX.into_pyobject(py).unwrap(); - assert!(U0::extract_bound(&obj).is_err()); assert!(U64::extract_bound(&obj).is_err()); assert!(U256::extract_bound(&obj).is_err()); }); diff --git a/src/support/rlp.rs b/src/support/rlp.rs index 4f7f11c4..5dc44b5a 100644 --- a/src/support/rlp.rs +++ b/src/support/rlp.rs @@ -65,7 +65,7 @@ fn trim_leading_zeros(bytes: &[u8]) -> &[u8] { mod test { use super::*; use crate::{ - aliases::{B160, U0, U256}, + aliases::{B160, U256}, const_for, nlimbs, }; use hex_literal::hex; @@ -74,7 +74,6 @@ mod test { #[test] fn test_uint_rlp() { // See - assert_eq!(U0::from(0).rlp_bytes()[..], hex!("80")); assert_eq!(U256::from(0).rlp_bytes()[..], hex!("80")); assert_eq!(U256::from(15).rlp_bytes()[..], hex!("0f")); assert_eq!(U256::from(1024).rlp_bytes()[..], hex!("820400")); diff --git a/src/support/serde.rs b/src/support/serde.rs index 8b8d0303..e14a7bd7 100644 --- a/src/support/serde.rs +++ b/src/support/serde.rs @@ -10,8 +10,7 @@ use serde_core::{ de::{Error, Unexpected, Visitor}, }; -/// Canonical serialization for all human-readable instances of `Uint<0, 0>`, -/// and minimal human-readable `Uint::ZERO` for any bit size. +/// Minimal human-readable `Uint::ZERO` for any bit size. const ZERO_STR: &str = "0x0"; impl Uint { @@ -38,9 +37,7 @@ impl Uint { } fn write_hex(&self, s: &mut (impl fmt::Write + ?Sized)) { - if BITS == 0 { - s.write_str(ZERO_STR) - } else if FULL { + if FULL { write!(s, "{:#0w$x}", *self, w = 2 + Self::BYTES * 2) } else { write!(s, "{:#x}", *self) @@ -119,11 +116,6 @@ impl Visitor<'_> for HrVisitor::ZERO); } - // `ZERO_STR` is the only valid serialization of `Uint<0, 0>`, so if we - // have not shortcut, we are in an error case - if BITS == 0 { - return Err(Error::invalid_value(Unexpected::Str(value), &self)); - } value .parse()