croaring/bitset/
imp.rs

1use super::Bitset;
2use core::{mem, ptr};
3
4impl Bitset {
5    #[inline]
6    #[allow(clippy::assertions_on_constants)]
7    pub(super) unsafe fn take_heap(p: *mut ffi::bitset_t) -> Self {
8        assert!(!p.is_null());
9        let result = Self { bitset: p.read() };
10        // It seems unlikely that the bitset type will meaningfully change, but check if we ever go
11        // to a version 3.
12        const _: () = assert!(ffi::ROARING_VERSION_MAJOR == 4);
13        ffi::roaring_free(p.cast());
14        result
15    }
16
17    /// Access the raw underlying slice
18    #[inline]
19    #[must_use]
20    pub const fn as_slice(&self) -> &[u64] {
21        if self.bitset.arraysize == 0 {
22            &[]
23        } else {
24            unsafe { core::slice::from_raw_parts(self.bitset.array, self.bitset.arraysize) }
25        }
26    }
27
28    /// Access the raw underlying slice
29    #[inline]
30    pub fn as_mut_slice(&mut self) -> &mut [u64] {
31        if self.bitset.arraysize == 0 {
32            &mut []
33        } else {
34            unsafe { core::slice::from_raw_parts_mut(self.bitset.array, self.bitset.arraysize) }
35        }
36    }
37
38    /// Create a new bitset
39    ///
40    /// Does not allocate
41    ///
42    /// # Examples
43    /// ```
44    /// use croaring::Bitset;
45    /// let bitset = Bitset::new();
46    /// assert_eq!(bitset.capacity(), 0);
47    /// assert_eq!(bitset.size_in_bits(), 0);
48    /// ```
49    #[inline]
50    #[doc(alias = "bitset_create")]
51    #[must_use]
52    pub const fn new() -> Self {
53        Self {
54            bitset: ffi::bitset_t {
55                array: ptr::null_mut(),
56                arraysize: 0,
57                capacity: 0,
58            },
59        }
60    }
61
62    /// Create a new bitset of the specified size
63    ///
64    /// # Examples
65    /// ```
66    /// use croaring::Bitset;
67    /// let bitset = Bitset::with_size(100);
68    /// // Actual size/capacity may be rounded up
69    /// assert!(bitset.capacity() >= 100);
70    /// assert!(bitset.size_in_bits() >= 100);
71    /// ```
72    #[inline]
73    #[doc(alias = "bitset_create_with_capacity")]
74    #[must_use]
75    pub fn with_size(size: usize) -> Self {
76        unsafe { Self::take_heap(ffi::bitset_create_with_capacity(size)) }
77    }
78
79    /// Capacity in bits
80    #[inline]
81    #[must_use]
82    pub const fn capacity(&self) -> usize {
83        self.bitset.capacity * 64
84    }
85
86    /// Set all bits to zero
87    ///
88    /// # Examples
89    /// ```
90    /// use croaring::Bitset;
91    /// let mut bitset = Bitset::with_size(64);
92    /// bitset.fill(true);
93    /// assert!(bitset.get(1));
94    /// assert!(bitset.get(63));
95    /// // Bitset size stays the same
96    /// assert!(!bitset.get(64));
97    /// bitset.fill(false);
98    /// assert!(!bitset.get(1));
99    /// assert!(!bitset.get(63));
100    /// assert!(!bitset.get(64));
101    /// ```
102    #[inline]
103    #[doc(alias = "bitset_clear")]
104    #[doc(alias = "bitset_fill")]
105    pub fn fill(&mut self, value: bool) {
106        if value {
107            unsafe { ffi::bitset_fill(&mut self.bitset) };
108        } else {
109            unsafe { ffi::bitset_clear(&mut self.bitset) };
110        }
111    }
112
113    /// How many bytes of memory the backend buffer uses
114    #[inline]
115    #[doc(alias = "bitset_size_in_bytes")]
116    #[must_use]
117    pub const fn size_in_bytes(&self) -> usize {
118        self.size_in_words() * mem::size_of::<u64>()
119    }
120
121    /// How many bits can be accessed
122    #[inline]
123    #[doc(alias = "bitset_size_in_bits")]
124    #[must_use]
125    pub const fn size_in_bits(&self) -> usize {
126        self.size_in_bytes() * 8
127    }
128
129    /// How many 64-bit words of memory the backend buffer uses
130    #[inline]
131    #[doc(alias = "bitset_size_in_words")]
132    #[must_use]
133    pub const fn size_in_words(&self) -> usize {
134        self.bitset.arraysize
135    }
136
137    /// Resize the bitset to contain `new_array_size` 64-bit words
138    ///
139    /// New bits are set to `value`
140    ///
141    /// # Examples
142    /// ```
143    /// use croaring::Bitset;
144    /// let mut bitset = Bitset::new();
145    /// bitset.resize_words(1, false);
146    /// bitset.resize_words(2, true);
147    /// assert_eq!(bitset.iter().collect::<Vec<_>>(), (64..128).collect::<Vec<_>>());
148    /// ```
149    pub fn resize_words(&mut self, new_array_size: usize, value: bool) {
150        let old_array_size = self.bitset.arraysize;
151        let res = unsafe { ffi::bitset_resize(&mut self.bitset, new_array_size, value) };
152        assert!(res);
153        if new_array_size > old_array_size {
154            let new_data_slice = &mut self.as_mut_slice()[old_array_size..];
155            new_data_slice.fill(u64::from(value) * !0);
156        }
157    }
158
159    /// For advanced users: Grow the bitset so that it can support newarraysize * 64 bits with padding.
160    /// Return true in case of success, false for failure
161    #[inline]
162    #[doc(alias = "bitset_grow")]
163    fn grow(&mut self, new_array_size: usize) {
164        assert!(unsafe { ffi::bitset_grow(&mut self.bitset, new_array_size) });
165    }
166
167    /// Attempts to recover unused memory by shrinking capacity to fit the highest set bit
168    ///
169    /// # Examples
170    /// ```
171    /// use croaring::Bitset;
172    /// let mut bitset = Bitset::new();
173    /// bitset.set(63);
174    /// bitset.set(1000);
175    /// assert!(bitset.size_in_bits() > 1000);
176    /// bitset.set_to_value(1000, false);
177    /// bitset.shrink_to_fit();
178    /// // The next highest bit is at index 63
179    /// assert_eq!(bitset.size_in_bits(), 64);
180    #[inline]
181    #[doc(alias = "bitset_trim")]
182    pub fn shrink_to_fit(&mut self) {
183        unsafe { ffi::bitset_trim(&mut self.bitset) };
184    }
185
186    /// Set the ith bit
187    ///
188    /// Will resize the bitset if needed, any other newly added bits will be initialized to zero
189    ///
190    /// # Examples
191    /// ```
192    /// use croaring::Bitset;
193    /// let mut bitset = Bitset::new();
194    /// bitset.set(1);
195    /// bitset.set(2);
196    /// bitset.set(100);
197    /// assert_eq!(bitset.iter().collect::<Vec<_>>(), vec![1, 2, 100]);
198    /// ```
199    #[inline]
200    #[doc(alias = "bitset_set")]
201    pub fn set(&mut self, i: usize) {
202        let array_idx = i / 64;
203        if array_idx >= self.bitset.arraysize {
204            self.grow(array_idx + 1);
205        }
206        self.as_mut_slice()[array_idx] |= 1 << (i % 64);
207    }
208
209    /// Set the ith bit to `value`
210    ///
211    /// Will resize the bitset if needed, any other newly added bits will be initialized to zero
212    ///
213    /// # Examples
214    /// ```
215    /// use croaring::Bitset;
216    /// let mut bitset = Bitset::new();
217    /// bitset.set_to_value(1, true);
218    /// bitset.set_to_value(2, true);
219    /// bitset.set_to_value(100, true);
220    /// bitset.set_to_value(1, false);
221    /// assert_eq!(bitset.iter().collect::<Vec<_>>(), vec![2, 100]);
222    /// ```
223    #[inline]
224    #[doc(alias = "bitset_set_to_value")]
225    pub fn set_to_value(&mut self, i: usize, value: bool) {
226        let array_idx = i / 64;
227        if array_idx >= self.bitset.arraysize {
228            self.grow(array_idx + 1);
229        }
230        let dst = &mut self.as_mut_slice()[array_idx];
231        let mask = 1 << (i % 64);
232        let value_bit = u64::from(value) << (i % 64);
233        let mut word = *dst;
234        word &= !mask;
235        word |= value_bit;
236        *dst = word;
237    }
238
239    /// Get the value of the ith bit
240    ///
241    /// If the bit is out of bounds, returns false
242    ///
243    /// # Examples
244    /// ```
245    /// use croaring::Bitset;
246    /// let mut bitset = Bitset::new();
247    /// bitset.set(1);
248    /// bitset.set(2);
249    /// assert!(bitset.get(1));
250    /// assert!(bitset.get(2));
251    /// assert!(!bitset.get(3));
252    /// ```
253    #[inline]
254    #[doc(alias = "bitset_get")]
255    #[must_use]
256    pub const fn get(&self, i: usize) -> bool {
257        let array_idx = i / 64;
258        if array_idx >= self.bitset.arraysize {
259            return false;
260        }
261        let word = self.as_slice()[array_idx];
262        let mask = 1 << (i % 64);
263        (word & mask) != 0
264    }
265
266    /// Check if the bitset is empty
267    ///
268    /// # Examples
269    /// ```
270    /// use croaring::Bitset;
271    /// let mut bitset = Bitset::new();
272    /// assert!(bitset.is_empty());
273    /// bitset.set(100);
274    /// assert!(!bitset.is_empty());
275    /// ```
276    #[inline]
277    #[doc(alias = "bitset_empty")]
278    #[must_use]
279    pub fn is_empty(&self) -> bool {
280        unsafe { ffi::bitset_empty(&self.bitset) }
281    }
282
283    /// Count of number of set bits
284    ///
285    /// # Examples
286    /// ```
287    /// use croaring::Bitset;
288    /// let mut bitset: Bitset = [1, 2, 3, 100].into_iter().collect();
289    /// assert_eq!(bitset.count(), 4);
290    /// ```
291    #[inline]
292    #[doc(alias = "bitset_count")]
293    #[must_use]
294    pub fn count(&self) -> usize {
295        unsafe { ffi::bitset_count(&self.bitset) }
296    }
297
298    /// Index of the first set bit, or usize::MAX if the bitset has no set bits
299    ///
300    /// # Examples
301    /// ```
302    /// use croaring::Bitset;
303    /// let mut bitset = Bitset::new();
304    /// // minimum returns 0 if the bitset is empty
305    /// assert_eq!(bitset.minimum(), usize::MAX);
306    /// bitset.set(100);
307    /// assert_eq!(bitset.minimum(), 100);
308    /// ```
309    #[inline]
310    #[doc(alias = "bitset_minimum")]
311    #[must_use]
312    pub fn minimum(&self) -> usize {
313        unsafe { ffi::bitset_minimum(&self.bitset) }
314    }
315
316    /// Index of the last set bit, or zero if the bitset has no set bits
317    ///
318    /// # Examples
319    /// ```
320    /// use croaring::Bitset;
321    /// let mut bitset = Bitset::new();
322    /// // maximum returns 0 if the bitset is empty
323    /// assert_eq!(bitset.maximum(), 0);
324    /// bitset.set(100);
325    /// assert_eq!(bitset.maximum(), 100);
326    /// bitset.set(1000);
327    /// assert_eq!(bitset.maximum(), 1000);
328    /// ```
329    #[inline]
330    #[doc(alias = "bitset_maximum")]
331    #[must_use]
332    pub fn maximum(&self) -> usize {
333        unsafe { ffi::bitset_maximum(&self.bitset) }
334    }
335
336    /// The size of the hypothetical union of `self` and `other`
337    ///
338    /// # Examples
339    /// ```
340    /// use croaring::Bitset;
341    /// let mut bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
342    /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
343    /// assert_eq!(bitset1.union_count(&bitset2), 6);
344    /// bitset1 |= &bitset2;
345    /// assert_eq!(bitset1.count(), 6);
346    /// ```
347    #[inline]
348    #[doc(alias = "bitset_union_count")]
349    #[must_use]
350    pub fn union_count(&self, other: &Self) -> usize {
351        // CRoaring uses restrict pointers, so we can't use the same pointer for both
352        if ptr::eq(self, other) {
353            return self.count();
354        }
355        unsafe { ffi::bitset_union_count(&self.bitset, &other.bitset) }
356    }
357
358    /// The size of the hypothetical intersection of `self` and `other`
359    ///
360    /// # Examples
361    /// ```
362    /// use croaring::Bitset;
363    /// let mut bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
364    /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
365    /// assert_eq!(bitset1.intersection_count(&bitset2), 2);
366    /// bitset1 &= &bitset2;
367    /// assert_eq!(bitset1.count(), 2);
368    /// ```
369    #[inline]
370    #[doc(alias = "bitset_intersection_count")]
371    #[must_use]
372    pub fn intersection_count(&self, other: &Self) -> usize {
373        // CRoaring uses restrict pointers, so we can't use the same pointer for both
374        if ptr::eq(self, other) {
375            return self.count();
376        }
377        unsafe { ffi::bitset_intersection_count(&self.bitset, &other.bitset) }
378    }
379
380    /// Return true if `self` and `other` contain no common elements
381    ///
382    /// # Examples
383    /// ```
384    /// use croaring::Bitset;
385    /// let bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
386    /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
387    /// assert!(!bitset1.is_disjoint(&bitset2));
388    /// let bitset3: Bitset = [4, 5, 6, 7].into_iter().collect();
389    /// assert!(bitset1.is_disjoint(&bitset3));
390    /// ```
391    ///
392    /// Empty bitsets are always disjoint
393    ///
394    /// ```
395    /// use croaring::Bitset;
396    /// let bitset1 = Bitset::new();
397    /// let bitset2 = Bitset::new();
398    /// assert!(bitset1.is_disjoint(&bitset2));
399    /// ```
400    #[inline]
401    #[doc(alias = "bitset_disjoint")]
402    #[must_use]
403    pub fn is_disjoint(&self, other: &Self) -> bool {
404        // CRoaring uses restrict pointers, so we can't use the same pointer for both
405        if ptr::eq(self, other) {
406            return false;
407        }
408        unsafe { ffi::bitsets_disjoint(&self.bitset, &other.bitset) }
409    }
410
411    /// Return true if `self` and `other` contain at least one common element
412    ///
413    /// # Examples
414    /// ```
415    /// use croaring::Bitset;
416    /// let bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
417    /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
418    /// assert!(bitset1.has_intersect(&bitset2));
419    /// let bitset3: Bitset = [4, 5, 6, 7].into_iter().collect();
420    /// assert!(!bitset1.has_intersect(&bitset3));
421    /// ```
422    #[inline]
423    #[doc(alias = "bitset_intersect")]
424    #[must_use]
425    pub fn has_intersect(&self, other: &Self) -> bool {
426        // CRoaring uses restrict pointers, so we can't use the same pointer for both
427        if ptr::eq(self, other) {
428            return true;
429        }
430        unsafe { ffi::bitsets_intersect(&self.bitset, &other.bitset) }
431    }
432
433    /// Return true if `self` is a superset of `other`
434    ///
435    /// # Examples
436    /// ```
437    /// use croaring::Bitset;
438    /// let bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
439    /// let bitset2: Bitset = [2, 3].into_iter().collect();
440    /// assert!(bitset1.is_superset(&bitset2));
441    /// let bitset3: Bitset = [4, 5, 6, 7].into_iter().collect();
442    /// assert!(!bitset1.is_superset(&bitset3));
443    /// ```
444    #[inline]
445    #[doc(alias = "bitset_contains_all")]
446    #[must_use]
447    pub fn is_superset(&self, other: &Self) -> bool {
448        // CRoaring uses restrict pointers, so we can't use the same pointer for both
449        if ptr::eq(self, other) {
450            return true;
451        }
452        unsafe { ffi::bitset_contains_all(&self.bitset, &other.bitset) }
453    }
454
455    /// The size of the hypothetical difference of `self` and `other`
456    ///
457    /// # Examples
458    /// ```
459    /// use croaring::Bitset;
460    /// let mut bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
461    /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
462    /// assert_eq!(bitset1.difference_count(&bitset2), 2);
463    /// bitset1 -= &bitset2;
464    /// assert_eq!(bitset1.count(), 2);
465    /// ```
466    #[inline]
467    #[doc(alias = "bitset_difference_count")]
468    #[must_use]
469    pub fn difference_count(&self, other: &Self) -> usize {
470        // CRoaring uses restrict pointers, so we can't use the same pointer for both
471        if ptr::eq(self, other) {
472            return 0;
473        }
474        unsafe { ffi::bitset_difference_count(&self.bitset, &other.bitset) }
475    }
476
477    /// The size of the hypothetical symmetric difference (xor) of `self` and `other`
478    ///
479    /// # Examples
480    /// ```
481    /// use croaring::Bitset;
482    /// let mut bitset1: Bitset = [1, 2, 3, 100].into_iter().collect();
483    /// let bitset2: Bitset = [2, 3, 4, 5].into_iter().collect();
484    /// assert_eq!(bitset1.symmetric_difference_count(&bitset2), 4);
485    /// bitset1 ^= &bitset2;
486    /// assert_eq!(bitset1.count(), 4);
487    /// ```
488    #[inline]
489    #[doc(alias = "bitset_symmetric_difference_count")]
490    #[doc(alias = "xor_count")]
491    #[must_use]
492    pub fn symmetric_difference_count(&self, other: &Self) -> usize {
493        // CRoaring uses restrict pointers, so we can't use the same pointer for both
494        if ptr::eq(self, other) {
495            return 0;
496        }
497        unsafe { ffi::bitset_symmetric_difference_count(&self.bitset, &other.bitset) }
498    }
499
500    /// Expose the raw `CRoaring` bitset
501    ///
502    /// This allows calling raw `CRoaring` functions on the bitset.
503    #[inline]
504    #[must_use]
505    pub fn as_raw(&self) -> &ffi::bitset_t {
506        &self.bitset
507    }
508
509    /// Expose the raw `CRoaring` bitset mutably
510    ///
511    /// This allows calling raw `CRoaring` functions on the bitset.
512    #[inline]
513    #[must_use]
514    pub fn as_raw_mut(&mut self) -> &mut ffi::bitset_t {
515        &mut self.bitset
516    }
517}