Skip to main content

fcb_core/static_btree/
payload.rs

1use crate::static_btree::entry::Offset;
2use crate::static_btree::error::Result;
3use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
4use std::io::{Read, Seek};
5
6#[derive(Debug)]
7/// A collection of offsets for duplicate keys.
8pub struct PayloadEntry {
9    /// Number of duplicates (including the original key)
10    pub count: u32,
11    /// Offsets for each duplicate
12    pub offsets: Vec<Offset>,
13}
14
15impl Default for PayloadEntry {
16    fn default() -> Self {
17        Self::new()
18    }
19}
20
21impl PayloadEntry {
22    /// Create an empty payload entry.
23    pub fn new() -> Self {
24        Self {
25            count: 0,
26            offsets: Vec::new(),
27        }
28    }
29
30    /// Add an offset to the entry.
31    pub fn add_offset(&mut self, offset: Offset) {
32        self.offsets.push(offset);
33        self.count += 1;
34    }
35
36    /// Serialized size: 4 bytes for count + 8 bytes per offset.
37    pub fn serialized_size(&self) -> usize {
38        4 + (self.count as usize * 8)
39    }
40
41    /// Serialize into a byte buffer (little-endian).
42    pub fn serialize(&self) -> Vec<u8> {
43        let mut buf = Vec::with_capacity(self.serialized_size());
44        buf.write_u32::<LittleEndian>(self.count).unwrap();
45        for &off in &self.offsets {
46            buf.write_u64::<LittleEndian>(off).unwrap();
47        }
48        buf
49    }
50
51    /// Deserialize from a byte slice, returning (entry, bytes_consumed).
52    pub fn deserialize<R: Read + Seek + ?Sized>(data: &mut R) -> Result<(Self, usize)> {
53        // [count, offset1, offset2, ...]
54        let count = data.read_u32::<LittleEndian>()?;
55        let mut offsets = Vec::with_capacity(count as usize);
56        for _ in 0..count {
57            offsets.push(data.read_u64::<LittleEndian>()?);
58        }
59
60        Ok((PayloadEntry { count, offsets }, count as usize * 8))
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use std::io::Cursor;
68
69    #[test]
70    fn test_serialize_deserialize_empty() {
71        let entry = PayloadEntry::new();
72        let buf = entry.serialize();
73        let buf_len = buf.len();
74        assert_eq!(buf_len, 4);
75        let (decoded, _) = PayloadEntry::deserialize(&mut Cursor::new(buf)).unwrap();
76        assert_eq!(decoded.count, 0);
77        assert!(decoded.offsets.is_empty());
78    }
79
80    #[test]
81    fn test_serialize_deserialize_multiple() {
82        let mut entry = PayloadEntry::new();
83        let offs = vec![1u64, 2u64, 3u64, 4u64];
84        for &o in &offs {
85            entry.add_offset(o);
86        }
87
88        let buf = entry.serialize();
89        let buf_len = buf.len();
90        assert_eq!(buf_len, 4 + offs.len() * 8);
91        let (decoded, _) = PayloadEntry::deserialize(&mut Cursor::new(buf)).unwrap();
92        assert_eq!(decoded.count as usize, offs.len());
93        assert_eq!(decoded.offsets, offs);
94    }
95}