1mod container;
71#[cfg(any(test, feature = "fuzz"))]
72commonware_macros::stability_mod!(ALPHA, pub mod fuzz);
73mod ops;
74mod prunable;
75
76#[cfg(not(feature = "std"))]
77use alloc::collections::BTreeMap;
78use bytes::{Buf, BufMut};
79use commonware_codec::{EncodeSize, Error as CodecError, RangeCfg, Read, Write};
80use container::Container;
81use core::ops::Range;
82pub use prunable::Prunable;
83#[cfg(feature = "std")]
84use std::collections::BTreeMap;
85
86const MAX_KEY: u64 = (1u64 << 48) - 1;
88
89const fn high_bits(value: u64) -> u64 {
91 value >> 16
92}
93
94const fn low_bits(value: u64) -> u16 {
96 value as u16
97}
98
99const fn combine(key: u64, index: u16) -> u64 {
101 (key << 16) | (index as u64)
102}
103
104#[derive(Clone, Debug, Default, PartialEq, Eq)]
129pub struct Bitmap {
130 containers: BTreeMap<u64, Container>,
132}
133
134impl Bitmap {
135 fn from_containers(containers: BTreeMap<u64, Container>) -> Result<Self, CodecError> {
136 if let Some((&max_key, _)) = containers.last_key_value() {
137 if max_key > MAX_KEY {
138 return Err(CodecError::Invalid(
139 "Bitmap",
140 "container key exceeds 48-bit range",
141 ));
142 }
143 }
144
145 if containers.values().any(|c| c.is_empty()) {
146 return Err(CodecError::Invalid("Bitmap", "empty container"));
147 }
148
149 Ok(Self { containers })
150 }
151
152 pub const fn new() -> Self {
154 Self {
155 containers: BTreeMap::new(),
156 }
157 }
158
159 pub fn len(&self) -> u64 {
161 self.containers.values().map(|c| c.len() as u64).sum()
162 }
163
164 pub fn is_empty(&self) -> bool {
166 self.containers.is_empty()
167 }
168
169 pub fn container_count(&self) -> usize {
171 self.containers.len()
172 }
173
174 pub fn clear(&mut self) {
176 self.containers.clear();
177 }
178
179 pub fn contains(&self, value: u64) -> bool {
181 let key = high_bits(value);
182 let index = low_bits(value);
183 self.containers.get(&key).is_some_and(|c| c.contains(index))
184 }
185
186 pub fn insert(&mut self, value: u64) -> bool {
190 let key = high_bits(value);
191 let index = low_bits(value);
192 self.containers.entry(key).or_default().insert(index)
193 }
194
195 pub fn insert_range(&mut self, range: Range<u64>) -> u64 {
199 let Range { start, end } = range;
200 if start >= end {
201 return 0;
202 }
203
204 let start_key = high_bits(start);
205 let end_key = high_bits(end - 1);
206 let mut inserted = 0u64;
207
208 for key in start_key..=end_key {
209 let container_start = if key == start_key { low_bits(start) } else { 0 };
210 let container_end = if key == end_key {
211 let last_value = low_bits(end - 1);
212 if last_value == u16::MAX {
213 None
214 } else {
215 Some(last_value + 1)
216 }
217 } else {
218 None
219 };
220
221 let container = self.containers.entry(key).or_default();
222 if container_start == 0 && container_end.is_none() {
223 inserted += container::bitmap::BITS as u64 - container.len() as u64;
224 *container = Container::Run(container::Run::full());
225 continue;
226 }
227 match container_end {
228 Some(container_end) => {
229 inserted += container.insert_range(container_start..container_end) as u64;
230 }
231 None => {
232 inserted += container.insert_range(container_start..u16::MAX) as u64;
233 if container.insert(u16::MAX) {
234 inserted += 1;
235 }
236 }
237 }
238 }
239
240 inserted
241 }
242
243 pub fn iter(&self) -> impl Iterator<Item = u64> + '_ {
245 self.containers
246 .iter()
247 .flat_map(|(&key, container)| container.iter().map(move |index| combine(key, index)))
248 }
249
250 pub fn iter_range(&self, range: Range<u64>) -> impl Iterator<Item = u64> + '_ {
252 let Range { start, end } = range;
253 let start_key = high_bits(start);
254 let end_key_exclusive = if start >= end {
255 start_key
256 } else {
257 high_bits(end - 1) + 1
258 };
259 let end_key = end_key_exclusive.saturating_sub(1);
260
261 self.containers
262 .range(start_key..end_key_exclusive)
263 .flat_map(move |(&key, container)| {
264 let container_start = if key == start_key { low_bits(start) } else { 0 };
265 let container_end = if key == end_key {
266 low_bits(end - 1) as u32 + 1
267 } else {
268 container::bitmap::BITS
269 };
270 container
271 .iter_range(container_start as u32..container_end)
272 .map(move |index| combine(key, index))
273 })
274 }
275
276 pub fn min(&self) -> Option<u64> {
278 self.containers
279 .first_key_value()
280 .and_then(|(&key, container)| container.min().map(|index| combine(key, index)))
281 }
282
283 pub fn max(&self) -> Option<u64> {
285 self.containers
286 .last_key_value()
287 .and_then(|(&key, container)| container.max().map(|index| combine(key, index)))
288 }
289
290 #[cfg(test)]
291 const fn containers(&self) -> &BTreeMap<u64, Container> {
292 &self.containers
293 }
294
295 fn truncate_containers_below(&mut self, target_key: u64) {
297 let kept = self.containers.split_off(&target_key);
299 self.containers = kept;
300 }
301
302 #[cfg(any(test, feature = "analysis"))]
306 pub fn container_variant_counts(&self) -> (usize, usize, usize) {
307 let mut counts = (0, 0, 0);
308 for container in self.containers.values() {
309 match container {
310 Container::Array(_) => counts.0 += 1,
311 Container::Bitmap(_) => counts.1 += 1,
312 Container::Run(_) => counts.2 += 1,
313 }
314 }
315 counts
316 }
317}
318
319impl Extend<u64> for Bitmap {
320 fn extend<I: IntoIterator<Item = u64>>(&mut self, iter: I) {
321 for value in iter {
322 self.insert(value);
323 }
324 }
325}
326
327impl FromIterator<u64> for Bitmap {
328 fn from_iter<I: IntoIterator<Item = u64>>(iter: I) -> Self {
329 let mut bitmap = Self::new();
330 bitmap.extend(iter);
331 bitmap
332 }
333}
334
335impl Write for Bitmap {
336 fn write(&self, buf: &mut impl BufMut) {
337 self.containers.write(buf);
338 }
339}
340
341impl EncodeSize for Bitmap {
342 fn encode_size(&self) -> usize {
343 self.containers.encode_size()
344 }
345}
346
347impl Read for Bitmap {
348 type Cfg = RangeCfg<usize>;
352
353 fn read_cfg(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, CodecError> {
354 let containers = BTreeMap::<u64, Container>::read_cfg(buf, &(*cfg, ((), ())))?;
356 Self::from_containers(containers)
357 }
358}
359
360#[cfg(feature = "arbitrary")]
361impl arbitrary::Arbitrary<'_> for Bitmap {
362 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
363 let num_containers = u.int_in_range(0..=1000)?;
364 let mut containers = BTreeMap::new();
365 let mut prev_key = 0u64;
366
367 for _ in 0..num_containers {
368 let key = if containers.is_empty() {
370 u.int_in_range(0..=MAX_KEY)?
371 } else {
372 let remaining = MAX_KEY - prev_key;
373 if remaining == 0 {
374 break;
375 }
376 prev_key.saturating_add(u.int_in_range(1..=remaining)?)
377 };
378 if key > MAX_KEY {
379 break;
380 }
381 let container = Container::arbitrary(u)?;
386 if container.is_empty() {
387 continue;
388 }
389 containers.insert(key, container);
390 prev_key = key;
391 }
392
393 Ok(Self { containers })
394 }
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400 use commonware_codec::Encode;
401
402 #[test]
403 fn test_new_and_empty() {
404 let bitmap = Bitmap::new();
405 assert!(bitmap.is_empty());
406 assert_eq!(bitmap.len(), 0);
407 assert_eq!(bitmap.container_count(), 0);
408 }
409
410 #[test]
411 fn test_insert_and_contains() {
412 let mut bitmap = Bitmap::new();
413
414 assert!(bitmap.insert(42));
415 assert!(bitmap.insert(100));
416 assert!(bitmap.insert(1000000));
417 assert!(!bitmap.insert(42)); assert_eq!(bitmap.len(), 3);
420 assert!(bitmap.contains(42));
421 assert!(bitmap.contains(100));
422 assert!(bitmap.contains(1000000));
423 assert!(!bitmap.contains(50));
424 }
425
426 #[test]
427 fn test_insert_range() {
428 let mut bitmap = Bitmap::new();
429
430 let inserted = bitmap.insert_range(100..200);
431 assert_eq!(inserted, 100);
432 assert_eq!(bitmap.len(), 100);
433
434 for i in 100..200 {
435 assert!(bitmap.contains(i), "missing value {}", i);
436 }
437 assert!(!bitmap.contains(99));
438 assert!(!bitmap.contains(200));
439 }
440
441 #[test]
442 fn test_insert_range_spanning_containers() {
443 let mut bitmap = Bitmap::new();
444
445 let start = 65530; let end = 65550; let inserted = bitmap.insert_range(start..end);
449 assert_eq!(inserted, 20);
450
451 for i in start..end {
452 assert!(bitmap.contains(i), "missing value {}", i);
453 }
454 }
455
456 #[test]
457 fn test_iterator() {
458 let mut bitmap = Bitmap::new();
459 bitmap.insert(100);
460 bitmap.insert(10);
461 bitmap.insert(1000);
462 bitmap.insert(5);
463
464 let values: Vec<_> = bitmap.iter().collect();
465 assert_eq!(values, vec![5, 10, 100, 1000]);
466 }
467
468 #[test]
469 fn test_iter_range() {
470 let mut bitmap = Bitmap::new();
471 for i in 0..100 {
472 bitmap.insert(i);
473 }
474
475 let values: Vec<_> = bitmap.iter_range(25..75).collect();
476 assert_eq!(values.len(), 50);
477 assert_eq!(values[0], 25);
478 assert_eq!(values[49], 74);
479 }
480
481 #[test]
482 fn test_iter_range_reversed_cross_container_empty() {
483 let mut bitmap = Bitmap::new();
484 bitmap.insert(1);
485 bitmap.insert(70_000);
486
487 let start = 70_000;
488 let end = 10;
489 let values: Vec<_> = bitmap.iter_range(start..end).collect();
490 assert!(values.is_empty());
491 }
492
493 #[test]
494 fn test_min_max() {
495 let mut bitmap = Bitmap::new();
496 assert_eq!(bitmap.min(), None);
497 assert_eq!(bitmap.max(), None);
498
499 bitmap.insert(50);
500 bitmap.insert(10);
501 bitmap.insert(100);
502
503 assert_eq!(bitmap.min(), Some(10));
504 assert_eq!(bitmap.max(), Some(100));
505 }
506
507 #[test]
508 fn test_clear() {
509 let mut bitmap = Bitmap::new();
510 bitmap.insert(1);
511 bitmap.insert(2);
512 bitmap.insert(3);
513
514 bitmap.clear();
515 assert!(bitmap.is_empty());
516 assert_eq!(bitmap.len(), 0);
517 }
518
519 #[test]
520 fn test_from_iter_empty() {
521 let bitmap: Bitmap = core::iter::empty::<u64>().collect();
522 assert!(bitmap.is_empty());
523 }
524
525 #[test]
526 fn test_from_iter_basic() {
527 let bitmap: Bitmap = [5u64, 10, 15, 100].into_iter().collect();
528 assert_eq!(bitmap.len(), 4);
529 let values: Vec<_> = bitmap.iter().collect();
530 assert_eq!(values, vec![5, 10, 15, 100]);
531 }
532
533 #[test]
534 fn test_from_iter_unsorted_with_duplicates() {
535 let bitmap: Bitmap = [100u64, 5, 100, 50, 5, 10].into_iter().collect();
537 assert_eq!(bitmap.len(), 4);
538 let values: Vec<_> = bitmap.iter().collect();
539 assert_eq!(values, vec![5, 10, 50, 100]);
540 }
541
542 #[test]
543 fn test_from_iter_range_expression() {
544 let bitmap: Bitmap = (0u64..1000).collect();
546 assert_eq!(bitmap.len(), 1000);
547 assert!(bitmap.contains(0));
548 assert!(bitmap.contains(999));
549 assert!(!bitmap.contains(1000));
550 }
551
552 #[test]
553 fn test_from_iter_multi_container() {
554 let bitmap: Bitmap = [1u64, 65_537, 131_073, 1_000_000].into_iter().collect();
556 assert_eq!(bitmap.len(), 4);
557 assert_eq!(bitmap.container_count(), 4);
558 }
559
560 #[test]
561 fn test_extend_into_existing() {
562 let mut bitmap: Bitmap = [1u64, 2, 3].into_iter().collect();
563 bitmap.extend([3u64, 4, 5]);
564 let values: Vec<_> = bitmap.iter().collect();
565 assert_eq!(values, vec![1, 2, 3, 4, 5]);
566 }
567
568 #[test]
569 fn test_high_low_bits() {
570 assert_eq!(high_bits(0), 0);
572 assert_eq!(low_bits(0), 0);
573
574 assert_eq!(high_bits(65535), 0);
575 assert_eq!(low_bits(65535), 65535);
576
577 assert_eq!(high_bits(65536), 1);
578 assert_eq!(low_bits(65536), 0);
579
580 assert_eq!(high_bits(u64::MAX), (1u64 << 48) - 1);
581 assert_eq!(low_bits(u64::MAX), u16::MAX);
582 }
583
584 #[test]
585 fn test_combine() {
586 assert_eq!(combine(0, 0), 0);
587 assert_eq!(combine(0, 65535), 65535);
588 assert_eq!(combine(1, 0), 65536);
589 assert_eq!(combine(1, 1), 65537);
590 }
591
592 #[test]
593 fn test_large_values() {
594 let mut bitmap = Bitmap::new();
595
596 let large_value = 1u64 << 40;
597 bitmap.insert(large_value);
598 bitmap.insert(large_value + 1);
599 bitmap.insert(large_value + 1000);
600
601 assert!(bitmap.contains(large_value));
602 assert!(bitmap.contains(large_value + 1));
603 assert!(bitmap.contains(large_value + 1000));
604 assert!(!bitmap.contains(large_value + 2));
605 }
606
607 #[test]
608 fn test_codec_roundtrip_empty() {
609 use commonware_codec::{Decode, Encode};
610
611 let bitmap = Bitmap::new();
612 let encoded = bitmap.encode();
613 let decoded = Bitmap::decode_cfg(encoded, &(..).into()).unwrap();
614 assert_eq!(bitmap, decoded);
615 }
616
617 #[test]
618 fn test_codec_roundtrip_sparse() {
619 use commonware_codec::{Decode, Encode};
620
621 let mut bitmap = Bitmap::new();
622 bitmap.insert(42);
623 bitmap.insert(100);
624 bitmap.insert(1000000);
625
626 let encoded = bitmap.encode();
627 let decoded = Bitmap::decode_cfg(encoded, &(..).into()).unwrap();
628 assert_eq!(bitmap, decoded);
629 }
630
631 #[test]
632 fn test_codec_roundtrip_dense() {
633 use commonware_codec::{Decode, Encode};
634
635 let mut bitmap = Bitmap::new();
636 bitmap.insert_range(0..5000);
637
638 let encoded = bitmap.encode();
639 let decoded = Bitmap::decode_cfg(encoded, &(..).into()).unwrap();
640 assert_eq!(bitmap, decoded);
641 }
642
643 #[test]
644 fn test_codec_roundtrip_multiple_containers() {
645 use commonware_codec::{Decode, Encode};
646
647 let mut bitmap = Bitmap::new();
648 bitmap.insert_range(0..100);
649 bitmap.insert_range(65536..65636);
650 bitmap.insert(1u64 << 40);
651
652 let encoded = bitmap.encode();
653 let decoded = Bitmap::decode_cfg(encoded, &(..).into()).unwrap();
654 assert_eq!(bitmap, decoded);
655 }
656
657 #[test]
658 fn test_codec_roundtrip_large_mixed_variants() {
659 use commonware_codec::{Decode, Encode};
664
665 let mut bitmap = Bitmap::new();
666
667 for shelf in 0..200u64 {
669 let base = shelf * 65_536;
670 for i in 0..100u64 {
671 bitmap.insert(base + i * 500);
672 }
673 }
674
675 for shelf in 200..400u64 {
678 let base = shelf * 65_536;
679 for i in 0..5_000u64 {
680 bitmap.insert(base + i * 2);
681 }
682 }
683
684 for shelf in 400..600u64 {
687 let base = shelf * 65_536;
688 bitmap.insert_range(base..base + 50_000);
689 }
690
691 assert_eq!(bitmap.container_count(), 600);
692
693 let (arrays, bitmaps, runs) = bitmap.container_variant_counts();
694 assert!(
695 arrays > 0 && bitmaps > 0 && runs > 0,
696 "expected all three variants, got A={arrays} B={bitmaps} R={runs}"
697 );
698
699 let encoded = bitmap.encode();
700 let decoded = Bitmap::decode_cfg(encoded, &(..=1000usize).into()).unwrap();
701 assert_eq!(decoded, bitmap);
702 }
703
704 #[test]
705 fn test_codec_container_limit() {
706 use commonware_codec::{Decode, Encode, Error};
707
708 let mut bitmap = Bitmap::new();
709 bitmap.insert(0);
711 bitmap.insert(65536);
712 bitmap.insert(131072);
713 assert_eq!(bitmap.container_count(), 3);
714
715 let encoded = bitmap.encode();
716
717 let decoded = Bitmap::decode_cfg(encoded.clone(), &(..=3).into()).unwrap();
719 assert_eq!(bitmap, decoded);
720
721 let result = Bitmap::decode_cfg(encoded, &(..=2).into());
723 assert!(matches!(result, Err(Error::InvalidLength(3))));
724 }
725
726 #[test]
727 fn test_from_containers_rejects_out_of_range_key() {
728 use commonware_codec::Error;
729
730 let mut malformed: BTreeMap<u64, Container> = BTreeMap::new();
731 let mut container = Container::new();
732 container.insert(0);
733 malformed.insert(1u64 << 48, container);
734
735 let result = Bitmap::from_containers(malformed);
736 assert!(
737 matches!(
738 result,
739 Err(Error::Invalid("Bitmap", msg)) if msg.contains("48-bit")
740 ),
741 "expected Invalid(\"Bitmap\", ...), got {result:?}"
742 );
743 }
744
745 #[test]
746 fn test_from_containers_accepts_in_range_keys() {
747 let mut map: BTreeMap<u64, Container> = BTreeMap::new();
748 let mut container = Container::new();
749 container.insert(42);
750 map.insert(MAX_KEY, container);
751
752 let bm = Bitmap::from_containers(map).unwrap();
753 assert!(bm.contains(combine(MAX_KEY, 42)));
754 }
755
756 #[test]
757 fn test_from_containers_rejects_empty_container() {
758 use commonware_codec::Error;
762
763 let mut map: BTreeMap<u64, Container> = BTreeMap::new();
764 map.insert(0, Container::new());
765
766 let result = Bitmap::from_containers(map);
767 assert!(
768 matches!(result, Err(Error::Invalid("Bitmap", "empty container"))),
769 "expected Invalid(\"Bitmap\", \"empty container\"), got {result:?}"
770 );
771 }
772
773 #[test]
774 fn test_decode_rejects_out_of_range_key() {
775 use commonware_codec::{Decode, Encode, Error};
776
777 let mut malformed: BTreeMap<u64, Container> = BTreeMap::new();
778 let mut container = Container::new();
779 container.insert(0);
780 malformed.insert(1u64 << 48, container);
781
782 let bytes = malformed.encode();
784
785 let result = Bitmap::decode_cfg(bytes, &(..=10usize).into());
786 assert!(
787 matches!(
788 result,
789 Err(Error::Invalid("Bitmap", msg)) if msg.contains("48-bit")
790 ),
791 "expected Invalid(\"Bitmap\", ...), got {result:?}"
792 );
793 }
794
795 #[test]
796 fn test_insert_range_at_container_boundary_regression() {
797 let mut bitmap = Bitmap::new();
806 let inserted = bitmap.insert_range(0..65536);
807 assert_eq!(inserted, 65536);
808 assert_eq!(bitmap.len(), 65536);
809 for i in 0u64..65536 {
810 assert!(bitmap.contains(i), "missing value {}", i);
811 }
812 assert!(!bitmap.contains(65536));
813
814 let mut bitmap = Bitmap::new();
816 let inserted = bitmap.insert_range(65000..65536);
817 assert_eq!(inserted, 536);
818 assert_eq!(bitmap.len(), 536);
819 for i in 65000u64..65536 {
820 assert!(bitmap.contains(i), "missing value {}", i);
821 }
822
823 let mut bitmap = Bitmap::new();
825 let inserted = bitmap.insert_range(65530..131072);
826 assert_eq!(inserted, 65542);
827 assert_eq!(bitmap.len(), 65542);
828 for i in 65530u64..131072 {
829 assert!(bitmap.contains(i), "missing value {}", i);
830 }
831
832 let start: u64 = 18446744071497449473;
834 let len: u16 = 65535;
835 let end = start.saturating_add(len as u64);
836 let expected_len = end - start;
837
838 let mut bitmap = Bitmap::new();
839 let inserted = bitmap.insert_range(start..end);
840 assert_eq!(inserted, expected_len);
841 assert_eq!(bitmap.len(), expected_len);
842 }
843
844 #[test]
845 fn test_encode_size_empty() {
846 let bm = Bitmap::new();
847 assert_eq!(bm.encode_size(), bm.encode().len());
848 }
849
850 #[test]
851 fn test_encode_size_grows_with_containers() {
852 let mut bm = Bitmap::new();
853 let s0 = bm.encode_size();
854 bm.insert(0);
856 bm.insert(65_536);
857 bm.insert(131_072);
858 let s3 = bm.encode_size();
859 assert_eq!(bm.container_count(), 3);
860 assert!(s3 > s0);
861 assert_eq!(s3, bm.encode().len());
862 }
863
864 #[test]
865 fn test_encode_size_dense_uses_bitmap_container() {
866 let mut bm = Bitmap::new();
870 for i in 0u64..5000 {
871 bm.insert(i * 2);
872 }
873 assert!(bm.encode_size() >= 8192);
875 assert_eq!(bm.encode_size(), bm.encode().len());
876 }
877
878 #[cfg(feature = "arbitrary")]
879 mod conformance {
880 use commonware_codec::conformance::CodecConformance;
881
882 commonware_conformance::conformance_tests! {
883 CodecConformance<super::Bitmap>,
884 }
885 }
886}