smallint/src/smallint.rs

70 lines
2.3 KiB
Rust

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 2<sup>32</sup> 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 2<sup>32</sup> 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)))
}
}
}
}