bits_io/buf/
bit_buf_impls.rs

1use bitvec::view::BitView;
2
3use crate::prelude::*;
4
5impl<T: BitBuf + ?Sized> BitBuf for &mut T {
6    fn advance(&mut self, count: usize) {
7        (**self).advance(count);
8    }
9
10    fn remaining(&self) -> usize {
11        (**self).remaining()
12    }
13
14    fn chunk(&self) -> &BitSlice {
15        (**self).chunk()
16    }
17
18    fn chunk_bytes(&self) -> &[u8] {
19        (**self).chunk_bytes()
20    }
21
22    fn byte_aligned(&self) -> bool {
23        (**self).byte_aligned()
24    }
25}
26
27impl BitBuf for Bits {
28    fn advance(&mut self, count: usize) {
29        assert!(count <= self.remaining(), "advance past end of Bits");
30        self.inc_start(count);
31    }
32
33    fn remaining(&self) -> usize {
34        self.bit_len
35    }
36
37    fn chunk(&self) -> &BitSlice {
38        &BitSlice::from_slice(&self.inner)[self.bit_start..self.bit_start + self.bit_len]
39    }
40
41    fn chunk_bytes(&self) -> &[u8] {
42        assert!(self.bit_start % 8 == 0);
43        assert!(self.bit_len % 8 == 0);
44
45        let byte_start = self.bit_start / 8;
46
47        &self.inner[byte_start..]
48    }
49
50    fn byte_aligned(&self) -> bool {
51        self.bit_start % 8 == 0 && self.bit_len % 8 == 0
52    }
53}
54
55impl BitBuf for BitsMut {
56    fn advance(&mut self, count: usize) {
57        assert!(count <= self.remaining(), "advance past end of BitsMut");
58        self.bit_start += count;
59        self.bit_len -= count;
60        self.capacity -= count;
61    }
62
63    fn remaining(&self) -> usize {
64        self.len()
65    }
66
67    fn chunk(&self) -> &BitSlice {
68        &BitSlice::from_slice(&self.inner)[self.bit_start..self.bit_start + self.bit_len]
69    }
70
71    fn chunk_bytes(&self) -> &[u8] {
72        assert!(self.byte_aligned());
73
74        let byte_start = self.bit_start / 8;
75
76        &self.inner[byte_start..]
77    }
78
79    fn byte_aligned(&self) -> bool {
80        self.bit_start % 8 == 0 && self.bit_len % 8 == 0
81    }
82}
83
84impl BitBuf for &[u8] {
85    fn advance(&mut self, count: usize) {
86        if self.len() < count {
87            panic!("Can't advance past the end of slice");
88        }
89        *self = &self[count..];
90    }
91
92    fn remaining(&self) -> usize {
93        self.len() * 8
94    }
95
96    fn chunk(&self) -> &BitSlice {
97        self[..].view_bits()
98    }
99
100    fn chunk_bytes(&self) -> &[u8] {
101        self
102    }
103
104    fn byte_aligned(&self) -> bool {
105        true
106    }
107}
108
109// TODO: I think we're gonna get bit by not supporting BitSlice<O> here, but come back to that
110// later--hopefully we don't need a generic on the trait
111// impl BitBuf for &BitSlice {
112impl BitBuf for &BitSlice {
113    fn advance(&mut self, count: usize) {
114        if self.len() < count {
115            panic!("Can't advance past end of BitSlice");
116        }
117        *self = &self[count..];
118    }
119
120    fn remaining(&self) -> usize {
121        self.len()
122    }
123
124    fn chunk(&self) -> &BitSlice {
125        self
126    }
127
128    fn chunk_bytes(&self) -> &[u8] {
129        assert!(self.byte_aligned());
130        let bitvec::domain::Domain::Region { body, .. } = self.domain() else {
131            unreachable!("Verified by the assert above");
132        };
133
134        body
135    }
136
137    fn byte_aligned(&self) -> bool {
138        matches!(
139            self.domain(),
140            bitvec::domain::Domain::Region {
141                head: None,
142                tail: None,
143                ..
144            }
145        )
146    }
147}
148
149impl<T: AsRef<BitSlice>> BitBuf for BitCursor<T> {
150    fn advance(&mut self, count: usize) {
151        let len = self.get_ref().as_ref().len();
152        let pos = self.position();
153
154        let max_count = len.saturating_sub(pos as usize);
155        if count > max_count {
156            panic!("Can't advance beyond end of buffer");
157        }
158        self.set_position(pos + count as u64);
159    }
160
161    fn remaining(&self) -> usize {
162        self.get_ref()
163            .as_ref()
164            .len()
165            .saturating_sub(self.position() as usize)
166    }
167
168    fn chunk(&self) -> &BitSlice {
169        let slice = self.get_ref().as_ref();
170        let start = slice.len().min(self.position() as usize);
171        &slice[start..]
172    }
173
174    fn chunk_bytes(&self) -> &[u8] {
175        assert!(self.byte_aligned());
176        let bitslice = self.get_ref().as_ref();
177        let bitvec::domain::Domain::Region { body, .. } = bitslice.domain() else {
178            unreachable!("Verified by the assert above");
179        };
180
181        body
182    }
183
184    fn byte_aligned(&self) -> bool {
185        // TODO: helper func on BitSlice?
186        matches!(
187            self.get_ref().as_ref().domain(),
188            bitvec::domain::Domain::Region {
189                head: None,
190                tail: None,
191                ..
192            }
193        )
194    }
195}
196
197#[cfg(test)]
198mod tests {
199    use super::*;
200
201    // TODO: write a set of common tests that take B: BitBuf and then run them with different
202    // types that impl BitBuf.
203
204    #[test]
205    fn test_byte_aligned() {
206        // Exactly one byte worth of bits
207        let bits = bits![0; 8];
208        assert!(bits.byte_aligned());
209        // Bits within one byte but not the entire byte shouldn't be considered byte-aligned
210        let bits = bits![1, 1, 1];
211        assert!(!bits.byte_aligned());
212        // 2 bytes worth of bits should be considered byte-aligned
213        let bits = bits![0; 16];
214        assert!(bits.byte_aligned());
215        // 1 byte's worth but not at the start shouldn't be considered byte-aligned
216        let bits = bits![0; 9];
217        let slice = &bits[1..];
218        assert_eq!(8, slice.len());
219        assert!(!slice.byte_aligned());
220    }
221
222    #[test]
223    fn test_bit_buf_bits_advance() {
224        let mut bits = Bits::copy_from_slice(bits![1, 1, 1, 1, 0, 0, 0, 0]);
225
226        bits.advance(4);
227        assert_eq!(bits.len(), 4);
228        assert_eq!(bits.chunk(), bits![0, 0, 0, 0]);
229    }
230
231    #[test]
232    fn test_bit_buf_bits_mut_advance() {
233        let mut bits_mut = BitsMut::zeroed(16);
234        bits_mut.advance(8);
235        assert_eq!(bits_mut.len(), 8);
236    }
237
238    #[test]
239    fn test_bits_copy_to_slice() {
240        let mut bits = Bits::copy_from_slice(bits![1, 1, 1, 1, 0, 0, 0, 0]);
241
242        let dest = bits![mut 0; 4];
243        bits.copy_to_slice(dest);
244        assert_eq!(dest, bits![1, 1, 1, 1,]);
245
246        bits.copy_to_slice(dest);
247        assert_eq!(dest, bits![0, 0, 0, 0]);
248    }
249
250    #[test]
251    fn test_chunk_bytes() {
252        {
253            let bits = Bits::copy_from_slice(bits![1, 1, 1, 1, 0, 0, 0, 0]);
254
255            let chunk_bytes = bits.chunk_bytes();
256            assert_eq!(chunk_bytes.len(), 1);
257            assert_eq!(chunk_bytes[0], 0b11110000);
258        }
259        {
260            let mut bits = Bits::copy_from_slice(bits![
261                0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0
262            ]);
263            bits.advance(8);
264            let chunk_bytes = bits.chunk_bytes();
265            assert_eq!(chunk_bytes.len(), 2);
266            assert_eq!(chunk_bytes, [0b11111111, 0b10101010]);
267        }
268    }
269
270    #[test]
271    fn test_copy_to_slice_bytes() {
272        let mut dest = [0; 4];
273
274        let mut bits = Bits::from_owner_bytes([42, 43, 44, 45]);
275
276        bits.copy_to_slice_bytes(&mut dest);
277        assert_eq!(dest, [42, 43, 44, 45]);
278    }
279
280    #[test]
281    fn test_bitslice_bitbuf() {
282        let mut bits = bits![1, 0, 1, 0, 1, 0];
283        assert_eq!(6, bits.remaining());
284        bits.advance(3);
285        assert_eq!(3, bits.remaining());
286    }
287
288    #[test]
289    fn test_take() {
290        let mut bits = Bits::from_static_bytes(&[1, 2, 3, 4]);
291
292        let mut head = (&mut bits).take(16);
293        let value = head.get_u16::<NetworkOrder>().unwrap();
294        assert!(head.get_bool().is_err());
295        assert_eq!(value, 0x0102);
296        let mut tail = (&mut bits).take(16);
297        let value = tail.get_u16::<NetworkOrder>().unwrap();
298        assert!(tail.get_bool().is_err());
299        assert_eq!(value, 0x0304);
300    }
301}