rlox_core/buffer/
varlen.rs1pub struct VarLenStore {
6 data: Vec<u32>,
7 offsets: Vec<u64>,
8}
9
10impl Default for VarLenStore {
11 fn default() -> Self {
12 Self::new()
13 }
14}
15
16impl VarLenStore {
17 pub fn new() -> Self {
19 Self {
20 data: Vec::new(),
21 offsets: vec![0],
22 }
23 }
24
25 pub fn push(&mut self, sequence: &[u32]) {
27 self.data.extend_from_slice(sequence);
28 self.offsets.push(self.data.len() as u64);
29 }
30
31 pub fn num_sequences(&self) -> usize {
33 self.offsets.len() - 1
34 }
35
36 pub fn total_elements(&self) -> usize {
38 self.data.len()
39 }
40
41 pub fn get(&self, index: usize) -> &[u32] {
46 let start = self.offsets[index] as usize;
47 let end = self.offsets[index + 1] as usize;
48 &self.data[start..end]
49 }
50
51 pub fn sequence_len(&self, index: usize) -> usize {
53 let start = self.offsets[index] as usize;
54 let end = self.offsets[index + 1] as usize;
55 end - start
56 }
57
58 pub fn flat_data(&self) -> &[u32] {
60 &self.data
61 }
62
63 pub fn offsets(&self) -> &[u64] {
65 &self.offsets
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn empty_store() {
75 let store = VarLenStore::new();
76 assert_eq!(store.num_sequences(), 0);
77 assert_eq!(store.total_elements(), 0);
78 }
79
80 #[test]
81 fn push_and_retrieve() {
82 let mut store = VarLenStore::new();
83 store.push(&[10, 20, 30]);
84 store.push(&[40, 50]);
85 assert_eq!(store.num_sequences(), 2);
86 assert_eq!(store.get(0), &[10, 20, 30]);
87 assert_eq!(store.get(1), &[40, 50]);
88 }
89
90 #[test]
91 fn total_elements_correct() {
92 let mut store = VarLenStore::new();
93 store.push(&[1, 2, 3]);
94 store.push(&[4, 5]);
95 assert_eq!(store.total_elements(), 5);
96 }
97
98 #[test]
99 fn no_padding_waste() {
100 let mut store = VarLenStore::new();
101 store.push(&[1, 2, 3]);
102 store.push(&[4, 5]);
103 assert_eq!(store.flat_data(), &[1, 2, 3, 4, 5]);
104 assert_eq!(store.offsets(), &[0, 3, 5]);
105 }
106
107 #[test]
108 fn sequence_len() {
109 let mut store = VarLenStore::new();
110 store.push(&[1, 2, 3]);
111 store.push(&[4]);
112 assert_eq!(store.sequence_len(0), 3);
113 assert_eq!(store.sequence_len(1), 1);
114 }
115
116 #[test]
117 fn default_is_empty() {
118 let store = VarLenStore::default();
119 assert_eq!(store.num_sequences(), 0);
120 }
121
122 mod proptests {
123 use super::*;
124 use proptest::collection::vec;
125 use proptest::prelude::*;
126
127 proptest! {
128 #[test]
129 fn varlen_total_equals_sum_of_lengths(sequences in vec(vec(0u32..1000, 1..100), 1..50)) {
130 let mut store = VarLenStore::new();
131 let expected: usize = sequences.iter().map(|s| s.len()).sum();
132 for seq in &sequences {
133 store.push(seq);
134 }
135 prop_assert_eq!(store.total_elements(), expected);
136 }
137
138 #[test]
139 fn varlen_roundtrip(sequences in vec(vec(0u32..1000, 1..100), 1..50)) {
140 let mut store = VarLenStore::new();
141 for seq in &sequences {
142 store.push(seq);
143 }
144 for (i, seq) in sequences.iter().enumerate() {
145 prop_assert_eq!(store.get(i), seq.as_slice());
146 }
147 }
148
149 #[test]
150 fn varlen_num_sequences_matches(sequences in vec(vec(0u32..1000, 1..50), 1..100)) {
151 let mut store = VarLenStore::new();
152 for seq in &sequences {
153 store.push(seq);
154 }
155 prop_assert_eq!(store.num_sequences(), sequences.len());
156 }
157 }
158 }
159}