mod consts;
mod bigint_helpers;
mod bits;
mod bytes;
pub mod cast;
mod checked;
mod cmp;
mod convert;
mod div;
#[cfg(feature = "alloc")]
mod fmt;
mod math;
mod mul;
#[cfg(feature = "numtraits")]
mod numtraits;
mod ops;
mod overflowing;
mod radix;
#[cfg(feature = "rand")]
mod random;
mod saturating;
mod strict;
mod unchecked;
mod wrapping;
mod const_trait_fillers;
use crate::Byte;
use crate::digits::Digits;
use crate::OverflowMode;
use crate::doc;
#[cfg(feature = "serde")]
use ::{
serde::{Deserialize, Serialize},
serde_big_array::BigArray,
};
#[cfg(feature = "borsh")]
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use core::default::Default;
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "borsh",
derive(BorshSerialize, BorshDeserialize, BorshSchema)
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "valuable", derive(valuable::Valuable))]
#[repr(transparent)]
pub struct Integer<const S: bool, const N: usize, const B: usize = 0, const OM: u8 = {OverflowMode::DEFAULT as u8}> {
#[cfg_attr(feature = "serde", serde(with = "BigArray"))]
pub(crate) bytes: [Byte; N],
}
pub type Uint<const N: usize, const B: usize = 0, const OM: u8 = {OverflowMode::DEFAULT as u8}> = Integer<false, N, B, OM>;
pub type Int<const N: usize, const B: usize = 0, const OM: u8 = {OverflowMode::DEFAULT as u8}> = Integer<true, N, B, OM>;
#[cfg(feature = "zeroize")]
impl<const S: bool, const N: usize, const B: usize, const OM: u8> zeroize::DefaultIsZeroes for Integer<S, N, B, OM> {}
impl<const S: bool, const N: usize, const B: usize, const OM: u8> Integer<S, N, B, OM> {
pub(crate) const LAST_BYTE_BITS: u32 = if Self::BITS % Byte::BITS == 0 {
Byte::BITS as _
} else {
Self::BITS % Byte::BITS
};
pub(crate) const LAST_BYTE_PAD_BITS: u32 = Byte::BITS - Self::LAST_BYTE_BITS;
#[inline(always)]
const fn widen(self) -> Integer<S, N, 0, OM> {
self.force()
}
#[inline(always)]
const fn set_sign_bits(&mut self) {
self.set_pad_bits(self.is_negative_internal());
}
#[inline(always)]
const fn set_pad_bits(&mut self, value: bool) {
if Self::LAST_BYTE_PAD_BITS != 0 {
if value {
self.bytes[N - 1] |= Byte::MAX << Self::LAST_BYTE_BITS; } else {
self.bytes[N - 1] &= !(Byte::MAX << Self::LAST_BYTE_BITS); }
}
}
#[inline(always)]
const fn has_valid_pad_bits(&self) -> bool {
if Self::LAST_BYTE_BITS == 8 {
true
} else {
(self.bytes[N - 1] >> Self::LAST_BYTE_BITS) == 0
}
}
#[inline(always)]
pub(crate) const fn force_sign<const R: bool>(self) -> Integer<R, N, B, OM> {
let mut out = Integer::from_bytes(self.bytes);
if R != S {
out.set_sign_bits();
}
out
}
#[inline(always)]
pub(crate) const fn force<const R: bool, const A: usize, const RO: u8>(self) -> Integer<R, N, A, RO> {
let mut out = Integer::from_bytes(self.bytes);
if R != S {
out.set_sign_bits();
}
out
}
#[must_use]
#[inline(always)]
const fn from_byte(byte: Byte) -> Self {
let mut out = Self::ZERO;
out.bytes[0] = byte;
out
}
#[inline]
pub(crate) const fn as_digits<D>(&self) -> &Digits<D, N> {
Digits::from_integer_ref(&self)
}
#[inline]
pub(crate) const fn to_digits<D>(self) -> Digits<D, N> {
Digits::from_integer(self)
}
}
impl<const N: usize, const B: usize, const OM: u8> Int<N, B, OM> {
#[inline(always)]
pub(crate) const fn signed_digit(&self) -> i8 {
self.bytes[N - 1] as _
}
}
impl<const S: bool, const N: usize, const B: usize, const OM: u8> Default for Integer<S, N, B, OM> {
#[doc = doc::default!()]
#[inline]
fn default() -> Self {
Self::ZERO
}
}
#[cfg(any(test, feature = "quickcheck"))]
impl<const S: bool, const N: usize, const B: usize, const OM: u8> quickcheck::Arbitrary for Integer<S, N, B, OM> {
#[inline]
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
<Digits<u128, N> as quickcheck::Arbitrary>::arbitrary(g).to_integer()
}
}
#[cfg(all(test, not(feature = "alloc")))]
impl<const S: bool, const N: usize, const B: usize, const OM: u8> core::fmt::Debug for Integer<S, N, B, OM> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
for bytes in self.bytes.iter().rev() {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::cast::As;
crate::test::test_all! {
testing integers;
#[test]
fn default() {
assert_eq!(UTEST::default(), utest::default().as_());
}
}
}