#![cfg(feature = "num-bigint")]
use num_bigint::BigInt;
use num_bigint::BigUint;
use num_bigint::Sign;
use core::mem::ManuallyDrop;
use crate::SmallInt;
use crate::SmallUint;
use crate::smallint::SmallIntType;
use crate::smallint::SmallUintType;
impl From<&BigInt> for SmallInt {
fn from(b: &BigInt) -> Self {
match b.try_into() {
Ok(i) => Self(SmallIntType::Inline(i)),
Err(_) => {
let (sign, vec) = b.to_u32_digits();
let mut slice = ManuallyDrop::new(vec.into_boxed_slice());
let size = match sign {
Sign::Minus => -isize::try_from(slice.len()).unwrap(),
Sign::NoSign => panic!(
"Shouldn't happen; BigInts which store zero should convert to inline."
),
Sign::Plus => isize::try_from(slice.len()).unwrap(),
};
Self(SmallIntType::Heap((slice.as_mut_ptr(), size)))
}
}
}
}
impl From<&SmallInt> for BigInt {
fn from(s: &SmallInt) -> Self {
match s.0 {
SmallIntType::Inline(i) => Self::from(i),
SmallIntType::Heap((r, s)) => {
let size = usize::try_from(s.abs()).unwrap();
let sign = s.signum();
let slice = unsafe { core::slice::from_raw_parts(r, size) };
let bs = match sign {
0 => Sign::NoSign,
-1 => Sign::Minus,
1 => Sign::Plus,
_ => panic!("This shouldn't happen; There are only 3 signums."),
};
BigInt::new(bs, slice.to_vec())
}
}
}
}
impl From<&BigUint> for SmallUint {
fn from(b: &BigUint) -> Self {
match b.try_into() {
Ok(i) => Self(SmallUintType::Inline(i)),
Err(_) => {
let vec = b.to_u32_digits();
let mut slice = ManuallyDrop::new(vec.into_boxed_slice());
let size = slice.len();
Self(SmallUintType::Heap((slice.as_mut_ptr(), size)))
}
}
}
}
impl From<&SmallUint> for BigUint {
fn from(s: &SmallUint) -> Self {
match s.0 {
SmallUintType::Inline(i) => Self::from(i),
SmallUintType::Heap((r, s)) => {
let slice = unsafe { core::slice::from_raw_parts(r, s) };
BigUint::new(slice.to_vec())
}
}
}
}