1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use super::RoaringTreemap;
use crate::RoaringBitmap;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::{io, mem::size_of};

impl RoaringTreemap {
    /// Return the size in bytes of the serialized output.
    /// This is compatible with the official C/C++, Java and Go implementations.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use roaring::RoaringTreemap;
    ///
    /// let rb1: RoaringTreemap = (1..4).collect();
    /// let mut bytes = Vec::with_capacity(rb1.serialized_size());
    /// rb1.serialize_into(&mut bytes).unwrap();
    /// let rb2 = RoaringTreemap::deserialize_from(&bytes[..]).unwrap();
    ///
    /// assert_eq!(rb1, rb2);
    /// ```
    pub fn serialized_size(&self) -> usize {
        self.map
            .values()
            .fold(size_of::<u64>(), |acc, bitmap| acc + size_of::<u32>() + bitmap.serialized_size())
    }

    /// Serialize this bitmap.
    /// This is compatible with the official C/C++, Java and Go implementations.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use roaring::RoaringTreemap;
    ///
    /// let rb1: RoaringTreemap = (1..4).collect();
    /// let mut bytes = vec![];
    /// rb1.serialize_into(&mut bytes).unwrap();
    /// let rb2 = RoaringTreemap::deserialize_from(&bytes[..]).unwrap();
    ///
    /// assert_eq!(rb1, rb2);
    /// ```
    pub fn serialize_into<W: io::Write>(&self, mut writer: W) -> io::Result<()> {
        writer.write_u64::<LittleEndian>(self.map.len() as u64)?;

        for (key, bitmap) in &self.map {
            writer.write_u32::<LittleEndian>(*key)?;
            bitmap.serialize_into(&mut writer)?;
        }

        Ok(())
    }

    /// Deserialize a bitmap into memory.
    ///
    /// This is compatible with the official C/C++, Java and Go implementations.
    /// This method checks that all of the internal values are valid.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use roaring::RoaringTreemap;
    ///
    /// let rb1: RoaringTreemap = (1..4).collect();
    /// let mut bytes = vec![];
    /// rb1.serialize_into(&mut bytes).unwrap();
    /// let rb2 = RoaringTreemap::deserialize_from(&bytes[..]).unwrap();
    ///
    /// assert_eq!(rb1, rb2);
    /// ```
    pub fn deserialize_from<R: io::Read>(reader: R) -> io::Result<Self> {
        RoaringTreemap::deserialize_from_impl(reader, |reader| {
            RoaringBitmap::deserialize_from(reader)
        })
    }

    /// Deserialize a bitmap into memory.
    ///
    /// This is compatible with the official C/C++, Java and Go implementations.
    /// This method is memory safe but will not check if the data is a valid bitmap.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use roaring::RoaringTreemap;
    ///
    /// let rb1: RoaringTreemap = (1..4).collect();
    /// let mut bytes = vec![];
    /// rb1.serialize_into(&mut bytes).unwrap();
    /// let rb2 = RoaringTreemap::deserialize_unchecked_from(&bytes[..]).unwrap();
    ///
    /// assert_eq!(rb1, rb2);
    /// ```
    pub fn deserialize_unchecked_from<R: io::Read>(reader: R) -> io::Result<Self> {
        RoaringTreemap::deserialize_from_impl(reader, |reader| {
            RoaringBitmap::deserialize_unchecked_from(reader)
        })
    }

    fn deserialize_from_impl<R, F>(mut reader: R, mut deserialize_bitmap: F) -> io::Result<Self>
    where
        R: io::Read,
        F: FnMut(&mut R) -> io::Result<RoaringBitmap>,
    {
        let size = reader.read_u64::<LittleEndian>()?;

        let mut s = Self::new();

        for _ in 0..size {
            let key = reader.read_u32::<LittleEndian>()?;
            let bitmap = deserialize_bitmap(&mut reader)?;

            s.map.insert(key, bitmap);
        }

        Ok(s)
    }
}

#[cfg(test)]
mod test {
    use crate::RoaringTreemap;
    use proptest::prelude::*;

    proptest! {
        #[test]
        fn test_serialization(
            treemap in RoaringTreemap::arbitrary(),
        ) {
            let mut buffer = Vec::new();
            treemap.serialize_into(&mut buffer).unwrap();
            prop_assert_eq!(treemap, RoaringTreemap::deserialize_from(buffer.as_slice()).unwrap());
        }
    }
}