1use std::ops::Bound;
5use std::ops::RangeBounds;
6
7use crate::BitBuffer;
8use crate::BitBufferMeta;
9use crate::BitBufferMut;
10use crate::ByteBuffer;
11use crate::bit::BitChunks;
12use crate::bit::BitIndexIterator;
13use crate::bit::BitIterator;
14use crate::bit::BitSliceIterator;
15use crate::bit::UnalignedBitChunk;
16use crate::bit::buf_mut::fill_bits;
17use crate::bit::count_ones::count_ones;
18use crate::bit::get_bit_unchecked;
19use crate::bit::select::bit_select;
20use crate::bit::set_bit_unchecked;
21use crate::bit::unset_bit_unchecked;
22
23#[inline]
25fn resolve_range(range: impl RangeBounds<usize>, len: usize) -> (usize, usize) {
26 let start = match range.start_bound() {
27 Bound::Included(&s) => s,
28 Bound::Excluded(&s) => s + 1,
29 Bound::Unbounded => 0,
30 };
31 let end = match range.end_bound() {
32 Bound::Included(&e) => e + 1,
33 Bound::Excluded(&e) => e,
34 Bound::Unbounded => len,
35 };
36
37 assert!(start <= end);
38 assert!(start <= len);
39 assert!(end <= len);
40 (start, end)
41}
42
43#[inline]
45fn normalize(buffer: &[u8], offset: usize) -> (&[u8], usize) {
46 let byte_offset = offset / 8;
47 (&buffer[byte_offset..], offset % 8)
48}
49
50#[derive(Debug, Clone, Copy)]
56pub struct BitBufferView<'a> {
57 buffer: &'a [u8],
58 offset: usize,
59 len: usize,
60}
61
62impl<'a> BitBufferView<'a> {
63 #[inline]
67 pub fn new(buffer: &'a [u8], len: usize) -> Self {
68 Self::new_with_offset(buffer, len, 0)
69 }
70
71 #[inline]
75 pub fn new_with_offset(buffer: &'a [u8], len: usize, offset: usize) -> Self {
76 assert!(
77 len.saturating_add(offset) <= buffer.len().saturating_mul(8),
78 "provided slice (len={}) not large enough to back BitBufferView with offset {offset} len {len}",
79 buffer.len()
80 );
81
82 let (buffer, offset) = normalize(buffer, offset);
83 Self {
84 buffer,
85 offset,
86 len,
87 }
88 }
89
90 #[inline]
92 pub fn from_meta(buffer: &'a [u8], meta: BitBufferMeta) -> Self {
93 Self::new_with_offset(buffer, meta.len(), meta.offset())
94 }
95
96 #[inline]
98 pub fn meta(&self) -> BitBufferMeta {
99 BitBufferMeta::new(self.offset, self.len)
100 }
101
102 #[inline]
104 pub fn len(&self) -> usize {
105 self.len
106 }
107
108 #[inline]
110 pub fn is_empty(&self) -> bool {
111 self.len == 0
112 }
113
114 #[allow(clippy::inline_always)]
116 #[inline(always)]
117 pub fn offset(&self) -> usize {
118 self.offset
119 }
120
121 #[allow(clippy::inline_always)]
123 #[inline(always)]
124 pub fn inner(&self) -> &'a [u8] {
125 self.buffer
126 }
127
128 #[inline]
132 pub fn value(&self, index: usize) -> bool {
133 assert!(index < self.len);
134 unsafe { self.value_unchecked(index) }
136 }
137
138 #[inline]
144 pub unsafe fn value_unchecked(&self, index: usize) -> bool {
145 unsafe { get_bit_unchecked(self.buffer.as_ptr(), index + self.offset) }
146 }
147
148 #[inline]
152 pub fn slice(&self, range: impl RangeBounds<usize>) -> BitBufferView<'a> {
153 let (start, end) = resolve_range(range, self.len);
154 BitBufferView::new_with_offset(self.buffer, end - start, self.offset + start)
155 }
156
157 #[inline]
160 pub fn unaligned_chunks(&self) -> UnalignedBitChunk<'a> {
161 UnalignedBitChunk::new(self.buffer, self.offset, self.len)
162 }
163
164 #[inline]
166 pub fn chunks(&self) -> BitChunks<'a> {
167 BitChunks::new(self.buffer, self.offset, self.len)
168 }
169
170 #[inline]
172 pub fn true_count(&self) -> usize {
173 count_ones(self.buffer, self.offset, self.len)
174 }
175
176 #[inline]
178 pub fn false_count(&self) -> usize {
179 self.len - self.true_count()
180 }
181
182 #[inline]
184 pub fn select(&self, nth: usize) -> Option<usize> {
185 bit_select(self.buffer, self.offset, self.len, nth)
186 }
187
188 #[inline]
190 pub fn iter(&self) -> BitIterator<'a> {
191 BitIterator::new(self.buffer, self.offset, self.len)
192 }
193
194 #[inline]
196 pub fn set_indices(&self) -> BitIndexIterator<'a> {
197 BitIndexIterator::new(self.buffer, self.offset, self.len)
198 }
199
200 #[inline]
202 pub fn set_slices(&self) -> BitSliceIterator<'a> {
203 BitSliceIterator::new(self.buffer, self.offset, self.len)
204 }
205
206 pub fn to_bit_buffer(&self) -> BitBuffer {
208 let bytes = (self.offset + self.len).div_ceil(8);
209 BitBuffer::new_with_offset(
210 ByteBuffer::copy_from(&self.buffer[..bytes]),
211 self.len,
212 self.offset,
213 )
214 }
215}
216
217impl<'a> IntoIterator for BitBufferView<'a> {
218 type Item = bool;
219 type IntoIter = BitIterator<'a>;
220
221 fn into_iter(self) -> Self::IntoIter {
222 self.iter()
223 }
224}
225
226impl PartialEq for BitBufferView<'_> {
227 fn eq(&self, other: &Self) -> bool {
228 if self.len != other.len {
229 return false;
230 }
231
232 self.chunks()
233 .iter_padded()
234 .zip(other.chunks().iter_padded())
235 .all(|(a, b)| a == b)
236 }
237}
238
239impl Eq for BitBufferView<'_> {}
240
241#[derive(Debug)]
248pub struct BitBufferMutView<'a> {
249 buffer: &'a mut [u8],
250 offset: usize,
251 len: usize,
252}
253
254impl<'a> BitBufferMutView<'a> {
255 #[inline]
259 pub fn new(buffer: &'a mut [u8], len: usize) -> Self {
260 Self::new_with_offset(buffer, len, 0)
261 }
262
263 #[inline]
267 pub fn new_with_offset(buffer: &'a mut [u8], len: usize, offset: usize) -> Self {
268 assert!(
269 len.saturating_add(offset) <= buffer.len().saturating_mul(8),
270 "provided slice (len={}) not large enough to back BitBufferMutView with offset {offset} len {len}",
271 buffer.len()
272 );
273
274 let byte_offset = offset / 8;
275 let offset = offset % 8;
276 Self {
277 buffer: &mut buffer[byte_offset..],
278 offset,
279 len,
280 }
281 }
282
283 #[inline]
285 pub fn as_view(&self) -> BitBufferView<'_> {
286 BitBufferView {
287 buffer: self.buffer,
288 offset: self.offset,
289 len: self.len,
290 }
291 }
292
293 #[inline]
295 pub fn len(&self) -> usize {
296 self.len
297 }
298
299 #[inline]
301 pub fn is_empty(&self) -> bool {
302 self.len == 0
303 }
304
305 #[allow(clippy::inline_always)]
307 #[inline(always)]
308 pub fn offset(&self) -> usize {
309 self.offset
310 }
311
312 #[inline]
314 pub fn as_slice(&self) -> &[u8] {
315 self.buffer
316 }
317
318 #[inline]
320 pub fn as_mut_slice(&mut self) -> &mut [u8] {
321 self.buffer
322 }
323
324 #[inline]
328 pub fn value(&self, index: usize) -> bool {
329 assert!(index < self.len);
330 unsafe { self.value_unchecked(index) }
332 }
333
334 #[inline]
340 pub unsafe fn value_unchecked(&self, index: usize) -> bool {
341 unsafe { get_bit_unchecked(self.buffer.as_ptr(), index + self.offset) }
342 }
343
344 #[inline]
346 pub fn true_count(&self) -> usize {
347 self.as_view().true_count()
348 }
349
350 #[inline]
352 pub fn false_count(&self) -> usize {
353 self.as_view().false_count()
354 }
355
356 #[inline]
358 pub fn iter(&self) -> BitIterator<'_> {
359 self.as_view().iter()
360 }
361
362 #[inline]
366 pub fn set_to(&mut self, index: usize, value: bool) {
367 if value {
368 self.set(index);
369 } else {
370 self.unset(index);
371 }
372 }
373
374 #[inline]
380 pub unsafe fn set_to_unchecked(&mut self, index: usize, value: bool) {
381 if value {
382 unsafe { self.set_unchecked(index) }
384 } else {
385 unsafe { self.unset_unchecked(index) }
387 }
388 }
389
390 #[inline]
394 pub fn set(&mut self, index: usize) {
395 assert!(index < self.len, "index {index} exceeds len {}", self.len);
396 unsafe { self.set_unchecked(index) };
398 }
399
400 #[inline]
404 pub fn unset(&mut self, index: usize) {
405 assert!(index < self.len, "index {index} exceeds len {}", self.len);
406 unsafe { self.unset_unchecked(index) };
408 }
409
410 #[inline]
416 pub unsafe fn set_unchecked(&mut self, index: usize) {
417 unsafe { set_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
419 }
420
421 #[inline]
427 pub unsafe fn unset_unchecked(&mut self, index: usize) {
428 unsafe { unset_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
430 }
431
432 #[allow(clippy::inline_always)]
436 #[inline(always)]
437 pub fn fill_range(&mut self, start: usize, end: usize, value: bool) {
438 assert!(end <= self.len, "end {end} exceeds len {}", self.len);
439 assert!(start <= end, "start {start} exceeds end {end}");
440 unsafe { self.fill_range_unchecked(start, end, value) }
442 }
443
444 #[allow(clippy::inline_always)]
450 #[inline(always)]
451 pub unsafe fn fill_range_unchecked(&mut self, start: usize, end: usize, value: bool) {
452 fill_bits(self.buffer, self.offset + start, self.offset + end, value);
453 }
454
455 pub fn to_bit_buffer(&self) -> BitBuffer {
457 self.as_view().to_bit_buffer()
458 }
459}
460
461impl BitBuffer {
462 #[inline]
464 pub fn as_view(&self) -> BitBufferView<'_> {
465 BitBufferView {
466 buffer: self.inner().as_slice(),
467 offset: self.offset(),
468 len: self.len(),
469 }
470 }
471}
472
473impl BitBufferMut {
474 #[inline]
476 pub fn as_view(&self) -> BitBufferView<'_> {
477 BitBufferView {
478 buffer: self.as_slice(),
479 offset: self.offset(),
480 len: self.len(),
481 }
482 }
483
484 #[inline]
486 pub fn as_mut_view(&mut self) -> BitBufferMutView<'_> {
487 let offset = self.offset();
488 let len = self.len();
489 BitBufferMutView {
490 buffer: self.as_mut_slice(),
491 offset,
492 len,
493 }
494 }
495}
496
497#[cfg(test)]
498mod tests {
499 use crate::BitBuffer;
500 use crate::BitBufferMut;
501 use crate::bitbuffer;
502
503 #[test]
504 fn view_reads_match_buffer() {
505 let buffer = bitbuffer![true, false, true, true, false, true, false, false];
506 let view = buffer.as_view();
507
508 assert_eq!(view.len(), buffer.len());
509 assert_eq!(view.true_count(), buffer.true_count());
510 assert_eq!(view.false_count(), buffer.false_count());
511 for i in 0..buffer.len() {
512 assert_eq!(view.value(i), buffer.value(i));
513 }
514 assert_eq!(
515 view.iter().collect::<Vec<_>>(),
516 buffer.iter().collect::<Vec<_>>()
517 );
518 }
519
520 #[test]
521 fn view_slice_preserves_offset() {
522 let buffer = BitBuffer::new_set(20);
523 let sliced = buffer.slice(5..17);
524 let view = buffer.as_view().slice(5..17);
525
526 assert_eq!(view.len(), sliced.len());
527 assert_eq!(view.true_count(), sliced.true_count());
528 assert_eq!(view.to_bit_buffer(), sliced);
529 }
530
531 #[test]
532 fn view_offset_buffer() {
533 let buffer = BitBuffer::new_set(64).slice(3..40);
534 let view = buffer.as_view();
535 assert_eq!(view.offset(), buffer.offset());
536 assert_eq!(view.len(), buffer.len());
537 assert_eq!(view.to_bit_buffer(), buffer);
538 }
539
540 #[test]
541 fn mut_view_set_unset() {
542 let mut buffer = BitBufferMut::new_unset(16);
543 {
544 let mut view = buffer.as_mut_view();
545 view.set(0);
546 view.set(15);
547 view.set_to(7, true);
548 view.fill_range(2, 5, true);
549 assert!(view.value(0));
550 assert_eq!(view.true_count(), 6);
551 view.unset(0);
552 }
553 let frozen = buffer.freeze();
554 assert!(!frozen.value(0));
555 assert!(frozen.value(2));
556 assert!(frozen.value(4));
557 assert!(frozen.value(7));
558 assert!(frozen.value(15));
559 assert_eq!(frozen.true_count(), 5);
560 }
561
562 #[test]
563 fn mut_view_with_offset() {
564 let mut buffer = BitBufferMut::from_buffer(crate::buffer_mut![0u8; 4], 3, 20);
565 {
566 let mut view = buffer.as_mut_view();
567 assert_eq!(view.offset(), 3);
568 view.fill_range(0, 20, true);
569 }
570 let frozen = buffer.freeze();
571 assert_eq!(frozen.true_count(), 20);
572 }
573}