mirror of
https://gitlab.com/artofrev/smallint.git
synced 2024-12-04 09:01:39 -05:00
fix drop
This commit is contained in:
parent
c5e952d7d7
commit
a5620cdda9
66
src/lib.rs
66
src/lib.rs
|
@ -1,3 +1,6 @@
|
|||
#![deny(missing_docs)]
|
||||
#![warn(clippy::all)]
|
||||
|
||||
//! A crate for small integer optimization. Provides the [`SmallInt`] type. When possible this will
|
||||
//! inline an integer and store it on the stack if that integer is small. However, for larger values,
|
||||
//! this will be instead stored on the heap as a pointer to a `u32` slice, a length, and a sign.
|
||||
|
@ -15,8 +18,8 @@ pub enum SmallIntError {
|
|||
|
||||
impl std::error::Error for SmallIntError {}
|
||||
|
||||
impl std::fmt::Display for SmallIntError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
impl core::fmt::Display for SmallIntError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let Self::ConversionError = self;
|
||||
write!(f, "Error converting integer to SmallInt.")
|
||||
}
|
||||
|
@ -37,7 +40,18 @@ pub enum SmallInt {
|
|||
Heap((*mut u32, isize))
|
||||
}
|
||||
|
||||
impl Drop for SmallInt {
|
||||
fn drop(&mut self) {
|
||||
if let Self::Heap((r, s)) = self {
|
||||
let size = usize::try_from(s.abs()).unwrap();
|
||||
let mut slice = unsafe { core::slice::from_raw_parts(r, size) };
|
||||
unsafe {
|
||||
core::ptr::drop_in_place(&mut slice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
macro_rules! int_impl {
|
||||
($itype:ty) => {
|
||||
|
@ -102,7 +116,7 @@ impl TryFrom<SmallInt> for u128 {
|
|||
let mut ret: u128 = 0;
|
||||
let mut bits = 0;
|
||||
let size = usize::try_from(s.abs()).unwrap();
|
||||
let slice = unsafe { std::slice::from_raw_parts(r, size) };
|
||||
let slice = unsafe { core::slice::from_raw_parts(r, size) };
|
||||
for i in slice {
|
||||
if bits >= 128 {
|
||||
return Err(SmallIntError::ConversionError);
|
||||
|
@ -144,7 +158,7 @@ impl From<SmallInt> for BigInt {
|
|||
SmallInt::Heap((r, s)) => {
|
||||
let size = usize::try_from(s.abs()).unwrap();
|
||||
let sign = s.signum();
|
||||
let slice = unsafe { std::slice::from_raw_parts(r, size) };
|
||||
let slice = unsafe { core::slice::from_raw_parts(r, size) };
|
||||
let bs = match sign {
|
||||
0 => Sign::NoSign,
|
||||
-1 => Sign::Minus,
|
||||
|
@ -162,27 +176,41 @@ impl From<SmallInt> for BigInt {
|
|||
mod conversion_tests {
|
||||
|
||||
use crate::SmallInt;
|
||||
use num_bigint::{BigInt, Sign};
|
||||
|
||||
#[test]
|
||||
fn test_u8() {
|
||||
let i = u8::MAX;
|
||||
let s = SmallInt::from(i);
|
||||
assert_eq!(u8::try_from(s).unwrap(), i);
|
||||
macro_rules! conversion_tests {
|
||||
($t:ty, $i:ident) => {
|
||||
#[test]
|
||||
fn $i() {
|
||||
let i = <$t>::MAX;
|
||||
let s = SmallInt::from(i);
|
||||
assert_eq!(<$t>::try_from(s).unwrap(), i);
|
||||
|
||||
let i = u8::MIN;
|
||||
let s = SmallInt::from(i);
|
||||
assert_eq!(u8::try_from(s).unwrap(), i);
|
||||
let i = <$t>::MIN;
|
||||
let s = SmallInt::from(i);
|
||||
assert_eq!(<$t>::try_from(s).unwrap(), i);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_i8() {
|
||||
let i = i8::MIN;
|
||||
let s = SmallInt::from(i);
|
||||
assert_eq!(i8::try_from(s).unwrap(), i);
|
||||
conversion_tests!(u8, test_u8);
|
||||
conversion_tests!(i8, test_i8);
|
||||
conversion_tests!(u16, test_u16);
|
||||
conversion_tests!(i16, test_i16);
|
||||
conversion_tests!(u32, test_u32);
|
||||
conversion_tests!(i32, test_i32);
|
||||
conversion_tests!(u64, test_u64);
|
||||
conversion_tests!(i64, test_i64);
|
||||
conversion_tests!(u128, test_u128);
|
||||
conversion_tests!(i128, test_i128);
|
||||
|
||||
let i = i8::MAX;
|
||||
#[test]
|
||||
fn test_bigint() {
|
||||
let i = BigInt::new(Sign::Plus, vec![5, 4, 8, 3, 2, 9, 3]);
|
||||
let s = SmallInt::from(i);
|
||||
assert_eq!(i8::try_from(s).unwrap(), i);
|
||||
assert_eq!(BigInt::from(s).to_u32_digits(), (Sign::Plus, vec![5, 4, 8, 3, 2, 9, 3]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user