1#![forbid(unsafe_code)]
2
3const ARRAY_TO_BITMAP_THRESHOLD: usize = 4096;
33
34#[derive(Clone, Debug)]
40struct ArrayContainer {
41 values: Vec<u16>,
42}
43
44impl ArrayContainer {
45 fn new() -> Self {
46 Self { values: Vec::new() }
47 }
48
49 fn insert(&mut self, value: u16) -> bool {
50 match self.values.binary_search(&value) {
51 Ok(_) => false, Err(pos) => {
53 self.values.insert(pos, value);
54 true
55 }
56 }
57 }
58
59 fn contains(&self, value: u16) -> bool {
60 self.values.binary_search(&value).is_ok()
61 }
62
63 fn cardinality(&self) -> usize {
64 self.values.len()
65 }
66
67 fn should_promote(&self) -> bool {
68 self.values.len() >= ARRAY_TO_BITMAP_THRESHOLD
69 }
70
71 fn to_bitmap(&self) -> BitmapContainer {
73 let mut bitmap = BitmapContainer::new();
74 for &v in &self.values {
75 bitmap.insert(v);
76 }
77 bitmap
78 }
79}
80
81#[derive(Clone, Debug)]
83struct BitmapContainer {
84 words: Box<[u64; 1024]>,
85 count: usize,
86}
87
88impl BitmapContainer {
89 fn new() -> Self {
90 Self {
91 words: Box::new([0u64; 1024]),
92 count: 0,
93 }
94 }
95
96 fn insert(&mut self, value: u16) -> bool {
97 let word_idx = (value >> 6) as usize;
98 let bit = 1u64 << (value & 63);
99 if self.words[word_idx] & bit == 0 {
100 self.words[word_idx] |= bit;
101 self.count += 1;
102 true
103 } else {
104 false
105 }
106 }
107
108 fn contains(&self, value: u16) -> bool {
109 let word_idx = (value >> 6) as usize;
110 let bit = 1u64 << (value & 63);
111 self.words[word_idx] & bit != 0
112 }
113
114 fn cardinality(&self) -> usize {
115 self.count
116 }
117
118 fn iter(&self) -> BitmapIter<'_> {
119 BitmapIter {
120 words: &self.words,
121 word_idx: 0,
122 current_word: 0,
123 started: false,
124 }
125 }
126}
127
128struct BitmapIter<'a> {
129 words: &'a [u64; 1024],
130 word_idx: usize,
131 current_word: u64,
132 started: bool,
133}
134
135impl Iterator for BitmapIter<'_> {
136 type Item = u16;
137
138 fn next(&mut self) -> Option<u16> {
139 if !self.started {
140 if self.word_idx < 1024 {
141 self.current_word = self.words[0];
142 }
143 self.started = true;
144 }
145
146 loop {
147 if self.current_word != 0 {
148 let bit = self.current_word.trailing_zeros() as u16;
149 self.current_word &= self.current_word - 1; return Some((self.word_idx as u16) * 64 + bit);
151 }
152 self.word_idx += 1;
153 if self.word_idx >= 1024 {
154 return None;
155 }
156 self.current_word = self.words[self.word_idx];
157 }
158 }
159}
160
161#[derive(Clone, Debug)]
166enum Container {
167 Array(ArrayContainer),
168 Bitmap(BitmapContainer),
169}
170
171impl Container {
172 fn new_array() -> Self {
173 Self::Array(ArrayContainer::new())
174 }
175
176 fn insert(&mut self, value: u16) -> bool {
177 match self {
178 Self::Array(arr) => {
179 let inserted = arr.insert(value);
180 if arr.should_promote() {
181 *self = Self::Bitmap(arr.to_bitmap());
182 }
183 inserted
184 }
185 Self::Bitmap(bm) => bm.insert(value),
186 }
187 }
188
189 fn contains(&self, value: u16) -> bool {
190 match self {
191 Self::Array(arr) => arr.contains(value),
192 Self::Bitmap(bm) => bm.contains(value),
193 }
194 }
195
196 fn cardinality(&self) -> usize {
197 match self {
198 Self::Array(arr) => arr.cardinality(),
199 Self::Bitmap(bm) => bm.cardinality(),
200 }
201 }
202}
203
204#[derive(Clone, Debug)]
210struct ContainerEntry {
211 key: u16,
212 container: Container,
213}
214
215#[derive(Clone, Debug)]
221pub struct RoaringBitmap {
222 containers: Vec<ContainerEntry>,
223}
224
225impl RoaringBitmap {
226 #[must_use]
228 pub fn new() -> Self {
229 Self {
230 containers: Vec::new(),
231 }
232 }
233
234 pub fn insert(&mut self, value: u32) -> bool {
236 let key = (value >> 16) as u16;
237 let low = value as u16;
238
239 match self.containers.binary_search_by_key(&key, |e| e.key) {
240 Ok(idx) => self.containers[idx].container.insert(low),
241 Err(idx) => {
242 let mut entry = ContainerEntry {
243 key,
244 container: Container::new_array(),
245 };
246 entry.container.insert(low);
247 self.containers.insert(idx, entry);
248 true
249 }
250 }
251 }
252
253 #[must_use]
255 pub fn contains(&self, value: u32) -> bool {
256 let key = (value >> 16) as u16;
257 let low = value as u16;
258
259 match self.containers.binary_search_by_key(&key, |e| e.key) {
260 Ok(idx) => self.containers[idx].container.contains(low),
261 Err(_) => false,
262 }
263 }
264
265 #[must_use]
267 pub fn cardinality(&self) -> usize {
268 self.containers
269 .iter()
270 .map(|e| e.container.cardinality())
271 .sum()
272 }
273
274 #[must_use]
276 pub fn is_empty(&self) -> bool {
277 self.containers
278 .iter()
279 .all(|e| e.container.cardinality() == 0)
280 }
281
282 pub fn clear(&mut self) {
284 self.containers.clear();
285 }
286
287 pub fn iter(&self) -> RoaringIter<'_> {
289 RoaringIter {
290 containers: &self.containers,
291 container_idx: 0,
292 inner: InnerIter::Empty,
293 }
294 }
295
296 #[must_use]
298 pub fn union(&self, other: &Self) -> Self {
299 let mut result = self.clone();
300 for value in other.iter() {
301 result.insert(value);
302 }
303 result
304 }
305
306 #[must_use]
308 pub fn intersection(&self, other: &Self) -> Self {
309 let mut result = Self::new();
310 let (smaller, larger) = if self.cardinality() <= other.cardinality() {
312 (self, other)
313 } else {
314 (other, self)
315 };
316 for value in smaller.iter() {
317 if larger.contains(value) {
318 result.insert(value);
319 }
320 }
321 result
322 }
323
324 pub fn insert_range(&mut self, start: u32, end: u32) {
326 for value in start..end {
327 self.insert(value);
328 }
329 }
330}
331
332impl Default for RoaringBitmap {
333 fn default() -> Self {
334 Self::new()
335 }
336}
337
338enum InnerIter<'a> {
343 Empty,
344 Array {
345 key: u16,
346 iter: std::slice::Iter<'a, u16>,
347 },
348 Bitmap {
349 key: u16,
350 iter: BitmapIter<'a>,
351 },
352}
353
354pub struct RoaringIter<'a> {
356 containers: &'a [ContainerEntry],
357 container_idx: usize,
358 inner: InnerIter<'a>,
359}
360
361impl Iterator for RoaringIter<'_> {
362 type Item = u32;
363
364 fn next(&mut self) -> Option<u32> {
365 loop {
366 match &mut self.inner {
367 InnerIter::Empty => {}
368 InnerIter::Array { key, iter } => {
369 if let Some(&low) = iter.next() {
370 return Some(((*key as u32) << 16) | low as u32);
371 }
372 }
373 InnerIter::Bitmap { key, iter } => {
374 if let Some(low) = iter.next() {
375 return Some(((*key as u32) << 16) | low as u32);
376 }
377 }
378 }
379
380 if self.container_idx >= self.containers.len() {
382 return None;
383 }
384 let entry = &self.containers[self.container_idx];
385 self.container_idx += 1;
386
387 self.inner = match &entry.container {
388 Container::Array(arr) => InnerIter::Array {
389 key: entry.key,
390 iter: arr.values.iter(),
391 },
392 Container::Bitmap(bm) => InnerIter::Bitmap {
393 key: entry.key,
394 iter: bm.iter(),
395 },
396 };
397 }
398 }
399}
400
401#[cfg(test)]
406mod tests {
407 use super::*;
408
409 #[test]
410 fn empty_bitmap() {
411 let bm = RoaringBitmap::new();
412 assert_eq!(bm.cardinality(), 0);
413 assert!(bm.is_empty());
414 assert!(!bm.contains(0));
415 assert_eq!(bm.iter().count(), 0);
416 }
417
418 #[test]
419 fn insert_and_contains() {
420 let mut bm = RoaringBitmap::new();
421 assert!(bm.insert(42));
422 assert!(!bm.insert(42)); assert!(bm.contains(42));
424 assert!(!bm.contains(43));
425 assert_eq!(bm.cardinality(), 1);
426 }
427
428 #[test]
429 fn insert_multiple_containers() {
430 let mut bm = RoaringBitmap::new();
431 bm.insert(0);
433 bm.insert(65536); bm.insert(131072); assert_eq!(bm.cardinality(), 3);
437 assert!(bm.contains(0));
438 assert!(bm.contains(65536));
439 assert!(bm.contains(131072));
440 }
441
442 #[test]
443 fn iteration_order() {
444 let mut bm = RoaringBitmap::new();
445 bm.insert(100);
446 bm.insert(5);
447 bm.insert(50);
448 bm.insert(1);
449
450 let values: Vec<u32> = bm.iter().collect();
451 assert_eq!(values, vec![1, 5, 50, 100]);
452 }
453
454 #[test]
455 fn iteration_across_containers() {
456 let mut bm = RoaringBitmap::new();
457 bm.insert(65537); bm.insert(10); bm.insert(65536); let values: Vec<u32> = bm.iter().collect();
462 assert_eq!(values, vec![10, 65536, 65537]);
463 }
464
465 #[test]
466 fn clear() {
467 let mut bm = RoaringBitmap::new();
468 bm.insert(1);
469 bm.insert(2);
470 bm.insert(3);
471 bm.clear();
472 assert_eq!(bm.cardinality(), 0);
473 assert!(bm.is_empty());
474 }
475
476 #[test]
477 fn union_basic() {
478 let mut a = RoaringBitmap::new();
479 a.insert(1);
480 a.insert(3);
481
482 let mut b = RoaringBitmap::new();
483 b.insert(2);
484 b.insert(3);
485
486 let c = a.union(&b);
487 assert_eq!(c.cardinality(), 3);
488 assert!(c.contains(1));
489 assert!(c.contains(2));
490 assert!(c.contains(3));
491 }
492
493 #[test]
494 fn intersection_basic() {
495 let mut a = RoaringBitmap::new();
496 a.insert(1);
497 a.insert(2);
498 a.insert(3);
499
500 let mut b = RoaringBitmap::new();
501 b.insert(2);
502 b.insert(3);
503 b.insert(4);
504
505 let c = a.intersection(&b);
506 assert_eq!(c.cardinality(), 2);
507 assert!(c.contains(2));
508 assert!(c.contains(3));
509 assert!(!c.contains(1));
510 assert!(!c.contains(4));
511 }
512
513 #[test]
514 fn intersection_empty() {
515 let mut a = RoaringBitmap::new();
516 a.insert(1);
517
518 let b = RoaringBitmap::new();
519 let c = a.intersection(&b);
520 assert!(c.is_empty());
521 }
522
523 #[test]
524 fn array_to_bitmap_promotion() {
525 let mut bm = RoaringBitmap::new();
526 for i in 0..ARRAY_TO_BITMAP_THRESHOLD as u32 {
528 bm.insert(i);
529 }
530
531 assert_eq!(bm.cardinality(), ARRAY_TO_BITMAP_THRESHOLD);
532
533 for i in 0..ARRAY_TO_BITMAP_THRESHOLD as u32 {
535 assert!(bm.contains(i), "missing value {i} after promotion");
536 }
537
538 match &bm.containers[0].container {
540 Container::Bitmap(_) => {} Container::Array(_) => panic!("container should have been promoted to bitmap"),
542 }
543 }
544
545 #[test]
546 fn cell_index_dirty_tracking() {
547 let width: u32 = 80;
549 let _height: u32 = 24;
550 let mut dirty = RoaringBitmap::new();
551
552 let cell = |x: u32, y: u32| -> u32 { y * width + x };
554
555 dirty.insert(cell(0, 0));
556 dirty.insert(cell(79, 0)); dirty.insert(cell(40, 12)); assert_eq!(dirty.cardinality(), 3);
560 assert!(dirty.contains(cell(0, 0)));
561 assert!(dirty.contains(cell(79, 0)));
562 assert!(dirty.contains(cell(40, 12)));
563 assert!(!dirty.contains(cell(1, 0)));
564 }
565
566 #[test]
567 fn large_screen_dirty_tracking() {
568 let width: u32 = 300;
570 let height: u32 = 100;
571 let mut dirty = RoaringBitmap::new();
572
573 for x in 0..width {
575 dirty.insert(10 * width + x);
576 }
577 assert_eq!(dirty.cardinality(), width as usize);
578
579 dirty.clear();
581 for y in 0..height {
582 for x in 0..width {
583 dirty.insert(y * width + x);
584 }
585 }
586 assert_eq!(dirty.cardinality(), (width * height) as usize);
587 }
588
589 #[test]
590 fn insert_range_basic() {
591 let mut bm = RoaringBitmap::new();
592 bm.insert_range(10, 20);
593 assert_eq!(bm.cardinality(), 10);
594 for i in 10..20 {
595 assert!(bm.contains(i));
596 }
597 assert!(!bm.contains(9));
598 assert!(!bm.contains(20));
599 }
600
601 #[test]
602 fn union_across_containers() {
603 let mut a = RoaringBitmap::new();
604 a.insert(100); let mut b = RoaringBitmap::new();
607 b.insert(65636); let c = a.union(&b);
610 assert_eq!(c.cardinality(), 2);
611 assert!(c.contains(100));
612 assert!(c.contains(65636));
613 }
614
615 #[test]
616 fn bitmap_iteration_correctness() {
617 let mut bm = BitmapContainer::new();
618 bm.insert(0);
619 bm.insert(63);
620 bm.insert(64);
621 bm.insert(65535);
622
623 let values: Vec<u16> = bm.iter().collect();
624 assert_eq!(values, vec![0, 63, 64, 65535]);
625 }
626
627 #[test]
628 fn default_is_empty() {
629 let bm = RoaringBitmap::default();
630 assert!(bm.is_empty());
631 }
632}