1use std::collections::BTreeMap;
10use std::collections::HashMap;
11use std::ops::Bound;
12
13use crate::value::IndexValue;
14
15#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct Cursor {
19 pub value: IndexValue,
21 pub key: Vec<u8>,
23}
24
25#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
27pub struct SegmentStats {
28 pub entries: u64,
30 pub approx_bytes: u64,
32 pub coerce_failures: u64,
34 pub duplicates: u64,
36}
37
38const ENTRY_OVERHEAD: usize = 48;
40
41#[derive(Debug, Default)]
43pub struct Segment {
44 tree: BTreeMap<(IndexValue, Vec<u8>), ()>,
45 back: HashMap<Vec<u8>, IndexValue>,
46 value_counts: BTreeMap<IndexValue, u32>,
47 stats: SegmentStats,
48}
49
50impl Segment {
51 pub fn new() -> Self {
53 Self::default()
54 }
55
56 pub fn apply(&mut self, key: &[u8], new: Option<IndexValue>) {
60 if let Some(old) = self.back.remove(key) {
61 self.tree.remove(&(old.clone(), key.to_vec()));
62 self.stats.entries -= 1;
63 self.stats.approx_bytes = self
64 .stats
65 .approx_bytes
66 .saturating_sub((old.approx_bytes() + key.len() + ENTRY_OVERHEAD) as u64);
67 self.dec_count(&old);
68 }
69 match new {
70 Some(v) => {
71 self.stats.entries += 1;
72 self.stats.approx_bytes +=
73 (v.approx_bytes() + key.len() + ENTRY_OVERHEAD) as u64;
74 self.inc_count(&v);
75 self.back.insert(key.to_vec(), v.clone());
76 self.tree.insert((v, key.to_vec()), ());
77 }
78 None => {
79 self.stats.coerce_failures += 1;
80 }
81 }
82 }
83
84 pub fn remove(&mut self, key: &[u8]) {
86 if let Some(old) = self.back.remove(key) {
87 self.tree.remove(&(old.clone(), key.to_vec()));
88 self.stats.entries -= 1;
89 self.stats.approx_bytes = self
90 .stats
91 .approx_bytes
92 .saturating_sub((old.approx_bytes() + key.len() + ENTRY_OVERHEAD) as u64);
93 self.dec_count(&old);
94 }
95 }
96
97 fn inc_count(&mut self, v: &IndexValue) {
98 let c = self.value_counts.entry(v.clone()).or_insert(0);
99 *c += 1;
100 if *c == 2 {
101 self.stats.duplicates += 1;
102 }
103 }
104
105 fn dec_count(&mut self, v: &IndexValue) {
106 if let Some(c) = self.value_counts.get_mut(v) {
107 if *c == 2 {
108 self.stats.duplicates -= 1;
109 }
110 *c -= 1;
111 if *c == 0 {
112 self.value_counts.remove(v);
113 }
114 }
115 }
116
117 pub fn range(
122 &self,
123 min: &IndexValue,
124 max: &IndexValue,
125 cursor: Option<&Cursor>,
126 limit: usize,
127 ) -> (Vec<(Vec<u8>, IndexValue)>, Option<Cursor>) {
128 let lower: Bound<(IndexValue, Vec<u8>)> = match cursor {
129 Some(c) => Bound::Excluded((c.value.clone(), c.key.clone())),
130 None => Bound::Included((min.clone(), Vec::new())),
131 };
132 let mut out = Vec::with_capacity(limit.min(64));
135 let mut iter = self.tree.range((lower, Bound::Unbounded));
136 for ((v, k), ()) in iter.by_ref() {
137 if v > max {
138 break;
139 }
140 out.push((k.clone(), v.clone()));
141 if out.len() == limit {
142 break;
143 }
144 }
145 let next = if out.len() == limit {
146 out.last().map(|(k, v)| Cursor { value: v.clone(), key: k.clone() })
147 } else {
148 None
149 };
150 (out, next)
151 }
152
153 pub fn eq(&self, value: &IndexValue, limit: usize) -> Vec<Vec<u8>> {
156 let lower = Bound::Included((value.clone(), Vec::new()));
157 self.tree
158 .range((lower, Bound::Unbounded))
159 .take_while(|((v, _), ())| v == value)
160 .take(limit)
161 .map(|((_, k), ())| k.clone())
162 .collect()
163 }
164
165 pub fn count(&self, min: &IndexValue, max: &IndexValue) -> u64 {
167 let lower = Bound::Included((min.clone(), Vec::new()));
168 self.tree
169 .range((lower, Bound::Unbounded))
170 .take_while(|((v, _), ())| v <= max)
171 .count() as u64
172 }
173
174 pub fn verify_entry(&self, key: &[u8]) -> Option<&IndexValue> {
177 self.back.get(key)
178 }
179
180 pub fn scan<'s>(
186 &'s self,
187 after: Option<&Cursor>,
188 desc: bool,
189 ) -> Box<dyn Iterator<Item = (&'s IndexValue, &'s [u8])> + 's> {
190 match (after, desc) {
191 (None, false) => Box::new(self.tree.keys().map(|(v, k)| (v, k.as_slice()))),
192 (None, true) => Box::new(self.tree.keys().rev().map(|(v, k)| (v, k.as_slice()))),
193 (Some(c), false) => Box::new(
194 self.tree
195 .range((
196 Bound::Excluded((c.value.clone(), c.key.clone())),
197 Bound::Unbounded,
198 ))
199 .map(|((v, k), ())| (v, k.as_slice())),
200 ),
201 (Some(c), true) => Box::new(
202 self.tree
203 .range((
204 Bound::Unbounded,
205 Bound::Excluded((c.value.clone(), c.key.clone())),
206 ))
207 .rev()
208 .map(|((v, k), ())| (v, k.as_slice())),
209 ),
210 }
211 }
212
213 pub fn each_entry<F: FnMut(&[u8], &IndexValue)>(&self, mut f: F) {
215 for (k, v) in &self.back {
216 f(k.as_slice(), v);
217 }
218 }
219
220 pub fn stats(&self) -> SegmentStats {
222 self.stats
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 fn i(v: i64) -> IndexValue {
231 IndexValue::I64(v)
232 }
233
234 fn seeded() -> Segment {
235 let mut s = Segment::new();
236 for (k, v) in [("u1", 30), ("u2", 25), ("u3", 30), ("u4", 40), ("u5", 18)] {
237 s.apply(k.as_bytes(), Some(i(v)));
238 }
239 s
240 }
241
242 #[test]
243 fn apply_replace_remove_and_stats() {
244 let mut s = seeded();
245 assert_eq!(s.stats().entries, 5);
246 assert_eq!(s.stats().duplicates, 1, "30 held twice");
247 s.apply(b"u1", Some(i(31)));
249 assert_eq!(s.stats().entries, 5);
250 assert_eq!(s.stats().duplicates, 0);
251 s.apply(b"u2", None);
253 assert_eq!(s.stats().entries, 4);
254 assert_eq!(s.stats().coerce_failures, 1);
255 s.remove(b"u3");
257 assert_eq!(s.stats().entries, 3);
258 assert_eq!(s.stats().coerce_failures, 1);
259 assert!(s.verify_entry(b"u3").is_none());
260 assert_eq!(s.verify_entry(b"u4"), Some(&i(40)));
261 }
262
263 #[test]
264 fn range_scan_orders_and_paginates() {
265 let s = seeded();
266 let (page1, cur) = s.range(&i(18), &i(30), None, 2);
267 assert_eq!(page1[0], (b"u5".to_vec(), i(18)));
268 assert_eq!(page1[1], (b"u2".to_vec(), i(25)));
269 let cur = cur.expect("more pages");
270 let (page2, cur2) = s.range(&i(18), &i(30), Some(&cur), 10);
271 assert_eq!(
272 page2,
273 vec![(b"u1".to_vec(), i(30)), (b"u3".to_vec(), i(30))],
274 "value tie broken by key"
275 );
276 assert!(cur2.is_none(), "exhausted");
277 assert_eq!(s.count(&i(18), &i(30)), 4);
278 assert_eq!(s.count(&i(99), &i(100)), 0);
279 }
280
281 #[test]
282 fn eq_and_duplicate_fence() {
283 let s = seeded();
284 assert_eq!(s.eq(&i(30), 10), vec![b"u1".to_vec(), b"u3".to_vec()]);
285 assert_eq!(s.eq(&i(40), 10), vec![b"u4".to_vec()]);
286 assert!(s.eq(&i(99), 10).is_empty());
287 }
288
289 #[test]
290 fn long_keys_at_max_value_not_missed() {
291 let mut s = Segment::new();
292 let long_key = vec![0xFFu8; 80]; s.apply(&long_key, Some(i(30)));
294 s.apply(b"short", Some(i(30)));
295 let (hits, _) = s.range(&i(30), &i(30), None, 10);
296 assert_eq!(hits.len(), 2, "max-valued long key must not be missed");
297 assert_eq!(s.eq(&i(30), 10).len(), 2);
298 assert_eq!(s.count(&i(30), &i(30)), 2);
299 }
300
301 #[test]
302 fn f64_and_str_orders() {
303 let mut s = Segment::new();
304 s.apply(b"a", Some(IndexValue::F64(1.5)));
305 s.apply(b"b", Some(IndexValue::F64(-0.5)));
306 let (hits, _) = s.range(&IndexValue::F64(-1.0), &IndexValue::F64(2.0), None, 10);
307 assert_eq!(hits[0].0, b"b".to_vec());
308
309 let mut t = Segment::new();
310 t.apply(b"x", Some(IndexValue::Str(b"banana".to_vec())));
311 t.apply(b"y", Some(IndexValue::Str(b"apple".to_vec())));
312 let (hits, _) = t.range(
313 &IndexValue::Str(b"a".to_vec()),
314 &IndexValue::Str(b"z".to_vec()),
315 None,
316 10,
317 );
318 assert_eq!(hits[0].0, b"y".to_vec());
319 }
320}