use core::{
fmt,
hash::{Hash, Hasher},
num::NonZeroUsize,
ptr,
};
use awint_internals::*;
use const_fn::const_fn;
use crate::Bits;
#[repr(C)]
#[derive(Clone, Copy)] pub struct InlAwi<const BW: usize, const LEN: usize> {
_raw_stack_bits: RawStackBits<BW, LEN>,
}
unsafe impl<const BW: usize, const LEN: usize> Send for InlAwi<BW, LEN> {}
unsafe impl<const BW: usize, const LEN: usize> Sync for InlAwi<BW, LEN> {}
impl<'a, const BW: usize, const LEN: usize> InlAwi<BW, LEN> {
#[inline]
#[const_fn(cfg(feature = "const_support"))]
#[must_use]
pub(in crate::data) const fn internal_as_ref(&'a self) -> &'a Bits {
unsafe { Bits::from_raw_parts(self._raw_stack_bits.to_raw_bits()) }
}
#[inline]
#[const_fn(cfg(feature = "const_support"))]
#[must_use]
pub(in crate::data) const fn internal_as_mut(&'a mut self) -> &'a mut Bits {
unsafe { Bits::from_raw_parts_mut(self._raw_stack_bits.to_raw_bits_mut()) }
}
#[const_fn(cfg(feature = "const_support"))]
#[must_use]
pub const fn const_nzbw() -> NonZeroUsize {
RawStackBits::<BW, LEN>::nzbw()
}
#[const_fn(cfg(feature = "const_support"))]
#[must_use]
pub const fn const_bw() -> usize {
RawStackBits::<BW, LEN>::bw()
}
#[const_fn(cfg(feature = "const_support"))]
#[must_use]
pub const fn nzbw(&self) -> NonZeroUsize {
Self::const_nzbw()
}
#[const_fn(cfg(feature = "const_support"))]
#[must_use]
pub const fn bw(&self) -> usize {
Self::const_bw()
}
#[const_fn(cfg(feature = "const_support"))]
#[must_use]
pub const fn total_digits(&self) -> usize {
RawStackBits::<BW, LEN>::total_digits().get()
}
#[doc(hidden)]
#[const_fn(cfg(feature = "const_support"))]
pub const fn unstable_from_u8_slice(buf: &[u8]) -> Self {
let mut val = InlAwi {
_raw_stack_bits: RawStackBits::zero(),
};
let self_byte_width = val.total_digits() * DIGIT_BYTES;
let min_width = if self_byte_width < buf.len() {
self_byte_width
} else {
buf.len()
};
let start = min_width / DIGIT_BYTES;
unsafe {
ptr::copy_nonoverlapping(
buf.as_ptr(),
val.as_mut_bytes_full_width_nonportable().as_mut_ptr(),
min_width,
);
let cap = if start >= val.total_digits() {
val.total_digits()
} else {
start + 1
};
const_for!(i in {0..cap} {
*val.get_unchecked_mut(i) = Digit::from_le(val.get_unchecked(i));
});
}
val.clear_unused_bits();
val
}
#[const_fn(cfg(feature = "const_support"))]
pub const fn zero() -> Self {
Self {
_raw_stack_bits: RawStackBits::zero(),
}
}
#[const_fn(cfg(feature = "const_support"))]
pub const fn umax() -> Self {
let mut val = Self {
_raw_stack_bits: RawStackBits::all_set(),
};
val.const_as_mut().clear_unused_bits();
val
}
#[const_fn(cfg(feature = "const_support"))]
pub const fn imax() -> Self {
let mut val = Self::umax();
*val.const_as_mut().last_mut() = (MAX >> 1) >> val.unused();
val
}
#[const_fn(cfg(feature = "const_support"))]
pub const fn imin() -> Self {
let mut val = Self::zero();
*val.const_as_mut().last_mut() = (IDigit::MIN as Digit) >> val.unused();
val
}
#[const_fn(cfg(feature = "const_support"))]
pub const fn uone() -> Self {
let mut val = Self::zero();
*val.const_as_mut().first_mut() = 1;
val
}
#[doc(hidden)]
#[const_fn(cfg(feature = "const_support"))]
pub const fn assert_invariants(this: &Self) {
RawStackBits::<BW, LEN>::_assert_invariants();
this.assert_cleared_unused_bits();
}
}
impl<const BW: usize, const LEN: usize> PartialEq for InlAwi<BW, LEN> {
fn eq(&self, rhs: &Self) -> bool {
self.as_ref() == rhs.as_ref()
}
}
impl<const BW: usize, const LEN: usize> Eq for InlAwi<BW, LEN> {}
#[cfg(feature = "zeroize_support")]
impl<const BW: usize, const LEN: usize> zeroize::Zeroize for InlAwi<BW, LEN> {
fn zeroize(&mut self) {
self.as_mut().zeroize()
}
}
macro_rules! impl_fmt {
($($ty:ident)*) => {
$(
impl<const BW: usize, const LEN: usize> fmt::$ty for InlAwi<BW, LEN> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::$ty::fmt(self.as_ref(), f)
}
}
)*
};
}
impl_fmt!(Debug Display LowerHex UpperHex Octal Binary);
impl<const BW: usize, const LEN: usize> Hash for InlAwi<BW, LEN> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_ref().hash(state);
}
}
impl InlAwi<1, { Bits::unstable_raw_digits(1) }> {
#[const_fn(cfg(feature = "const_support"))]
pub const fn from_bool(x: bool) -> Self {
let mut val = Self::zero();
val.bool_(x);
val
}
}
macro_rules! inlawi_from {
($($w:expr, $u:ident $from_u:ident $u_:ident
$i:ident $from_i:ident $i_:ident);*;) => {
$(
impl InlAwi<$w, {Bits::unstable_raw_digits($w)}> {
#[const_fn(cfg(feature = "const_support"))]
pub const fn $from_u(x: $u) -> Self {
let mut val = Self::zero();
val.$u_(x);
val
}
#[const_fn(cfg(feature = "const_support"))]
pub const fn $from_i(x: $i) -> Self {
let mut val = Self::zero();
val.$i_(x);
val
}
}
)*
};
}
inlawi_from!(
8, u8 from_u8 u8_ i8 from_i8 i8_;
16, u16 from_u16 u16_ i16 from_i16 i16_;
32, u32 from_u32 u32_ i32 from_i32 i32_;
64, u64 from_u64 u64_ i64 from_i64 i64_;
128, u128 from_u128 u128_ i128 from_i128 i128_;
);
pub(crate) type UsizeInlAwi = InlAwi<{ USIZE_BITS }, { Bits::unstable_raw_digits(USIZE_BITS) }>;
impl UsizeInlAwi {
#[const_fn(cfg(feature = "const_support"))]
pub const fn from_usize(x: usize) -> Self {
let mut val = Self::zero();
val.usize_(x);
val
}
#[const_fn(cfg(feature = "const_support"))]
pub const fn from_isize(x: isize) -> Self {
let mut val = Self::zero();
val.isize_(x);
val
}
}
pub(crate) type DigitInlAwi = InlAwi<{ BITS }, { Bits::unstable_raw_digits(BITS) }>;
impl DigitInlAwi {
#[const_fn(cfg(feature = "const_support"))]
pub const fn from_digit(x: Digit) -> Self {
let mut val = Self::zero();
val.digit_(x);
val
}
}