1use crate::iter::BlockIter;
2use crate::BlockType;
3use crate::{BitSliceable, Bits};
4
5use crate::traits::get_masked_block;
6
7use core::cmp;
8
9#[derive(Clone, Debug)]
14pub struct BitNot<T>(T);
15
16impl<T> BitNot<T> {
17 pub(crate) fn new(bits: T) -> Self {
18 BitNot(bits)
19 }
20}
21
22#[derive(Clone, Debug)]
27pub struct BitAnd<T, U>(BitBinOp<T, U>);
28
29impl<T: Bits, U: Bits<Block = T::Block>> BitAnd<T, U> {
30 pub(crate) fn new(bits1: T, bits2: U) -> Self {
31 BitAnd(BitBinOp::new(bits1, bits2))
32 }
33}
34
35#[derive(Clone, Debug)]
40pub struct BitOr<T, U>(BitBinOp<T, U>);
41
42impl<T: Bits, U: Bits<Block = T::Block>> BitOr<T, U> {
43 pub(crate) fn new(bits1: T, bits2: U) -> Self {
44 BitOr(BitBinOp::new(bits1, bits2))
45 }
46}
47
48#[derive(Clone, Debug)]
53pub struct BitXor<T, U>(BitBinOp<T, U>);
54
55impl<T: Bits, U: Bits<Block = T::Block>> BitXor<T, U> {
56 pub(crate) fn new(bits1: T, bits2: U) -> Self {
57 BitXor(BitBinOp::new(bits1, bits2))
58 }
59}
60
61#[derive(Clone, Debug)]
63pub struct BitZip<T, U, F> {
64 ops: BitBinOp<T, U>,
65 fun: F,
66}
67
68impl<T: Bits, U: Bits<Block = T::Block>, F> BitZip<T, U, F> {
69 pub(crate) fn new(bits1: T, bits2: U, fun: F) -> Self {
70 BitZip {
71 ops: BitBinOp::new(bits1, bits2),
72 fun,
73 }
74 }
75}
76
77#[derive(Clone, Debug)]
82struct BitBinOp<T, U> {
83 op1: T,
84 op2: U,
85 len: u64,
86}
87
88impl<T: Bits, U: Bits<Block = T::Block>> BitBinOp<T, U> {
89 fn new(op1: T, op2: U) -> Self {
90 let len = cmp::min(op1.bit_len(), op2.bit_len());
91 BitBinOp { op1, op2, len }
92 }
93
94 fn bit1(&self, position: u64) -> bool {
95 self.op1.get_bit(position)
96 }
97
98 fn bit2(&self, position: u64) -> bool {
99 self.op2.get_bit(position)
100 }
101
102 fn block1(&self, position: usize) -> T::Block {
103 self.op1.get_raw_block(position)
104 }
105
106 fn block2(&self, position: usize) -> T::Block {
107 self.op2.get_raw_block(position)
108 }
109}
110
111impl<T: Bits> Bits for BitNot<T> {
112 type Block = T::Block;
113
114 fn bit_len(&self) -> u64 {
115 self.0.bit_len()
116 }
117
118 fn get_bit(&self, position: u64) -> bool {
119 !self.0.get_bit(position)
120 }
121
122 fn get_block(&self, position: usize) -> Self::Block {
123 !self.0.get_block(position)
124 }
125
126 fn get_raw_block(&self, position: usize) -> Self::Block {
127 !self.0.get_raw_block(position)
128 }
129}
130
131impl_index_from_bits! {
132 impl[T: Bits] Index<u64> for BitNot<T>;
133}
134
135impl<R, T> BitSliceable<R> for BitNot<T>
136where
137 T: BitSliceable<R>,
138{
139 type Slice = BitNot<T::Slice>;
140
141 fn bit_slice(self, range: R) -> Self::Slice {
142 BitNot(self.0.bit_slice(range))
143 }
144}
145
146impl_bit_sliceable_adapter! {
147 impl['a, T: Bits] BitSliceable for &'a BitNot<T>;
148}
149
150impl<T, U> PartialEq<U> for BitNot<T>
151where
152 T: Bits,
153 U: Bits<Block = T::Block>,
154{
155 fn eq(&self, other: &U) -> bool {
156 BlockIter::new(self) == BlockIter::new(other)
157 }
158}
159
160macro_rules! impl_bits_bin_op {
161 ( $target:ident as $block_op:tt $bool_op:tt ) => {
162 impl<T, U> Bits for $target<T, U>
163 where T: Bits,
164 U: Bits<Block = T::Block>
165 {
166 type Block = T::Block;
167
168 fn bit_len(&self) -> u64 {
169 self.0.len
170 }
171
172 fn get_bit(&self, position: u64) -> bool {
173 assert!( position < self.bit_len(),
174 "{}::get_bit: out of bounds", stringify!($target) );
175 self.0.bit1(position) $bool_op self.0.bit2(position)
176 }
177
178 fn get_block(&self, position: usize) -> Self::Block {
179 assert!( position < self.block_len(),
180 "{}::get_block: out of bounds", stringify!($target) );
181 get_masked_block(self, position)
182 }
183
184 fn get_raw_block(&self, position: usize) -> Self::Block {
185 self.0.block1(position) $block_op self.0.block2(position)
186 }
187 }
188
189 impl_index_from_bits! {
190 impl[T: Bits, U: Bits<Block = T::Block>] Index<u64> for $target<T, U>;
191 }
192
193 impl<Block, R, T, U> BitSliceable<R> for $target<T, U>
194 where Block: BlockType,
195 R: Clone,
196 T: BitSliceable<R, Block = Block>,
197 U: BitSliceable<R, Block = Block> {
198
199 type Slice = $target<T::Slice, U::Slice>;
200
201 fn bit_slice(self, range: R) -> Self::Slice {
202 $target(BitBinOp::new(self.0.op1.bit_slice(range.clone()),
203 self.0.op2.bit_slice(range)))
204 }
205 }
206
207 impl_bit_sliceable_adapter! {
208 impl['a, T: Bits, U: Bits<Block = T::Block>] BitSliceable for &'a $target<T, U>;
209 }
210
211 impl<T, U, V> PartialEq<V> for $target<T, U>
212 where T: Bits,
213 U: Bits<Block = T::Block>,
214 V: Bits<Block = T::Block> {
215
216 fn eq(&self, other: &V) -> bool {
217 BlockIter::new(self) == BlockIter::new(other)
218 }
219 }
220 };
221}
222
223impl_bits_bin_op!(BitAnd as & &&);
224impl_bits_bin_op!(BitOr as | ||);
225impl_bits_bin_op!(BitXor as ^ ^);
226
227impl<T, U, F> Bits for BitZip<T, U, F>
228where
229 T: Bits,
230 U: Bits<Block = T::Block>,
231 F: Fn(T::Block, T::Block) -> T::Block,
232{
233 type Block = T::Block;
234
235 fn bit_len(&self) -> u64 {
236 self.ops.len
237 }
238
239 fn get_block(&self, position: usize) -> Self::Block {
240 assert!(
241 position < self.block_len(),
242 "BitZip::get_block: out of bounds"
243 );
244 get_masked_block(self, position)
245 }
246
247 fn get_raw_block(&self, position: usize) -> Self::Block {
248 (self.fun)(self.ops.block1(position), self.ops.block2(position))
249 }
250}
251
252impl_index_from_bits! {
253 impl[T: Bits, U: Bits<Block = T::Block>,
254 F: Fn(T::Block, T::Block) -> T::Block]
255 Index<u64> for BitZip<T, U, F>;
256}
257
258impl<Block, R, T, U, F> BitSliceable<R> for BitZip<T, U, F>
259where
260 Block: BlockType,
261 R: Clone,
262 T: BitSliceable<R, Block = Block>,
263 U: BitSliceable<R, Block = Block>,
264 F: Fn(Block, Block) -> Block,
265{
266 type Slice = BitZip<T::Slice, U::Slice, F>;
267
268 fn bit_slice(self, range: R) -> Self::Slice {
269 BitZip {
270 ops: BitBinOp::new(
271 self.ops.op1.bit_slice(range.clone()),
272 self.ops.op2.bit_slice(range),
273 ),
274 fun: self.fun,
275 }
276 }
277}
278
279impl_bit_sliceable_adapter! {
280 impl['a, T: Bits, U: Bits<Block = T::Block>,
281 F: Fn(T::Block, T::Block) -> T::Block]
282 BitSliceable for &'a BitZip<T, U, F>;
283}
284
285impl<T, U, F, V> PartialEq<V> for BitZip<T, U, F>
286where
287 T: Bits,
288 U: Bits<Block = T::Block>,
289 V: Bits<Block = T::Block>,
290 F: Fn(T::Block, T::Block) -> T::Block,
291{
292 fn eq(&self, other: &V) -> bool {
293 BlockIter::new(self) == BlockIter::new(other)
294 }
295}