redb_extras/roaring/
value.rs

1//! Roaring bitmap value type for partitioned tables.
2//!
3//! Provides encoding, decoding, and size information for RoaringTreemap values
4//! stored in partitioned segments.
5
6use super::RoaringError;
7use crate::Result;
8use redb::Value as RedbValue;
9use roaring::RoaringTreemap;
10
11/// Value handler for RoaringTreemap in partitioned tables.
12///
13/// This struct provides the bridge between the generic partitioned storage
14/// and roaring-specific value operations. It handles:
15/// - Serialization/deserialization of RoaringTreemap
16/// - Size queries for segment rolling decisions
17/// - Version management for future migrations
18#[derive(Debug, Clone)]
19pub struct RoaringValue;
20
21impl RoaringValue {
22    /// Creates a new RoaringValue handler.
23    pub fn new() -> Self {
24        Self
25    }
26
27    /// Encodes a RoaringTreemap into storage format.
28    ///
29    /// # Arguments
30    /// * `bitmap` - The roaring bitmap to encode
31    ///
32    /// # Returns
33    /// Encoded bytes ready for storage
34    pub fn encode(&self, bitmap: &RoaringTreemap) -> Result<Vec<u8>> {
35        let mut buf = Vec::new();
36        bitmap
37            .serialize_into(&mut buf)
38            .map_err(|e| RoaringError::SerializationFailed(e.to_string()))?;
39
40        // Add version prefix (current version = 1)
41        let mut result = Vec::with_capacity(1 + buf.len());
42        result.push(1u8); // Version byte
43        result.extend_from_slice(&buf);
44
45        Ok(result)
46    }
47
48    /// Decodes storage bytes into a RoaringTreemap.
49    ///
50    /// # Arguments
51    /// * `data` - The encoded value bytes
52    ///
53    /// # Returns
54    /// Decoded RoaringTreemap
55    pub fn decode(&self, data: &[u8]) -> Result<RoaringTreemap> {
56        if data.is_empty() {
57            return Err(RoaringError::InvalidBitmap("Empty data".to_string()).into());
58        }
59
60        let version = data[0];
61        let bitmap_bytes = &data[1..];
62
63        if version != 1 {
64            return Err(
65                RoaringError::InvalidBitmap(format!("Unsupported version: {}", version)).into(),
66            );
67        }
68
69        Ok(RoaringTreemap::deserialize_from(bitmap_bytes)
70            .map_err(|e| RoaringError::SerializationFailed(e.to_string()))?)
71    }
72
73    /// Gets the serialized size of a RoaringTreemap.
74    ///
75    /// This size is used by the partition layer to determine when to roll
76    /// segments based on the configured maximum segment size.
77    ///
78    /// # Arguments
79    /// * `bitmap` - The roaring bitmap to measure
80    ///
81    /// # Returns
82    /// Serialized size in bytes (including version prefix)
83    pub fn get_serialized_size(&self, bitmap: &RoaringTreemap) -> Result<usize> {
84        let mut buf = Vec::new();
85        bitmap
86            .serialize_into(&mut buf)
87            .map_err(|e| RoaringError::SerializationFailed(e.to_string()))?;
88
89        // Include 1 byte for version prefix
90        Ok(1 + buf.len())
91    }
92
93    /// Creates an empty RoaringTreemap.
94    pub fn empty(&self) -> RoaringTreemap {
95        RoaringTreemap::new()
96    }
97
98    /// Creates a RoaringTreemap from a single value.
99    pub fn from_single(&self, value: u64) -> RoaringTreemap {
100        let mut bitmap = RoaringTreemap::new();
101        bitmap.insert(value);
102        bitmap
103    }
104
105    /// Creates a RoaringTreemap from an iterator of values.
106    pub fn from_iter<I>(&self, iter: I) -> RoaringTreemap
107    where
108        I: IntoIterator<Item = u64>,
109    {
110        let values: Vec<u64> = iter.into_iter().collect();
111        RoaringTreemap::from_sorted_iter(values.iter().cloned()).unwrap_or_else(|_| {
112            let mut bitmap = RoaringTreemap::new();
113            for value in &values {
114                bitmap.insert(*value);
115            }
116            bitmap
117        })
118    }
119}
120
121impl Default for RoaringValue {
122    fn default() -> Self {
123        Self::new()
124    }
125}
126
127impl RedbValue for RoaringValue {
128    type SelfType<'a>
129        = RoaringTreemap
130    where
131        Self: 'a;
132    type AsBytes<'a>
133        = Vec<u8>
134    where
135        Self: 'a;
136
137    fn fixed_width() -> Option<usize> {
138        None // Variable width serialization
139    }
140
141    fn from_bytes<'a>(data: &'a [u8]) -> Self::SelfType<'a>
142    where
143        Self: 'a,
144    {
145        let handler = RoaringValue::new();
146        handler
147            .decode(data)
148            .unwrap_or_else(|_| RoaringTreemap::new())
149    }
150
151    fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Self::AsBytes<'a>
152    where
153        Self: 'b,
154    {
155        let handler = RoaringValue::new();
156        handler.encode(value).unwrap_or_else(|_| Vec::new())
157    }
158
159    fn type_name() -> redb::TypeName {
160        redb::TypeName::new("RoaringTreemap")
161    }
162}
163
164#[cfg(test)]
165mod tests {
166    use super::*;
167
168    #[test]
169    fn test_encode_decode_roundtrip() {
170        let handler = RoaringValue::new();
171        let mut bitmap = RoaringTreemap::new();
172        bitmap.insert(1);
173        bitmap.insert(100);
174        bitmap.insert(1000);
175
176        let encoded = handler.encode(&bitmap).unwrap();
177        let decoded = handler.decode(&encoded).unwrap();
178
179        assert_eq!(bitmap, decoded);
180    }
181
182    #[test]
183    fn test_empty_bitmap() {
184        let handler = RoaringValue::new();
185        let bitmap = RoaringTreemap::new();
186
187        let encoded = handler.encode(&bitmap).unwrap();
188        let decoded = handler.decode(&encoded).unwrap();
189
190        assert_eq!(bitmap, decoded);
191        assert_eq!(decoded.len(), 0);
192    }
193
194    #[test]
195    fn test_serialized_size() {
196        let handler = RoaringValue::new();
197        let mut bitmap = RoaringTreemap::new();
198        bitmap.insert(1);
199        bitmap.insert(2);
200
201        let size = handler.get_serialized_size(&bitmap).unwrap();
202        assert!(size > 1); // At least version byte
203        assert!(size < 1000); // Should be reasonably small
204
205        let encoded = handler.encode(&bitmap).unwrap();
206        assert_eq!(size, encoded.len());
207    }
208
209    #[test]
210    fn test_single_value() {
211        let handler = RoaringValue::new();
212        let bitmap = handler.from_single(42);
213
214        assert_eq!(bitmap.len(), 1);
215        assert!(bitmap.contains(42));
216
217        let encoded = handler.encode(&bitmap).unwrap();
218        let decoded = handler.decode(&encoded).unwrap();
219
220        assert_eq!(bitmap, decoded);
221    }
222
223    #[test]
224    fn test_from_iter() {
225        let handler = RoaringValue::new();
226        let values = vec![1, 5, 10, 100];
227        let bitmap = handler.from_iter(values.clone());
228
229        assert_eq!(bitmap.len(), values.len() as u64);
230        for value in &values {
231            assert!(bitmap.contains(*value));
232        }
233
234        let encoded = handler.encode(&bitmap).unwrap();
235        let decoded = handler.decode(&encoded).unwrap();
236
237        assert_eq!(bitmap, decoded);
238    }
239
240    #[test]
241    fn test_invalid_version() {
242        let handler = RoaringValue::new();
243        let mut invalid_data = vec![99]; // Invalid version
244        invalid_data.extend_from_slice(b"fake_data");
245
246        let result = handler.decode(&invalid_data);
247        assert!(result.is_err());
248    }
249}