use crate::smallint::SmallUintType; use crate::SmallUint; use core::mem::ManuallyDrop; use core::ops::{BitAnd, BitOr, BitXor}; use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign}; macro_rules! basic_op { ($imp:ident, $typ:ty, $fun:ident) => { impl<'a, 'b> $imp<&'a $typ> for &'b $typ { type Output = $typ; fn $fun(self, rhs: &$typ) -> Self::Output { $fun(self, rhs) } } impl<'a> $imp<$typ> for &'a $typ { type Output = $typ; fn $fun(self, rhs: $typ) -> Self::Output { self.$fun(&rhs) } } impl<'a> $imp<&'a $typ> for $typ { type Output = $typ; fn $fun(self, rhs: &$typ) -> Self::Output { (&self).$fun(rhs) } } impl $imp<$typ> for $typ { type Output = $typ; fn $fun(self, rhs: $typ) -> Self::Output { (&self).$fun(&rhs) } } }; } fn bitand(a: &SmallUint, b: &SmallUint) -> SmallUint { match (&a.0, &b.0) { (&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => { SmallUint(SmallUintType::Inline(i & j)) } (&SmallUintType::Inline(i), &SmallUintType::Heap((r, s))) | (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) => { let slice = unsafe { core::slice::from_raw_parts(r, s) }; let mut j = 0u128; for i in 0..4 { j <<= 32; j |= slice[3 - i] as u128; } SmallUint(SmallUintType::Inline(i & j)) } (&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => { let slice1 = unsafe { core::slice::from_raw_parts(r, s) }; let slice2 = unsafe { core::slice::from_raw_parts(i, j) }; let min = std::cmp::min(slice1.len(), slice2.len()); let mut res = Vec::with_capacity(min); for l in 0..min { res.push(slice1[l] & slice2[l]); } while res.len() != 1 && res[res.len() - 1] == 0 { res.pop(); } if res.len() <= 4 { let mut r = 0u128; for t in 0..res.len() { r <<= 32; r |= res[res.len() - 1 - t] as u128; } SmallUint(SmallUintType::Inline(r)) } else { let mut slice = ManuallyDrop::new(res.into_boxed_slice()); SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len()))) } } } } basic_op!(BitAnd, SmallUint, bitand); impl<'a> BitAndAssign<&'a SmallUint> for SmallUint { fn bitand_assign(&mut self, rhs: &'a SmallUint) { *self = self.clone() & rhs; } } impl BitAndAssign for SmallUint { fn bitand_assign(&mut self, rhs: SmallUint) { *self = self.clone() & rhs; } } fn bitor(a: &SmallUint, b: &SmallUint) -> SmallUint { match (&a.0, &b.0) { (&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => { SmallUint(SmallUintType::Inline(i | j)) } (&SmallUintType::Inline(i), &SmallUintType::Heap((r, s))) | (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) => { let slice = unsafe { core::slice::from_raw_parts(r, s) }; let mut retvec = slice.to_vec(); let mut v = i; #[allow(clippy::needless_range_loop)] for r in 0..4 { retvec[r] |= v as u32; v >>= 32; } let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice()); SmallUint(SmallUintType::Heap((retslice.as_mut_ptr(), retslice.len()))) } (&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => { let slice1 = unsafe { core::slice::from_raw_parts(r, s) }; let slice2 = unsafe { core::slice::from_raw_parts(i, j) }; let m = std::cmp::min(slice1.len(), slice2.len()); let mut retvec; if slice1.len() > slice2.len() { retvec = slice1.to_vec(); } else { retvec = slice2.to_vec(); } for t in 0..m { retvec[t] = slice1[t] | slice2[t]; } let mut slice = ManuallyDrop::new(retvec.into_boxed_slice()); SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len()))) } } } basic_op!(BitOr, SmallUint, bitor); impl<'a> BitOrAssign<&'a SmallUint> for SmallUint { fn bitor_assign(&mut self, rhs: &'a SmallUint) { *self = self.clone() | rhs; } } impl BitOrAssign for SmallUint { fn bitor_assign(&mut self, rhs: SmallUint) { *self = self.clone() | rhs; } } fn bitxor(a: &SmallUint, b: &SmallUint) -> SmallUint { match (&a.0, &b.0) { (&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => { SmallUint(SmallUintType::Inline(i ^ j)) } (&SmallUintType::Inline(i), &SmallUintType::Heap((r, s))) | (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) => { let slice = unsafe { core::slice::from_raw_parts(r, s) }; let mut retvec = slice.to_vec(); let mut v = i; #[allow(clippy::needless_range_loop)] for r in 0..4 { retvec[r] ^= v as u32; v >>= 32; } let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice()); SmallUint(SmallUintType::Heap((retslice.as_mut_ptr(), retslice.len()))) } (&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => { let slice1 = unsafe { core::slice::from_raw_parts(r, s) }; let slice2 = unsafe { core::slice::from_raw_parts(i, j) }; let m = std::cmp::min(slice1.len(), slice2.len()); let mut res; if slice1.len() > slice2.len() { res = slice1.to_vec(); } else { res = slice2.to_vec(); } for t in 0..m { res[t] = slice1[t] ^ slice2[t]; } while res.len() != 1 && res[res.len() - 1] == 0 { res.pop(); } if res.len() <= 4 { let mut r = 0u128; for t in 0..res.len() { r <<= 32; r |= res[res.len() - 1 - t] as u128; } SmallUint(SmallUintType::Inline(r)) } else { let mut slice = ManuallyDrop::new(res.into_boxed_slice()); SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len()))) } } } } basic_op!(BitXor, SmallUint, bitxor); impl<'a> BitXorAssign<&'a SmallUint> for SmallUint { fn bitxor_assign(&mut self, rhs: &'a SmallUint) { *self = self.clone() ^ rhs; } } impl BitXorAssign for SmallUint { fn bitxor_assign(&mut self, rhs: SmallUint) { *self = self.clone() ^ rhs; } }