nostd_bv/adapter/
bit_slice_adapter.rs

1use crate::iter::BlockIter;
2use crate::{BitSliceable, Bits, BitsMut, BlockType};
3
4use crate::range_compat::*;
5
6/// An adapter that turns any implementation of `Bits` into a slice.
7///
8/// This is likely less efficient than [`BitSlice`].
9///
10/// [`BitSlice`]: ../struct.BitSlice.html
11#[derive(Copy, Clone, Debug)]
12pub struct BitSliceAdapter<T> {
13    bits: T,
14    start: u64,
15    len: u64,
16}
17
18impl<T: Bits> BitSliceAdapter<T> {
19    /// Creates a new slice adaptor from the given bit-vector-like.
20    ///
21    /// Takes the index of the start bit, and the length to slice.
22    ///
23    /// # Panics
24    ///
25    /// Out of bounds if `start + len > bits.bit_len()`.
26    pub fn new(bits: T, start: u64, len: u64) -> Self {
27        assert!(
28            start + len <= bits.bit_len(),
29            "BitSliceAdapter::new: out of bounds"
30        );
31        BitSliceAdapter { bits, start, len }
32    }
33
34    /// Reslices an existing slice adapter, by value.
35    ///
36    /// Takes the index of the start bit, relative to the indexing
37    /// of the adapter.
38    ///
39    /// # Panics
40    ///
41    /// Out of bounds if `start + len > self.bit_len()`.
42    fn reslice(self, start: u64, len: u64) -> Self {
43        assert!(
44            start + len <= self.bit_len(),
45            "BitSliceAdapter::reslice: out of bounds"
46        );
47        BitSliceAdapter {
48            bits: self.bits,
49            start: self.start + start,
50            len,
51        }
52    }
53
54    /// Reslices an existing slice adapter, by reference.
55    ///
56    /// Takes the index of the start bit, relative to the indexing
57    /// of the adapter.
58    ///
59    /// # Panics
60    ///
61    /// Out of bounds if `start + len > self.bit_len()`.
62    fn reslice_ref(&self, start: u64, len: u64) -> BitSliceAdapter<&T> {
63        assert!(
64            start + len <= self.bit_len(),
65            "BitSliceAdapter::reslice: out of bounds"
66        );
67        BitSliceAdapter {
68            bits: &self.bits,
69            start: self.start + start,
70            len,
71        }
72    }
73}
74
75impl<T, U> PartialEq<U> for BitSliceAdapter<T>
76where
77    T: Bits,
78    U: Bits<Block = T::Block>,
79{
80    fn eq(&self, other: &U) -> bool {
81        BlockIter::new(self) == BlockIter::new(other)
82    }
83}
84
85macro_rules! impl_bit_sliceable_adapter {
86    (
87        $(
88            impl[ $($param:tt)* ] BitSliceable for $target:ty ;
89        )+
90    ) => {
91        $(
92            impl<$($param)*> $crate::BitSliceable<::core::ops::Range<u64>> for $target {
93                type Slice = $crate::adapter::BitSliceAdapter<Self>;
94
95                fn bit_slice(self, range: ::core::ops::Range<u64>) -> Self::Slice {
96                    assert!( range.start <= range.end,
97                             "{}::slice: bad range", stringify!($target) );
98                    $crate::adapter::BitSliceAdapter::new(self, range.start, range.end - range.start)
99                }
100            }
101
102            impl<$($param)*> $crate::BitSliceable<::core::ops::RangeFrom<u64>> for $target {
103                type Slice = $crate::adapter::BitSliceAdapter<Self>;
104
105                fn bit_slice(self, range: ::core::ops::RangeFrom<u64>) -> Self::Slice {
106                    let len = self.bit_len();
107                    self.bit_slice(range.start .. len)
108                }
109            }
110
111            impl<$($param)*> $crate::BitSliceable<::core::ops::RangeTo<u64>> for $target {
112                type Slice = $crate::adapter::BitSliceAdapter<Self>;
113
114                fn bit_slice(self, range: ::core::ops::RangeTo<u64>) -> Self::Slice {
115                    $crate::adapter::BitSliceAdapter::new(self, 0, range.end)
116                }
117            }
118
119            impl<$($param)*> $crate::BitSliceable<::core::ops::RangeFull> for $target {
120                type Slice = $crate::adapter::BitSliceAdapter<Self>;
121
122                fn bit_slice(self, _range: ::core::ops::RangeFull) -> Self::Slice {
123                    let len = self.bit_len();
124                    $crate::adapter::BitSliceAdapter::new(self, 0, len)
125                }
126            }
127
128            impl<$($param)*> $crate::BitSliceable<::core::ops::RangeInclusive<u64>> for $target {
129                type Slice = $crate::adapter::BitSliceAdapter<Self>;
130
131                fn bit_slice(self, range: ::core::ops::RangeInclusive<u64>) -> Self::Slice {
132                    let (start, end) = $crate::range_compat::get_inclusive_bounds(range)
133                        .expect("BitSliceable::bit_slice: bad inclusive range");
134                    $crate::adapter::BitSliceAdapter::new(self, start, end - start + 1)
135                }
136            }
137
138            impl<$($param)*> $crate::BitSliceable<::core::ops::RangeToInclusive<u64>> for $target {
139                type Slice = $crate::adapter::BitSliceAdapter<Self>;
140
141                fn bit_slice(self, range: ::core::ops::RangeToInclusive<u64>) -> Self::Slice {
142                    $crate::adapter::BitSliceAdapter::new(self, 0, range.end + 1)
143                }
144            }
145        )+
146    };
147}
148
149impl<T: Bits> Bits for BitSliceAdapter<T> {
150    type Block = T::Block;
151
152    fn bit_len(&self) -> u64 {
153        self.len
154    }
155
156    fn get_bit(&self, position: u64) -> bool {
157        assert!(
158            position < self.bit_len(),
159            "BitSliceAdapter::get_bit: out of bounds"
160        );
161        self.bits.get_bit(self.start + position)
162    }
163
164    fn get_block(&self, position: usize) -> Self::Block {
165        assert!(
166            position < self.block_len(),
167            "BitSliceAdapter::get_block: out of bounds"
168        );
169        let (real_start, real_len) = get_block_addr::<T::Block>(self.start, self.len, position);
170        self.bits.get_bits(real_start, real_len)
171    }
172
173    fn get_bits(&self, start: u64, count: usize) -> Self::Block {
174        assert!(
175            start + count as u64 <= self.bit_len(),
176            "BitSliceAdapter::get_bits: out of bounds"
177        );
178        self.bits.get_bits(self.start + start, count)
179    }
180}
181
182impl<T: BitsMut> BitsMut for BitSliceAdapter<T> {
183    fn set_bit(&mut self, position: u64, value: bool) {
184        assert!(
185            position < self.bit_len(),
186            "BitSliceAdapter::set_bit: out of bounds"
187        );
188        self.bits.set_bit(self.start + position, value);
189    }
190
191    fn set_block(&mut self, position: usize, value: Self::Block) {
192        assert!(
193            position < self.block_len(),
194            "BitSliceAdapter::get_block: out of bounds"
195        );
196        let (real_start, real_len) = get_block_addr::<T::Block>(self.start, self.len, position);
197        self.bits.set_bits(real_start, real_len, value);
198    }
199
200    fn set_bits(&mut self, start: u64, count: usize, value: Self::Block) {
201        assert!(
202            start + count as u64 <= self.bit_len(),
203            "BitSliceAdapter::set_bits: out of bounds"
204        );
205        self.bits.set_bits(self.start + start, count, value);
206    }
207}
208
209// For a slice starting at `start`, of length `len`, finds the parameters
210// for extracting the `position`th block. The parameters are the bit position
211// of the start of the block, and the number of bits in the block.
212fn get_block_addr<Block: BlockType>(start: u64, len: u64, position: usize) -> (u64, usize) {
213    let real_start = start + Block::mul_nbits(position);
214    let block_size = Block::nbits() as u64;
215    let real_len = if real_start + block_size < start + len {
216        block_size
217    } else {
218        start + len - real_start
219    };
220
221    (real_start, real_len as usize)
222}
223
224impl_index_from_bits! {
225    impl[T: Bits] Index<u64> for BitSliceAdapter<T>;
226}
227
228impl<T: Bits> BitSliceable<Range<u64>> for BitSliceAdapter<T> {
229    type Slice = Self;
230
231    fn bit_slice(self, range: Range<u64>) -> Self::Slice {
232        assert!(
233            range.start <= range.end,
234            "BitSliceAdapter::bit_slice: bad range"
235        );
236        self.reslice(range.start, range.end - range.start)
237    }
238}
239
240impl<T: Bits> BitSliceable<RangeTo<u64>> for BitSliceAdapter<T> {
241    type Slice = Self;
242
243    fn bit_slice(self, range: RangeTo<u64>) -> Self::Slice {
244        self.reslice(0, range.end)
245    }
246}
247
248impl<T: Bits> BitSliceable<RangeFrom<u64>> for BitSliceAdapter<T> {
249    type Slice = Self;
250
251    fn bit_slice(self, range: RangeFrom<u64>) -> Self::Slice {
252        let len = self.bit_len();
253        assert!(
254            range.start <= len,
255            "BitSliceAdapter::bit_slice: out of bounds"
256        );
257        self.reslice(range.start, len - range.start)
258    }
259}
260
261impl<T: Bits> BitSliceable<RangeFull> for BitSliceAdapter<T> {
262    type Slice = Self;
263
264    fn bit_slice(self, _range: RangeFull) -> Self::Slice {
265        self
266    }
267}
268
269impl<T: Bits> BitSliceable<RangeInclusive<u64>> for BitSliceAdapter<T> {
270    type Slice = Self;
271
272    fn bit_slice(self, range: RangeInclusive<u64>) -> Self::Slice {
273        let (start, limit) =
274            get_inclusive_bounds(range).expect("BitSliceAdapter::bit_slice: bad range");
275        self.reslice(start, limit - start + 1)
276    }
277}
278
279impl<T: Bits> BitSliceable<RangeToInclusive<u64>> for BitSliceAdapter<T> {
280    type Slice = Self;
281
282    fn bit_slice(self, range: RangeToInclusive<u64>) -> Self::Slice {
283        self.reslice(0, range.end + 1)
284    }
285}
286
287impl<'a, T: Bits> BitSliceable<Range<u64>> for &'a BitSliceAdapter<T> {
288    type Slice = BitSliceAdapter<&'a T>;
289
290    fn bit_slice(self, range: Range<u64>) -> Self::Slice {
291        assert!(
292            range.start <= range.end,
293            "BitSliceAdapter::bit_slice: bad range"
294        );
295        self.reslice_ref(range.start, range.end - range.start)
296    }
297}
298
299impl<'a, T: Bits> BitSliceable<RangeTo<u64>> for &'a BitSliceAdapter<T> {
300    type Slice = BitSliceAdapter<&'a T>;
301
302    fn bit_slice(self, range: RangeTo<u64>) -> Self::Slice {
303        self.reslice_ref(0, range.end)
304    }
305}
306
307impl<'a, T: Bits> BitSliceable<RangeFrom<u64>> for &'a BitSliceAdapter<T> {
308    type Slice = BitSliceAdapter<&'a T>;
309
310    fn bit_slice(self, range: RangeFrom<u64>) -> Self::Slice {
311        let len = self.bit_len();
312        assert!(
313            range.start <= len,
314            "BitSliceAdapter::bit_slice: out of bounds"
315        );
316        self.reslice_ref(range.start, len - range.start)
317    }
318}
319
320impl<'a, T: Bits> BitSliceable<RangeFull> for &'a BitSliceAdapter<T> {
321    type Slice = BitSliceAdapter<&'a T>;
322
323    fn bit_slice(self, _range: RangeFull) -> Self::Slice {
324        self.reslice_ref(0, self.bit_len())
325    }
326}
327
328impl<'a, T: Bits> BitSliceable<RangeInclusive<u64>> for &'a BitSliceAdapter<T> {
329    type Slice = BitSliceAdapter<&'a T>;
330
331    fn bit_slice(self, range: RangeInclusive<u64>) -> Self::Slice {
332        let (start, limit) =
333            get_inclusive_bounds(range).expect("BitSliceAdapter::bit_slice: bad range");
334        self.reslice_ref(start, limit - start + 1)
335    }
336}
337
338impl<'a, T: Bits> BitSliceable<RangeToInclusive<u64>> for &'a BitSliceAdapter<T> {
339    type Slice = BitSliceAdapter<&'a T>;
340
341    fn bit_slice(self, range: RangeToInclusive<u64>) -> Self::Slice {
342        self.reslice_ref(0, range.end + 1)
343    }
344}