sui_sdk_types/
bitmap.rs

1/// A compressed bitmap using the [Roaring bitmap compression scheme](https://roaringbitmap.org/).
2///
3/// # BCS
4///
5/// The BCS serialized form for this type is defined by the following ABNF:
6///
7/// ```text
8/// roaring-bitmap = bytes  ; where the contents of the bytes are valid
9///                         ; according to the serialized spec for
10///                         ; roaring bitmaps
11/// ```
12#[derive(Clone, Debug, Default, PartialEq)]
13pub struct Bitmap(roaring::RoaringBitmap);
14
15impl Bitmap {
16    /// Creates an empty `Bitmap`.
17    ///
18    /// # Examples
19    ///
20    /// ```rust
21    /// use sui_sdk_types::Bitmap;
22    /// let bitmap = Bitmap::new();
23    /// ```
24    pub fn new() -> Self {
25        Self::default()
26    }
27
28    /// Returns the number of distinct integers added to the set.
29    ///
30    /// # Examples
31    ///
32    /// ```rust
33    /// use sui_sdk_types::Bitmap;
34    ///
35    /// let mut bitmap = Bitmap::new();
36    /// assert_eq!(bitmap.len(), 0);
37    ///
38    /// bitmap.insert(3);
39    /// assert_eq!(bitmap.len(), 1);
40    ///
41    /// bitmap.insert(3);
42    /// bitmap.insert(4);
43    /// assert_eq!(bitmap.len(), 2);
44    /// ```
45    pub fn len(&self) -> u64 {
46        self.0.len()
47    }
48
49    /// Clears all integers in this set.
50    ///
51    /// # Examples
52    ///
53    /// ```rust
54    /// use sui_sdk_types::Bitmap;
55    ///
56    /// let mut bitmap = Bitmap::new();
57    /// bitmap.insert(1);
58    /// assert_eq!(bitmap.contains(1), true);
59    /// bitmap.clear();
60    /// assert_eq!(bitmap.contains(1), false);
61    /// ```
62    pub fn clear(&mut self) {
63        self.0.clear()
64    }
65
66    /// Returns `true` if there are no integers in this set.
67    ///
68    /// # Examples
69    ///
70    /// ```rust
71    /// use sui_sdk_types::Bitmap;
72    ///
73    /// let mut bitmap = Bitmap::new();
74    /// assert_eq!(bitmap.is_empty(), true);
75    ///
76    /// bitmap.insert(3);
77    /// assert_eq!(bitmap.is_empty(), false);
78    /// ```
79    pub fn is_empty(&self) -> bool {
80        self.0.is_empty()
81    }
82
83    /// Adds a value to the set.
84    ///
85    /// Returns whether the value was absent from the set.
86    ///
87    /// # Examples
88    ///
89    /// ```rust
90    /// use sui_sdk_types::Bitmap;
91    ///
92    /// let mut bitmap = Bitmap::new();
93    /// assert_eq!(bitmap.insert(3), true);
94    /// assert_eq!(bitmap.insert(3), false);
95    /// assert_eq!(bitmap.contains(3), true);
96    /// ```
97    pub fn insert(&mut self, value: u32) -> bool {
98        self.0.insert(value)
99    }
100
101    /// Inserts a range of values.
102    /// Returns the number of inserted values.
103    ///
104    /// # Examples
105    ///
106    /// ```rust
107    /// use sui_sdk_types::Bitmap;
108    ///
109    /// let mut bitmap = Bitmap::new();
110    /// bitmap.insert_range(2..4);
111    /// assert!(bitmap.contains(2));
112    /// assert!(bitmap.contains(3));
113    /// assert!(!bitmap.contains(4));
114    /// ```
115    pub fn insert_range<R>(&mut self, range: R) -> u64
116    where
117        R: std::ops::RangeBounds<u32>,
118    {
119        self.0.insert_range(range)
120    }
121
122    /// Removes a value from the set. Returns `true` if the value was present in the set.
123    ///
124    /// # Examples
125    ///
126    /// ```rust
127    /// use sui_sdk_types::Bitmap;
128    ///
129    /// let mut bitmap = Bitmap::new();
130    /// bitmap.insert(3);
131    /// assert_eq!(bitmap.remove(3), true);
132    /// assert_eq!(bitmap.remove(3), false);
133    /// assert_eq!(bitmap.contains(3), false);
134    /// ```
135    pub fn remove(&mut self, value: u32) -> bool {
136        self.0.remove(value)
137    }
138
139    /// Returns `true` if this set contains the specified integer.
140    ///
141    /// # Examples
142    ///
143    /// ```rust
144    /// use sui_sdk_types::Bitmap;
145    ///
146    /// let mut bitmap = Bitmap::new();
147    /// bitmap.insert(1);
148    /// assert_eq!(bitmap.contains(0), false);
149    /// assert_eq!(bitmap.contains(1), true);
150    /// assert_eq!(bitmap.contains(100), false);
151    /// ```
152    pub fn contains(&self, value: u32) -> bool {
153        self.0.contains(value)
154    }
155
156    /// Iterator over each value stored in the Bitmap, guarantees values are ordered by value.
157    ///
158    /// # Examples
159    ///
160    /// ```rust
161    /// use core::iter::FromIterator;
162    /// use sui_sdk_types::Bitmap;
163    ///
164    /// let bitmap = (1..3).collect::<Bitmap>();
165    /// let mut iter = bitmap.iter();
166    ///
167    /// assert_eq!(iter.next(), Some(1));
168    /// assert_eq!(iter.next(), Some(2));
169    /// assert_eq!(iter.next(), None);
170    /// ```
171    pub fn iter(&self) -> impl Iterator<Item = u32> + use<'_> {
172        self.0.iter()
173    }
174
175    /// Deserialize a bitmap into memory from [the standard Roaring on-disk
176    /// format][format]. This is compatible with the official C/C++, Java and
177    /// Go implementations. This method checks that all of the internal values
178    /// are valid.
179    ///
180    /// [format]: https://github.com/RoaringBitmap/RoaringFormatSpec
181    ///
182    /// # Examples
183    ///
184    /// ```rust
185    /// use sui_sdk_types::Bitmap;
186    ///
187    /// let bitmap1: Bitmap = (1..4).collect();
188    /// let mut bytes = vec![];
189    /// bitmap1.serialize_into(&mut bytes).unwrap();
190    /// let bitmap2 = Bitmap::deserialize_from(&bytes[..]).unwrap();
191    ///
192    /// assert_eq!(bitmap1, bitmap2);
193    /// ```
194    #[cfg(feature = "serde")]
195    #[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
196    pub fn deserialize_from<R: std::io::Read>(reader: R) -> std::io::Result<Self> {
197        let rb = roaring::RoaringBitmap::deserialize_from(reader)?;
198
199        // Need to explicilty build by iterating the read bitmap to enforce uniquness since the
200        // deserialization path doesn't guarantee it.
201        let mut bitmap = Self::new();
202        bitmap.extend(rb);
203        Ok(bitmap)
204    }
205
206    /// Serialize this bitmap into [the standard Roaring on-disk format][format].
207    /// This is compatible with the official C/C++, Java and Go implementations.
208    ///
209    /// [format]: https://github.com/RoaringBitmap/RoaringFormatSpec
210    ///
211    /// # Examples
212    ///
213    /// ```rust
214    /// use sui_sdk_types::Bitmap;
215    ///
216    /// let bitmap1: Bitmap = (1..4).collect();
217    /// let mut bytes = vec![];
218    /// bitmap1.serialize_into(&mut bytes).unwrap();
219    /// let bitmap2 = Bitmap::deserialize_from(&bytes[..]).unwrap();
220    ///
221    /// assert_eq!(bitmap1, bitmap2);
222    /// ```
223    #[cfg(feature = "serde")]
224    #[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
225    pub fn serialize_into<W: std::io::Write>(&self, writer: W) -> std::io::Result<()> {
226        self.0.serialize_into(writer)
227    }
228}
229
230impl FromIterator<u32> for Bitmap {
231    fn from_iter<I: IntoIterator<Item = u32>>(iterator: I) -> Bitmap {
232        let mut bitmap = Self::new();
233        bitmap.extend(iterator);
234        bitmap
235    }
236}
237
238impl<'a> FromIterator<&'a u32> for Bitmap {
239    fn from_iter<I: IntoIterator<Item = &'a u32>>(iterator: I) -> Bitmap {
240        let mut bitmap = Self::new();
241        bitmap.extend(iterator);
242        bitmap
243    }
244}
245
246impl Extend<u32> for Bitmap {
247    fn extend<I: IntoIterator<Item = u32>>(&mut self, values: I) {
248        self.0.extend(values)
249    }
250}
251
252impl<'a> Extend<&'a u32> for Bitmap {
253    fn extend<I: IntoIterator<Item = &'a u32>>(&mut self, values: I) {
254        self.extend(values.into_iter().copied());
255    }
256}
257
258#[cfg(feature = "serde")]
259#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
260impl serde::Serialize for Bitmap {
261    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
262    where
263        S: serde::Serializer,
264    {
265        use serde_with::SerializeAs;
266
267        let mut bytes = vec![];
268
269        self.serialize_into(&mut bytes)
270            .map_err(serde::ser::Error::custom)?;
271
272        if serializer.is_human_readable() {
273            let b64 = <base64ct::Base64 as base64ct::Encoding>::encode_string(&bytes);
274            serde::Serialize::serialize(&b64, serializer)
275        } else {
276            serde_with::Bytes::serialize_as(&bytes, serializer)
277        }
278    }
279}
280
281#[cfg(feature = "serde")]
282#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
283impl<'de> serde::Deserialize<'de> for Bitmap {
284    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
285    where
286        D: serde::Deserializer<'de>,
287    {
288        use serde_with::DeserializeAs;
289
290        if deserializer.is_human_readable() {
291            let b64: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
292            let bytes = <base64ct::Base64 as base64ct::Encoding>::decode_vec(&b64)
293                .map_err(serde::de::Error::custom)?;
294            Self::deserialize_from(&bytes[..]).map_err(serde::de::Error::custom)
295        } else {
296            let bytes: std::borrow::Cow<'de, [u8]> =
297                serde_with::Bytes::deserialize_as(deserializer)?;
298            Self::deserialize_from(&bytes[..]).map_err(serde::de::Error::custom)
299        }
300    }
301}
302
303#[cfg(feature = "proptest")]
304#[cfg_attr(doc_cfg, doc(cfg(feature = "proptest")))]
305impl proptest::arbitrary::Arbitrary for Bitmap {
306    type Parameters = ();
307    type Strategy = proptest::strategy::BoxedStrategy<Self>;
308
309    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
310        use proptest::collection::vec;
311        use proptest::prelude::*;
312
313        vec(any::<u32>(), 0..32).prop_map(Self::from_iter).boxed()
314    }
315}
316
317#[cfg(test)]
318mod test {
319    use super::*;
320
321    use base64ct::Encoding;
322
323    #[test]
324    fn test_unique_deserialize() {
325        let raw = "OjAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAAAFoAAABcAAAAXgAAAGAAAABiAAAAZAAAAGYAAABoAAAAagAAAAEAAQABAAEAAQABAAEAAQABAAEA";
326        let bytes = base64ct::Base64::decode_vec(raw).unwrap();
327
328        let rb = roaring::RoaringBitmap::deserialize_from(&bytes[..]).unwrap();
329        assert_eq!(rb.len(), 10);
330        let bitmap_values: Vec<u32> = rb.iter().collect();
331        assert_eq!(bitmap_values, vec![1; 10]);
332
333        let bitmap = Bitmap::deserialize_from(&bytes[..]).unwrap();
334        assert_eq!(bitmap.len(), 1);
335        let bitmap_values: Vec<u32> = bitmap.iter().collect();
336        assert_eq!(bitmap_values, vec![1]);
337    }
338}