use core::mem::ManuallyDrop;
/// An integer-like type that will store small integers up to `i128` inline. Larger integers are
/// represented as a slice to a sequence of base 232 digits represented as a `*mut u32`.
pub struct SmallInt(pub(crate) SmallIntType);
/// An integer-like type that will store small integers up to `u128` inline. Larger integers are
/// represented as a slice to a sequence of base 232 digits represented as a `*mut u32`.
pub struct SmallUint(pub(crate) SmallUintType);
pub enum SmallIntType {
    Inline(i128),
    Heap((*mut u32, isize)),
}
pub enum SmallUintType {
    Inline(u128),
    Heap((*mut u32, usize)),
}
impl Drop for SmallInt {
    fn drop(&mut self) {
        if let Self(SmallIntType::Heap((r, s))) = self {
            let size = usize::try_from(s.abs()).unwrap();
            let slice = unsafe { core::slice::from_raw_parts_mut(*r, size) };
            unsafe { std::mem::drop(Box::from_raw(slice)) }
        }
    }
}
impl Drop for SmallUint {
    fn drop(&mut self) {
        if let Self(SmallUintType::Heap((r, s))) = self {
            let slice = unsafe { core::slice::from_raw_parts_mut(*r, *s) };
            unsafe { std::mem::drop(Box::from_raw(slice)) }
        }
    }
}
impl Clone for SmallUint {
    fn clone(&self) -> Self {
        match self.0 {
            SmallUintType::Inline(i) => Self(SmallUintType::Inline(i)),
            SmallUintType::Heap((r, s)) => {
                let slice = unsafe { core::slice::from_raw_parts(r, s) };
                let mut ret = vec![0; s];
                ret.clone_from_slice(slice);
                let mut val = ManuallyDrop::new(ret.into_boxed_slice());
                SmallUint(SmallUintType::Heap((val.as_mut_ptr(), s)))
            }
        }
    }
}
impl Clone for SmallInt {
    fn clone(&self) -> Self {
        match self.0 {
            SmallIntType::Inline(i) => Self(SmallIntType::Inline(i)),
            SmallIntType::Heap((r, s)) => {
                let size = usize::try_from(s.abs()).unwrap();
                let slice = unsafe { core::slice::from_raw_parts(r, size) };
                let mut ret = vec![0; size];
                ret.clone_from_slice(slice);
                let mut val = ManuallyDrop::new(ret.into_boxed_slice());
                SmallInt(SmallIntType::Heap((val.as_mut_ptr(), s)))
            }
        }
    }
}