diff --git a/src/logic.rs b/src/logic.rs index d38a2a9..e47169d 100644 --- a/src/logic.rs +++ b/src/logic.rs @@ -40,201 +40,123 @@ macro_rules! basic_op { }; } -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; +macro_rules! logic_op { + ( + $imp:ident, $imp_assign:ident, $typ:ident, $typ_inner:ident, $fun:ident, $fun_assign:ident; + $i:ident, $j:ident, $r:ident, $s:ident, $slice:ident, $slice1:ident, $slice2:ident, $res:ident; + $inline_heap:tt, $heap_heap:tt + ) => { + fn $fun(a: &$typ, b: &$typ) -> $typ { + match (&a.0, &b.0) { + (&$typ_inner::Inline($i), &$typ_inner::Inline($j)) => { + $typ($typ_inner::Inline($i.$fun($j))) } - SmallUint(SmallUintType::Inline(r)) - } else { - let mut slice = ManuallyDrop::new(res.into_boxed_slice()); - SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len()))) + + (&$typ_inner::Inline($i), &$typ_inner::Heap(($r, $s))) + | (&$typ_inner::Heap(($r, $s)), &$typ_inner::Inline($i)) => { + let $slice = unsafe { core::slice::from_raw_parts($r, $s) }; + + $inline_heap + } + + (&$typ_inner::Heap(($r, $s)), &$typ_inner::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]); + } + + $heap_heap + } + } + } + + basic_op!($imp, $typ, $fun); + + impl<'a> $imp_assign<&'a SmallUint> for $typ { + fn $fun_assign(&mut self, rhs: &'a $typ) { + *self = (&*self).$fun(rhs); + } + } + + impl $imp_assign<$typ> for $typ { + fn $fun_assign(&mut self, rhs: $typ) { + *self = (&*self).$fun(rhs); } } } } -basic_op!(BitAnd, SmallUint, bitand); +macro_rules! inline_heap_to_heap { + ($op_assign:tt, $i:ident, $slice:ident) => { + let mut retvec = $slice.to_vec(); -impl<'a> BitAndAssign<&'a SmallUint> for SmallUint { - fn bitand_assign(&mut self, rhs: &'a SmallUint) { - *self = self.clone() & rhs; + let mut v = $i; + #[allow(clippy::needless_range_loop)] + for r in 0..4 { + retvec[r] $op_assign v as u32; + + v >>= 32; + } + + let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice()); + + SmallUint(SmallUintType::Heap((retslice.as_mut_ptr(), retslice.len()))) } } -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()))) +macro_rules! heap_heap_to_any { + ($res:ident) => { + while $res.len() != 1 && $res[$res.len() - 1] == 0 { + $res.pop(); } - (&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(); + if $res.len() <= 4 { + let mut r = 0u128; + for t in 0..$res.len() { + r <<= 32; + r |= $res[$res.len() - 1 - t] as u128; } - - for t in 0..m { - retvec[t] = slice1[t] | slice2[t]; - } - - let mut slice = ManuallyDrop::new(retvec.into_boxed_slice()); - + 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!(BitOr, SmallUint, bitor); +logic_op! { + BitAnd, BitAndAssign, SmallUint, SmallUintType, bitand, bitand_assign; + i, j, r, s, slice, slice1, slice2, res; + { + let mut j = 0u128; + for i in 0..4 { + j <<= 32; + j |= slice[3 - i] as u128; + } + SmallUint(SmallUintType::Inline(i & j)) + }, + { heap_heap_to_any! { res } } +} -impl<'a> BitOrAssign<&'a SmallUint> for SmallUint { - fn bitor_assign(&mut self, rhs: &'a SmallUint) { - *self = self.clone() | rhs; +logic_op! { + BitOr, BitOrAssign, SmallUint, SmallUintType, bitor, bitor_assign; + i, j, r, s, slice, slice1, slice2, res; + { inline_heap_to_heap! { |=, i, slice } }, + { + let mut slice = ManuallyDrop::new(res.into_boxed_slice()); + SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len()))) } } -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; - } +logic_op! { + BitXor, BitXorAssign, SmallUint, SmallUintType, bitxor, bitxor_assign; + i, j, r, s, slice, slice1, slice2, res; + { inline_heap_to_heap! { |=, i, slice } }, + { heap_heap_to_any! { res } } }