From a5620cdda95ea56b57fc5a9ae01c7e76e01d5af5 Mon Sep 17 00:00:00 2001 From: EvilMuffinHa Date: Tue, 2 Aug 2022 03:41:25 -0400 Subject: [PATCH] fix drop --- src/lib.rs | 66 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fd58eb9..60762a2 100644 --- a/src/lib.rs +++ b/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 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 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 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])); } + }