bv/adapter/
bit_slice_adapter.rs

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