nostd_bv/adapter/
logic.rs

1use crate::iter::BlockIter;
2use crate::BlockType;
3use crate::{BitSliceable, Bits};
4
5use crate::traits::get_masked_block;
6
7use core::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>
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}