bv/adapter/
logic.rs

1use {Bits, BitSliceable};
2use BlockType;
3use iter::BlockIter;
4
5use traits::get_masked_block;
6
7use std::cmp;
8
9/// The result of [`BitsExt::bit_not`](../trait.BitsExt.html#method.bit_not).
10///
11/// The resulting bit vector adapter *not*s the bits of the underlying
12/// bit-vector-like.
13#[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/// The result of [`BitsExt::bit_and`](../trait.BitsExt.html#method.bit_and).
23///
24/// The resulting bit vector adapter *and*s the bits of the two underlying
25/// bit-vector-likes.
26#[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/// The result of [`BitsExt::bit_or`](../trait.BitsExt.html#method.bit_or).
36///
37/// The resulting bit vector adapter *or*s the bits of the two underlying
38/// bit-vector-likes.
39#[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/// The result of [`BitsExt::bit_xor`](../trait.BitsExt.html#method.bit_xor).
49///
50/// The resulting bit vector adapter *xor*s the bits of the two underlying
51/// bit-vector-likes.
52#[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/// The result of [`BitsExt::bit_zip`](../trait.BitsExt.html#method.bit_zip).
62#[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/// Used to store the two operands to a bitwise logical operation on
78/// `Bits`es, along with the length of the result (min the length of
79/// the operands). (Note that `len` is derivable from `op1` and `op2`,
80/// but it probably makes sense to cache it.)
81#[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>
136    where T: BitSliceable<R> {
137
138    type Slice = BitNot<T::Slice>;
139
140    fn bit_slice(self, range: R) -> Self::Slice {
141        BitNot(self.0.bit_slice(range))
142    }
143}
144
145impl_bit_sliceable_adapter! {
146    impl['a, T: Bits] BitSliceable for &'a BitNot<T>;
147}
148
149impl<T, U> PartialEq<U> for BitNot<T>
150    where T: Bits,
151          U: Bits<Block = T::Block> {
152
153    fn eq(&self, other: &U) -> bool {
154        BlockIter::new(self) == BlockIter::new(other)
155    }
156}
157
158macro_rules! impl_bits_bin_op {
159    ( $target:ident as $block_op:tt $bool_op:tt ) => {
160        impl<T, U> Bits for $target<T, U>
161            where T: Bits,
162                  U: Bits<Block = T::Block>
163        {
164            type Block = T::Block;
165
166            fn bit_len(&self) -> u64 {
167                self.0.len
168            }
169
170            fn get_bit(&self, position: u64) -> bool {
171                assert!( position < self.bit_len(),
172                         format!("{}::get_bit: out of bounds", stringify!($target)) );
173                self.0.bit1(position) $bool_op self.0.bit2(position)
174            }
175
176            fn get_block(&self, position: usize) -> Self::Block {
177                assert!( position < self.block_len(),
178                         format!("{}::get_block: out of bounds", stringify!($target)) );
179                get_masked_block(self, position)
180            }
181
182            fn get_raw_block(&self, position: usize) -> Self::Block {
183                self.0.block1(position) $block_op self.0.block2(position)
184            }
185        }
186
187        impl_index_from_bits! {
188            impl[T: Bits, U: Bits<Block = T::Block>] Index<u64> for $target<T, U>;
189        }
190
191        impl<Block, R, T, U> BitSliceable<R> for $target<T, U>
192            where Block: BlockType,
193                  R: Clone,
194                  T: BitSliceable<R, Block = Block>,
195                  U: BitSliceable<R, Block = Block> {
196
197            type Slice = $target<T::Slice, U::Slice>;
198
199            fn bit_slice(self, range: R) -> Self::Slice {
200                $target(BitBinOp::new(self.0.op1.bit_slice(range.clone()),
201                                      self.0.op2.bit_slice(range)))
202            }
203        }
204
205        impl_bit_sliceable_adapter! {
206            impl['a, T: Bits, U: Bits<Block = T::Block>] BitSliceable for &'a $target<T, U>;
207        }
208
209        impl<T, U, V> PartialEq<V> for $target<T, U>
210            where T: Bits,
211                  U: Bits<Block = T::Block>,
212                  V: Bits<Block = T::Block> {
213
214            fn eq(&self, other: &V) -> bool {
215                BlockIter::new(self) == BlockIter::new(other)
216            }
217        }
218    };
219}
220
221impl_bits_bin_op!(BitAnd as & &&);
222impl_bits_bin_op!(BitOr  as | ||);
223impl_bits_bin_op!(BitXor as ^ ^);
224
225impl<T, U, F> Bits for BitZip<T, U, F>
226    where T: Bits,
227          U: Bits<Block = T::Block>,
228          F: Fn(T::Block, T::Block) -> T::Block {
229    type Block = T::Block;
230
231    fn bit_len(&self) -> u64 {
232        self.ops.len
233    }
234
235    fn get_block(&self, position: usize) -> Self::Block {
236        assert!( position < self.block_len(), "BitZip::get_block: out of bounds" );
237        get_masked_block(self, position)
238    }
239
240    fn get_raw_block(&self, position: usize) -> Self::Block {
241        (self.fun)(self.ops.block1(position), self.ops.block2(position))
242    }
243}
244
245impl_index_from_bits! {
246    impl[T: Bits, U: Bits<Block = T::Block>,
247         F: Fn(T::Block, T::Block) -> T::Block]
248        Index<u64> for BitZip<T, U, F>;
249}
250
251impl<Block, R, T, U, F> BitSliceable<R> for BitZip<T, U, F>
252    where Block: BlockType,
253          R: Clone,
254          T: BitSliceable<R, Block = Block>,
255          U: BitSliceable<R, Block = Block>,
256          F: Fn(Block, Block) -> Block {
257
258    type Slice = BitZip<T::Slice, U::Slice, F>;
259
260    fn bit_slice(self, range: R) -> Self::Slice {
261        BitZip {
262            ops: BitBinOp::new(self.ops.op1.bit_slice(range.clone()),
263                               self.ops.op2.bit_slice(range)),
264            fun: self.fun,
265        }
266    }
267}
268
269impl_bit_sliceable_adapter! {
270    impl['a, T: Bits, U: Bits<Block = T::Block>,
271         F: Fn(T::Block, T::Block) -> T::Block]
272        BitSliceable for &'a BitZip<T, U, F>;
273}
274
275impl<T, U, F, V> PartialEq<V> for BitZip<T, U, F>
276    where T: Bits,
277          U: Bits<Block = T::Block>,
278          V: Bits<Block = T::Block>,
279          F: Fn(T::Block, T::Block) -> T::Block {
280
281    fn eq(&self, other: &V) -> bool {
282        BlockIter::new(self) == BlockIter::new(other)
283    }
284}
285