nostd_bv/traits/
bits_ext.rs

1use super::Bits;
2use crate::adapter::*;
3
4/// Extension trait for adapter operations on bit slices.
5///
6/// The methods return lazy adapter objects that query the underlying bit vectors
7/// and perform operations as needed. To eagerly evaluate a result, copy
8/// it into a vector using the [`Bits::to_bit_vec`] method, as in the example below.
9///
10/// This trait is currently `pub use`d from the [`adapter`] module, but that alias
11/// is deprecated.
12///
13/// [`Bits::to_bit_vec`]: trait.Bits.html#method.to_bit_vec
14/// [`adapter`]: adapter/index.html
15///
16/// # Examples
17///
18/// ```
19/// use nostd_bv::*;
20///
21/// let bv1: BitVec = bit_vec![false, false, true, true];
22/// let bv2: BitVec = bit_vec![false, true, false, true];
23///
24/// let and_bv = bv1.bit_and(&bv2);
25///
26/// assert_eq!( and_bv[0], false );
27/// assert_eq!( and_bv[1], false );
28/// assert_eq!( and_bv[2], false );
29/// assert_eq!( and_bv[3], true );
30///
31/// let bv3 = and_bv.to_bit_vec();
32/// assert_eq!( bv3, bit_vec![false, false, false, true] );
33/// ```
34pub trait BitsExt: Bits {
35    /// Concatenates two bit vectors, with the bits of `self` followed by the bits
36    /// of `other`.
37    fn bit_concat<Other>(&self, other: Other) -> BitConcat<&Self, Other>
38    where
39        Other: Bits<Block = Self::Block>,
40    {
41        BitConcat::new(self, other)
42    }
43
44    /// Concatenates two bit vectors, with the bits of `self` followed by the bits
45    /// of `other`.
46    ///
47    /// Consumes `self`.
48    fn into_bit_concat<Other>(self, other: Other) -> BitConcat<Self, Other>
49    where
50        Self: Sized,
51        Other: Bits<Block = Self::Block>,
52    {
53        BitConcat::new(self, other)
54    }
55
56    /// Pads `self` with 0s on the right to reach at least `len` bits in length.
57    ///
58    /// If `self` is already long enough, the length is unchanged.
59    fn bit_pad(&self, len: u64) -> BitConcat<&Self, BitFill<Self::Block>> {
60        self.into_bit_pad(len)
61    }
62
63    /// Pads `self` with 0s on the right to reach at least `len` bits in length.
64    ///
65    /// If `self` is already long enough, the length is unchanged.
66    ///
67    /// Consumes `self`.
68    fn into_bit_pad(self, len: u64) -> BitConcat<Self, BitFill<Self::Block>>
69    where
70        Self: Sized,
71    {
72        let have = self.bit_len();
73        let need = len.saturating_sub(have);
74        self.into_bit_concat(BitFill::zeroes(need))
75    }
76
77    /// Returns an object that inverts the values of all the bits in `self`.
78    fn bit_not(&self) -> BitNot<&Self> {
79        BitNot::new(self)
80    }
81
82    /// Returns an object that inverts the values of all the bits in `self`.
83    ///
84    /// Consumes `self`.
85    fn into_bit_not(self) -> BitNot<Self>
86    where
87        Self: Sized,
88    {
89        BitNot::new(self)
90    }
91
92    /// Returns an object that lazily computes the bit-wise conjunction
93    /// of two bit-vector-likes.
94    ///
95    /// If the lengths of the operands differ, the result will have
96    /// the minimum of the two.
97    fn bit_and<Other>(&self, other: Other) -> BitAnd<&Self, Other>
98    where
99        Other: Bits<Block = Self::Block>,
100    {
101        BitAnd::new(self, other)
102    }
103
104    /// Returns an object that lazily computes the bit-wise conjunction
105    /// of two bit-vector-likes.
106    ///
107    /// If the lengths of the operands differ, the result will have
108    /// the minimum of the two.
109    ///
110    /// Consumes `self`.
111    fn into_bit_and<Other>(self, other: Other) -> BitAnd<Self, Other>
112    where
113        Self: Sized,
114        Other: Bits<Block = Self::Block>,
115    {
116        BitAnd::new(self, other)
117    }
118
119    /// Returns an object that lazily computes the bit-wise disjunction
120    /// of two bit-vector-likes.
121    ///
122    /// If the lengths of the operands differ, the result will have
123    /// the minimum of the two.
124    fn bit_or<Other>(&self, other: Other) -> BitOr<&Self, Other>
125    where
126        Other: Bits<Block = Self::Block>,
127    {
128        BitOr::new(self, other)
129    }
130
131    /// Returns an object that lazily computes the bit-wise disjunction
132    /// of two bit-vector-likes.
133    ///
134    /// If the lengths of the operands differ, the result will have
135    /// the minimum of the two.
136    ///
137    /// Consumes `self`.
138    fn into_bit_or<Other>(self, other: Other) -> BitOr<Self, Other>
139    where
140        Self: Sized,
141        Other: Bits<Block = Self::Block>,
142    {
143        BitOr::new(self, other)
144    }
145
146    /// Returns an object that lazily computes the bit-wise xor of two
147    /// bit-vector-likes.
148    ///
149    /// If the lengths of the operands differ, the result will have
150    /// the minimum of the two.
151    fn bit_xor<Other>(&self, other: Other) -> BitXor<&Self, Other>
152    where
153        Other: Bits<Block = Self::Block>,
154    {
155        BitXor::new(self, other)
156    }
157
158    /// Returns an object that lazily computes the bit-wise xor of two
159    /// bit-vector-likes.
160    ///
161    /// If the lengths of the operands differ, the result will have
162    /// the minimum of the two.
163    ///
164    /// Consumes `self`.
165    fn into_bit_xor<Other>(self, other: Other) -> BitXor<Self, Other>
166    where
167        Self: Sized,
168        Other: Bits<Block = Self::Block>,
169    {
170        BitXor::new(self, other)
171    }
172
173    /// Returns an object that lazily zips a function over the blocks of
174    /// two bit-vector-like.
175    ///
176    /// The third parameter to the zipping function `fun` is the number of
177    /// bits in the block currently being processed. (This will be
178    /// `Self::Block::nbits()` for all but the last block.)
179    ///
180    /// If the lengths of the operands differ, the result will have
181    /// the minimum of the two.
182    fn bit_zip<Other, F>(&self, other: Other, fun: F) -> BitZip<&Self, Other, F>
183    where
184        Other: Bits<Block = Self::Block>,
185        F: Fn(Self::Block, Self::Block, usize) -> Self::Block,
186    {
187        BitZip::new(self, other, fun)
188    }
189
190    /// Returns an object that lazily zips a function over the blocks of
191    /// two bit-vector-like.
192    ///
193    /// The third parameter to the zipping function `fun` is the number of
194    /// bits in the block currently being processed. (This will be
195    /// `Self::Block::nbits()` for all but the last block.)
196    ///
197    /// If the lengths of the operands differ, the result will have
198    /// the minimum of the two.
199    ///
200    /// Consumes `self`.
201    fn into_bit_zip<Other, F>(self, other: Other, fun: F) -> BitZip<Self, Other, F>
202    where
203        Self: Sized,
204        Other: Bits<Block = Self::Block>,
205        F: Fn(Self::Block, Self::Block, usize) -> Self::Block,
206    {
207        BitZip::new(self, other, fun)
208    }
209}
210
211impl<T: Bits> BitsExt for T {}