Skip to main content

yo_kv/
rank.rs

1//! A counted B+ tree, which is the ordered index a sorted set ranks with.
2//!
3//! What this holds is a sequence of element row numbers and nothing else. It
4//! does not know what a score is, it does not know what a member is, and it
5//! never reads either. Every question about order is asked of the caller through
6//! a closure, and every answer this gives back is a rank or a row number. That
7//! is not shyness about the sorted set, it is the reason the document model can
8//! use the same tree for an ordered index over a path (`09` section 5) without
9//! either of them growing a special case for the other.
10//!
11//! ```text
12//!            +-------------------------------+
13//!   branch   | kid | kid | kid | kid |       |   counts, and the first row
14//!            +-------------------------------+   of each kid's subtree
15//!               |     |     |     \
16//!            +-----+-----+-----+-----+
17//!   leaves   |rows |rows |rows |rows |  <-> linked both ways
18//!            +-----+-----+-----+-----+
19//! ```
20//!
21//! # Why this and not a skiplist
22//!
23//! Redis ranks with a skiplist and aki copied it, and that decision is most of
24//! the 37 bytes an aki zset entry cost, plus ninety more per node. A skiplist
25//! node is an allocation with a tower of pointers on it, so a million member
26//! zset is a million allocations scattered over the heap, and the interior of
27//! the structure, the part every single `ZRANK` has to walk, is scattered with
28//! them. That is `08` section 5's zipfian miss and the long term memory fault
29//! count in one sentence: the hot part of a skiplist is not a small part.
30//!
31//! Here the interior is separate from the elements and it is tiny. A branch node
32//! holds a hundred and twenty eight kids, so ten million elements sit under three
33//! levels and the whole interior is a few hundred kilobytes no matter how the
34//! members are spread. It stays resident under any budget worth having, which is
35//! the mechanism behind `06`'s one device read per point read.
36//!
37//! # What an element costs
38//!
39//! Three bytes, the row number, plus whatever share of a branch node it owns,
40//! which at a fanout of a hundred and twenty eight is a fifth of a byte. Three
41//! point two three bytes an element measured over a million of them, against the
42//! 37 plus 90 per node an aki zset entry cost, and `G8` asks for three. There is
43//! no per element allocation and no per element pointer, and the score is not
44//! here at all: it lives once, in the element table, where `ZSCORE` reads it.
45//!
46//! The cost that buys is that a search asks the caller to compare, and the caller
47//! reads a score out of the element table to answer, so a descent touches a
48//! handful of rows that are not next to each other. That trade is the right way
49//! round for `G8` and it is deliberately the only one on the table: a tree that
50//! cached the score next to the row would answer a search without leaving the
51//! node and would cost three times the memory, which `Y14` calls a fail however
52//! fast it is.
53//!
54//! # Occupancy
55//!
56//! A B+ tree that splits a full node down the middle settles at about seventy
57//! percent full under random inserts and at exactly half under sorted ones, and
58//! sorted is not a corner case here: a leaderboard is written in score order more
59//! often than not. So a full node that is being pushed at either end does not
60//! split down the middle, it puts the new row in a node of its own and leaves the
61//! full one alone. Ascending and descending runs both come out at very nearly a
62//! hundred percent full that way, and a random spread is unaffected.
63
64use core::cmp::Ordering;
65
66/// How many rows a leaf holds.
67///
68/// A kilobyte of row numbers. Small enough that the binary search inside a leaf
69/// is eight comparisons rather than twenty, which matters because each of those
70/// comparisons is a question for the caller and the caller answers it by reading
71/// an element row somewhere else in memory.
72const LEAF_MAX: usize = 256;
73
74/// When a leaf is small enough to be worth folding into a neighbour.
75const LEAF_MIN: usize = LEAF_MAX / 2;
76
77/// How many kids a branch holds.
78///
79/// Three levels reach sixteen million elements, which is the ceiling the element
80/// table puts on a collection anyway, so no tree here is ever deeper than that.
81const BRANCH_MAX: usize = 128;
82
83/// When a branch is small enough to be worth folding into a neighbour.
84const BRANCH_MIN: usize = BRANCH_MAX / 2;
85
86/// No node.
87const NIL: u32 = u32::MAX;
88
89/// Row numbers packed three bytes each.
90///
91/// The fourth byte of a row number is always zero and it is not a guess: the
92/// element table packs a tag and a row into one word and gives the row
93/// twenty four bits of it, so [`crate::elem::MAX_ROWS`] is what a collection can
94/// hold and no row number this ever sees needs the top byte. Storing it anyway
95/// is a third of the leaf, and the leaf is nearly all of what a zset index
96/// costs, so it is the difference between four and a bit bytes an element and
97/// three and a bit.
98///
99/// The room is asked for once, at the size a leaf is allowed to reach, so that a
100/// leaf that is half full is holding a fixed 768 bytes rather than whatever
101/// power of two a growing `Vec` last landed on.
102#[derive(Debug, Clone, Default)]
103struct Rows {
104    at: Vec<u8>,
105}
106
107impl Rows {
108    fn with_room() -> Self {
109        Self {
110            at: Vec::with_capacity(LEAF_MAX * 3),
111        }
112    }
113
114    fn len(&self) -> usize {
115        self.at.len() / 3
116    }
117
118    fn get(&self, i: usize) -> u32 {
119        let at = i * 3;
120        u32::from(self.at[at]) | u32::from(self.at[at + 1]) << 8 | u32::from(self.at[at + 2]) << 16
121    }
122
123    fn set(&mut self, i: usize, row: u32) {
124        let at = i * 3;
125        self.at[at..at + 3].copy_from_slice(&row.to_le_bytes()[..3]);
126    }
127
128    fn push(&mut self, row: u32) {
129        self.at.extend_from_slice(&row.to_le_bytes()[..3]);
130    }
131
132    fn insert(&mut self, i: usize, row: u32) {
133        let at = i * 3;
134        self.at.extend_from_slice(&[0, 0, 0]);
135        let end = self.at.len();
136        self.at.copy_within(at..end - 3, at + 3);
137        self.at[at..at + 3].copy_from_slice(&row.to_le_bytes()[..3]);
138    }
139
140    fn remove(&mut self, i: usize) -> u32 {
141        let row = self.get(i);
142        let at = i * 3;
143        self.at.copy_within(at + 3.., at);
144        self.at.truncate(self.at.len() - 3);
145        row
146    }
147
148    /// Everything from `i` on, in a run of its own.
149    fn split_off(&mut self, i: usize) -> Self {
150        let mut out = Self::with_room();
151        out.at.extend_from_slice(&self.at[i * 3..]);
152        self.at.truncate(i * 3);
153        out
154    }
155
156    fn append(&mut self, other: &Self) {
157        self.at.extend_from_slice(&other.at);
158    }
159
160    /// How many rows at the front the probe calls `Greater`.
161    fn partition_point<F: FnMut(u32) -> bool>(&self, mut keep: F) -> usize {
162        let (mut lo, mut hi) = (0, self.len());
163        while lo < hi {
164            let mid = (lo + hi) / 2;
165            if keep(self.get(mid)) {
166                lo = mid + 1;
167            } else {
168                hi = mid;
169            }
170        }
171        lo
172    }
173
174    fn bytes(&self) -> usize {
175        self.at.capacity()
176    }
177}
178
179/// A run of rows, in order, linked to the runs on either side of it.
180///
181/// The links are what makes `ZRANGE` a descent and then a walk rather than a
182/// descent per element.
183#[derive(Debug, Clone)]
184struct Leaf {
185    rows: Rows,
186    prev: u32,
187    next: u32,
188}
189
190/// A level of the interior: which subtrees are under here, how many elements
191/// each one holds, and the first row of each so that a search can steer without
192/// descending into a subtree to find out what is in it.
193#[derive(Debug, Clone)]
194struct Branch {
195    kids: Vec<u32>,
196    counts: Vec<u32>,
197    firsts: Vec<u32>,
198}
199
200/// A node that came out of a node that was full.
201struct Split {
202    node: u32,
203    count: u32,
204    first: u32,
205}
206
207/// An ordered sequence of element rows that can be asked for a rank.
208///
209/// The sequence is kept in whatever order the caller's comparisons imply. This
210/// type never checks that order and never repairs it, which is the same contract
211/// `slice::binary_search` has: hand it something out of order and it will answer
212/// nonsense rather than complain.
213#[derive(Debug, Clone)]
214pub struct Rank {
215    leaves: Vec<Leaf>,
216    branches: Vec<Branch>,
217    free_leaves: Vec<u32>,
218    free_branches: Vec<u32>,
219    /// The leaf, when `depth` is zero, and otherwise the branch.
220    root: u32,
221    /// How many branch levels sit above the leaves.
222    depth: u8,
223    len: usize,
224    /// The leftmost leaf, which is where a forward walk starts.
225    head: u32,
226    /// The rightmost leaf, which is where a backward walk starts.
227    tail: u32,
228}
229
230impl Default for Rank {
231    fn default() -> Self {
232        Self::new()
233    }
234}
235
236impl Rank {
237    /// An empty sequence, holding one empty leaf.
238    ///
239    /// The leaf is made up front rather than on the first insert because every
240    /// path below would otherwise need to know that the root might not exist,
241    /// and an empty leaf is a `Vec` that has not allocated.
242    #[must_use]
243    pub fn new() -> Self {
244        Self {
245            leaves: vec![Leaf {
246                rows: Rows::with_room(),
247                prev: NIL,
248                next: NIL,
249            }],
250            branches: Vec::new(),
251            free_leaves: Vec::new(),
252            free_branches: Vec::new(),
253            root: 0,
254            depth: 0,
255            len: 0,
256            head: 0,
257            tail: 0,
258        }
259    }
260
261    /// How many rows are in here.
262    #[must_use]
263    pub const fn len(&self) -> usize {
264        self.len
265    }
266
267    /// Whether there are no rows in here.
268    #[must_use]
269    pub const fn is_empty(&self) -> bool {
270        self.len == 0
271    }
272
273    /// What this is holding on to, in bytes, not counting the rows themselves.
274    ///
275    /// This is the number `G8` is about, so it is reported rather than estimated
276    /// from the element count. It counts the room the nodes have asked for and
277    /// not the room they are using, because the difference between those two is
278    /// exactly what the occupancy argument above is about.
279    #[must_use]
280    pub fn bytes(&self) -> usize {
281        let leaves: usize = self
282            .leaves
283            .iter()
284            .map(|l| l.rows.bytes() + size_of::<Leaf>())
285            .sum();
286        let branches: usize = self
287            .branches
288            .iter()
289            .map(|b| {
290                (b.kids.capacity() + b.counts.capacity() + b.firsts.capacity()) * size_of::<u32>()
291                    + size_of::<Branch>()
292            })
293            .sum();
294        leaves + branches
295    }
296
297    /// The row at a rank, or `None` past the end.
298    #[must_use]
299    pub fn row_at(&self, rank: usize) -> Option<u32> {
300        if rank >= self.len {
301            return None;
302        }
303        let (leaf, at) = self.find(rank);
304        Some(self.leaves[leaf as usize].rows.get(at))
305    }
306
307    /// Where a rank sits: which leaf, and how far into it.
308    fn find(&self, rank: usize) -> (u32, usize) {
309        let mut node = self.root;
310        let mut at = rank;
311        for _ in 0..self.depth {
312            let b = &self.branches[node as usize];
313            let mut i = 0;
314            while at >= b.counts[i] as usize && i + 1 < b.kids.len() {
315                at -= b.counts[i] as usize;
316                i += 1;
317            }
318            node = b.kids[i];
319        }
320        (node, at)
321    }
322
323    /// The rank of the first row the probe does not call `Greater`.
324    ///
325    /// The probe answers where the thing being looked for sits against the row it
326    /// is given: `Greater` means the target is past that row and the search
327    /// should keep going right. So this is a lower bound, the same thing
328    /// `partition_point` gives, and it is what every one of `ZADD`, `ZRANK`,
329    /// `ZRANGEBYSCORE` and `ZRANGEBYLEX` is asking for underneath.
330    ///
331    /// It is up to the caller whether ties count. A probe that answers `Equal` on
332    /// an exact match lands on it, and a probe that answers `Greater` there lands
333    /// one past it, which is the difference between the two ends of a range.
334    pub fn seek<F: FnMut(u32) -> Ordering>(&self, mut probe: F) -> usize {
335        let mut node = self.root;
336        let mut base = 0;
337        for _ in 0..self.depth {
338            let b = &self.branches[node as usize];
339            // The first kid is taken whatever the probe says, because everything
340            // in the tree is under it or to the right of it and there is nowhere
341            // further left to go.
342            let mut i = 0;
343            while i + 1 < b.kids.len() && probe(b.firsts[i + 1]) == Ordering::Greater {
344                base += b.counts[i] as usize;
345                i += 1;
346            }
347            node = b.kids[i];
348        }
349        let rows = &self.leaves[node as usize].rows;
350        base + rows.partition_point(|r| probe(r) == Ordering::Greater)
351    }
352
353    /// Put a row at a rank, moving everything from there on one to the right.
354    ///
355    /// # Panics
356    ///
357    /// If the rank is past the end. Ranks up to and including [`Rank::len`] are
358    /// fine, because appending is inserting at the end.
359    pub fn insert_at(&mut self, rank: usize, row: u32) {
360        assert!(
361            rank <= self.len,
362            "rank {rank} is past the end of {}",
363            self.len
364        );
365        let split = if self.depth == 0 {
366            self.leaf_insert(self.root, rank, row)
367        } else {
368            self.branch_insert(self.root, self.depth, rank, row)
369        };
370        if let Some(split) = split {
371            let left = self.root;
372            let left_count = (self.len + 1 - split.count as usize) as u32;
373            let left_first = self.first_of(left, self.depth);
374            let root = self.take_branch();
375            let b = &mut self.branches[root as usize];
376            b.kids.push(left);
377            b.counts.push(left_count);
378            b.firsts.push(left_first);
379            b.kids.push(split.node);
380            b.counts.push(split.count);
381            b.firsts.push(split.first);
382            self.root = root;
383            self.depth += 1;
384        }
385        self.len += 1;
386    }
387
388    /// Take the row at a rank out, moving everything after it one to the left.
389    ///
390    /// # Panics
391    ///
392    /// If the rank is past the end.
393    pub fn remove_at(&mut self, rank: usize) -> u32 {
394        assert!(
395            rank < self.len,
396            "rank {rank} is past the end of {}",
397            self.len
398        );
399        let row = if self.depth == 0 {
400            let leaf = &mut self.leaves[self.root as usize];
401            leaf.rows.remove(rank)
402        } else {
403            self.branch_remove(self.root, self.depth, rank)
404        };
405        // A root that has been emptied down to one kid is a level nobody needs.
406        while self.depth > 0 && self.branches[self.root as usize].kids.len() == 1 {
407            let old = self.root;
408            self.root = self.branches[old as usize].kids[0];
409            self.drop_branch(old);
410            self.depth -= 1;
411        }
412        self.len -= 1;
413        row
414    }
415
416    /// Write a different row number at a rank, leaving the order alone.
417    ///
418    /// This exists because the element table is dense: taking a row out of it
419    /// moves the last row into the hole, so one element that nobody asked about
420    /// gets a new number on every removal, and the tree has to be told. It is a
421    /// renumbering and not a move, so the caller is promising that the element
422    /// now at `row` sorts exactly where the one that was there did.
423    ///
424    /// # Panics
425    ///
426    /// If the rank is past the end.
427    pub fn set_at(&mut self, rank: usize, row: u32) {
428        assert!(
429            rank < self.len,
430            "rank {rank} is past the end of {}",
431            self.len
432        );
433        let mut node = self.root;
434        let mut at = rank;
435        for _ in 0..self.depth {
436            let b = &mut self.branches[node as usize];
437            let mut i = 0;
438            while at >= b.counts[i] as usize && i + 1 < b.kids.len() {
439                at -= b.counts[i] as usize;
440                i += 1;
441            }
442            // A separator holds the first row of its subtree, so a row that is
443            // first in one is first in every one above it too.
444            if at == 0 {
445                b.firsts[i] = row;
446            }
447            node = b.kids[i];
448        }
449        self.leaves[node as usize].rows.set(at, row);
450    }
451
452    /// Walk rows in order from a rank.
453    ///
454    /// The walk is a descent to find the leaf and then a link per leaf after
455    /// that, so a range of a thousand costs one descent and four link hops.
456    #[must_use]
457    pub fn iter_from(&self, rank: usize) -> Walk<'_> {
458        if rank >= self.len {
459            return Walk {
460                tree: self,
461                leaf: NIL,
462                at: 0,
463                left: 0,
464            };
465        }
466        let (leaf, at) = self.find(rank);
467        Walk {
468            tree: self,
469            leaf,
470            at,
471            left: self.len - rank,
472        }
473    }
474
475    /// Walk rows backwards from a rank.
476    #[must_use]
477    pub fn iter_back_from(&self, rank: usize) -> Back<'_> {
478        if rank >= self.len {
479            return Back {
480                tree: self,
481                leaf: NIL,
482                at: 0,
483                left: 0,
484            };
485        }
486        let (leaf, at) = self.find(rank);
487        Back {
488            tree: self,
489            leaf,
490            at,
491            left: rank + 1,
492        }
493    }
494
495    /// Insert into a leaf, and say what came out of it if it was full.
496    fn leaf_insert(&mut self, id: u32, at: usize, row: u32) -> Option<Split> {
497        let leaf = &mut self.leaves[id as usize];
498        if leaf.rows.len() < LEAF_MAX {
499            leaf.rows.insert(at, row);
500            return None;
501        }
502        // A full leaf being pushed at its right hand end is a sorted run, and
503        // splitting it down the middle would leave both halves half full for
504        // ever. The new row goes in a leaf of its own instead.
505        if at == LEAF_MAX {
506            let new = self.take_leaf();
507            self.leaves[new as usize].rows.push(row);
508            self.link_after(id, new);
509            return Some(Split {
510                node: new,
511                count: 1,
512                first: row,
513            });
514        }
515        // Same at the other end, except that what moves is the full leaf rather
516        // than the new row, because the parent already has this node in its kid
517        // list at the position the new row belongs in. The rows go across to a
518        // node of their own and this one keeps its place holding the one row.
519        if at == 0 {
520            let new = self.take_leaf();
521            let full = core::mem::replace(&mut self.leaves[id as usize].rows, Rows::with_room());
522            let count = full.len() as u32;
523            let first = full.get(0);
524            self.leaves[new as usize].rows = full;
525            self.leaves[id as usize].rows.push(row);
526            self.link_after(id, new);
527            return Some(Split {
528                node: new,
529                count,
530                first,
531            });
532        }
533        let new = self.take_leaf();
534        let tail = self.leaves[id as usize].rows.split_off(LEAF_MAX / 2);
535        self.leaves[new as usize].rows = tail;
536        self.link_after(id, new);
537        if at <= LEAF_MAX / 2 {
538            self.leaves[id as usize].rows.insert(at, row);
539        } else {
540            self.leaves[new as usize]
541                .rows
542                .insert(at - LEAF_MAX / 2, row);
543        }
544        let first = self.leaves[new as usize].rows.get(0);
545        let count = self.leaves[new as usize].rows.len() as u32;
546        Some(Split {
547            node: new,
548            count,
549            first,
550        })
551    }
552
553    /// Insert under a branch, and say what came out of it if it was full.
554    fn branch_insert(&mut self, id: u32, level: u8, at: usize, row: u32) -> Option<Split> {
555        let (mut i, mut local) = (0, at);
556        {
557            let b = &self.branches[id as usize];
558            while local > b.counts[i] as usize && i + 1 < b.kids.len() {
559                local -= b.counts[i] as usize;
560                i += 1;
561            }
562        }
563        let kid = self.branches[id as usize].kids[i];
564        let split = if level == 1 {
565            self.leaf_insert(kid, local, row)
566        } else {
567            self.branch_insert(kid, level - 1, local, row)
568        };
569        {
570            let b = &mut self.branches[id as usize];
571            b.counts[i] += 1;
572            if local == 0 {
573                b.firsts[i] = row;
574            }
575        }
576        let split = split?;
577        // A leaf split at its left hand end hands back the node that stayed put
578        // rather than the new one, and the count and first of the kid that is
579        // already in this branch have to be repaired from what is under it.
580        let kept = self.branches[id as usize].kids[i];
581        let kept_count = self.branches[id as usize].counts[i] - split.count;
582        {
583            let b = &mut self.branches[id as usize];
584            b.counts[i] = kept_count;
585        }
586        let kept_first = self.first_of(kept, level - 1);
587        {
588            let b = &mut self.branches[id as usize];
589            b.firsts[i] = kept_first;
590            b.kids.insert(i + 1, split.node);
591            b.counts.insert(i + 1, split.count);
592            b.firsts.insert(i + 1, split.first);
593            if b.kids.len() <= BRANCH_MAX {
594                return None;
595            }
596        }
597        let new = self.take_branch();
598        let (kids, counts, firsts) = {
599            let b = &mut self.branches[id as usize];
600            (
601                b.kids.split_off(BRANCH_MAX / 2),
602                b.counts.split_off(BRANCH_MAX / 2),
603                b.firsts.split_off(BRANCH_MAX / 2),
604            )
605        };
606        let count: u32 = counts.iter().sum();
607        let first = firsts[0];
608        let b = &mut self.branches[new as usize];
609        b.kids = kids;
610        b.counts = counts;
611        b.firsts = firsts;
612        Some(Split {
613            node: new,
614            count,
615            first,
616        })
617    }
618
619    /// Remove from under a branch and put right whatever that emptied.
620    fn branch_remove(&mut self, id: u32, level: u8, at: usize) -> u32 {
621        let (mut i, mut local) = (0, at);
622        {
623            let b = &self.branches[id as usize];
624            while local >= b.counts[i] as usize && i + 1 < b.kids.len() {
625                local -= b.counts[i] as usize;
626                i += 1;
627            }
628        }
629        let kid = self.branches[id as usize].kids[i];
630        let row = if level == 1 {
631            self.leaves[kid as usize].rows.remove(local)
632        } else {
633            self.branch_remove(kid, level - 1, local)
634        };
635        self.branches[id as usize].counts[i] -= 1;
636        if local == 0 && self.branches[id as usize].counts[i] > 0 {
637            let first = self.first_of(kid, level - 1);
638            self.branches[id as usize].firsts[i] = first;
639        }
640        self.mend(id, level, i);
641        row
642    }
643
644    /// Fold a kid that has got too small into one of its neighbours, or borrow
645    /// from one if neither will fit.
646    fn mend(&mut self, id: u32, level: u8, i: usize) {
647        let (small, kids) = {
648            let b = &self.branches[id as usize];
649            let kid = b.kids[i];
650            let small = if level == 1 {
651                self.leaves[kid as usize].rows.len() < LEAF_MIN
652            } else {
653                self.branches[kid as usize].kids.len() < BRANCH_MIN
654            };
655            (small, b.kids.len())
656        };
657        if !small || kids == 1 {
658            return;
659        }
660        // Always fold to the right, so that the pair is (i, i + 1) and the node
661        // that goes away is the second of the two. At the end there is no right
662        // hand neighbour, so step back one and fold this one into its left.
663        let at = if i + 1 == kids { i - 1 } else { i };
664        let (left, right) = {
665            let b = &self.branches[id as usize];
666            (b.kids[at], b.kids[at + 1])
667        };
668        let room = if level == 1 {
669            self.leaves[left as usize].rows.len() + self.leaves[right as usize].rows.len()
670                <= LEAF_MAX
671        } else {
672            self.branches[left as usize].kids.len() + self.branches[right as usize].kids.len()
673                <= BRANCH_MAX
674        };
675        if room {
676            self.join(id, level, at);
677        } else {
678            self.share(id, level, at);
679        }
680    }
681
682    /// Move everything in the right hand node into the left hand one and drop it.
683    fn join(&mut self, id: u32, level: u8, at: usize) {
684        let (left, right) = {
685            let b = &self.branches[id as usize];
686            (b.kids[at], b.kids[at + 1])
687        };
688        if level == 1 {
689            let rows = core::mem::take(&mut self.leaves[right as usize].rows);
690            self.leaves[left as usize].rows.append(&rows);
691            self.unlink(right);
692            self.drop_leaf(right);
693        } else {
694            let (kids, counts, firsts) = {
695                let b = &mut self.branches[right as usize];
696                (
697                    core::mem::take(&mut b.kids),
698                    core::mem::take(&mut b.counts),
699                    core::mem::take(&mut b.firsts),
700                )
701            };
702            let b = &mut self.branches[left as usize];
703            b.kids.extend_from_slice(&kids);
704            b.counts.extend_from_slice(&counts);
705            b.firsts.extend_from_slice(&firsts);
706            self.drop_branch(right);
707        }
708        {
709            let b = &mut self.branches[id as usize];
710            b.counts[at] += b.counts[at + 1];
711            b.kids.remove(at + 1);
712            b.counts.remove(at + 1);
713            b.firsts.remove(at + 1);
714        }
715        // The kid that stayed may have been the empty one, in which case its
716        // first row is whatever just came across into it.
717        let first = self.first_of(left, level - 1);
718        self.branches[id as usize].firsts[at] = first;
719    }
720
721    /// Move one across from the right hand node to the left hand one.
722    fn share(&mut self, id: u32, level: u8, at: usize) {
723        let (left, right) = {
724            let b = &self.branches[id as usize];
725            (b.kids[at], b.kids[at + 1])
726        };
727        let moved = if level == 1 {
728            let row = self.leaves[right as usize].rows.remove(0);
729            self.leaves[left as usize].rows.push(row);
730            1
731        } else {
732            let b = &mut self.branches[right as usize];
733            let kid = b.kids.remove(0);
734            let count = b.counts.remove(0);
735            let first = b.firsts.remove(0);
736            let b = &mut self.branches[left as usize];
737            b.kids.push(kid);
738            b.counts.push(count);
739            b.firsts.push(first);
740            count
741        };
742        let first = self.first_of(right, level - 1);
743        let b = &mut self.branches[id as usize];
744        b.counts[at] += moved;
745        b.counts[at + 1] -= moved;
746        b.firsts[at + 1] = first;
747    }
748
749    /// The first row under a node.
750    fn first_of(&self, id: u32, level: u8) -> u32 {
751        if level == 0 {
752            return self.leaves[id as usize].rows.get(0);
753        }
754        self.branches[id as usize].firsts[0]
755    }
756
757    fn take_leaf(&mut self) -> u32 {
758        if let Some(id) = self.free_leaves.pop() {
759            return id;
760        }
761        self.leaves.push(Leaf {
762            rows: Rows::with_room(),
763            prev: NIL,
764            next: NIL,
765        });
766        (self.leaves.len() - 1) as u32
767    }
768
769    fn drop_leaf(&mut self, id: u32) {
770        let leaf = &mut self.leaves[id as usize];
771        leaf.rows = Rows::default();
772        leaf.prev = NIL;
773        leaf.next = NIL;
774        self.free_leaves.push(id);
775    }
776
777    fn take_branch(&mut self) -> u32 {
778        if let Some(id) = self.free_branches.pop() {
779            return id;
780        }
781        self.branches.push(Branch {
782            kids: Vec::new(),
783            counts: Vec::new(),
784            firsts: Vec::new(),
785        });
786        (self.branches.len() - 1) as u32
787    }
788
789    fn drop_branch(&mut self, id: u32) {
790        let b = &mut self.branches[id as usize];
791        b.kids = Vec::new();
792        b.counts = Vec::new();
793        b.firsts = Vec::new();
794        self.free_branches.push(id);
795    }
796
797    fn link_after(&mut self, id: u32, new: u32) {
798        let next = self.leaves[id as usize].next;
799        self.leaves[new as usize].prev = id;
800        self.leaves[new as usize].next = next;
801        self.leaves[id as usize].next = new;
802        if next == NIL {
803            self.tail = new;
804        } else {
805            self.leaves[next as usize].prev = new;
806        }
807    }
808
809    fn unlink(&mut self, id: u32) {
810        let (prev, next) = {
811            let l = &self.leaves[id as usize];
812            (l.prev, l.next)
813        };
814        if prev == NIL {
815            self.head = next;
816        } else {
817            self.leaves[prev as usize].next = next;
818        }
819        if next == NIL {
820            self.tail = prev;
821        } else {
822            self.leaves[next as usize].prev = prev;
823        }
824    }
825}
826
827/// Rows in order, from where [`Rank::iter_from`] was asked to start.
828#[derive(Debug)]
829pub struct Walk<'a> {
830    tree: &'a Rank,
831    leaf: u32,
832    at: usize,
833    left: usize,
834}
835
836impl Iterator for Walk<'_> {
837    type Item = u32;
838
839    fn next(&mut self) -> Option<u32> {
840        if self.left == 0 || self.leaf == NIL {
841            return None;
842        }
843        let leaf = &self.tree.leaves[self.leaf as usize];
844        let row = leaf.rows.get(self.at);
845        self.at += 1;
846        self.left -= 1;
847        if self.at == leaf.rows.len() {
848            self.leaf = leaf.next;
849            self.at = 0;
850        }
851        Some(row)
852    }
853
854    fn size_hint(&self) -> (usize, Option<usize>) {
855        (self.left, Some(self.left))
856    }
857}
858
859impl ExactSizeIterator for Walk<'_> {}
860
861/// Rows in reverse order, from where [`Rank::iter_back_from`] was asked to start.
862#[derive(Debug)]
863pub struct Back<'a> {
864    tree: &'a Rank,
865    leaf: u32,
866    at: usize,
867    left: usize,
868}
869
870impl Iterator for Back<'_> {
871    type Item = u32;
872
873    fn next(&mut self) -> Option<u32> {
874        if self.left == 0 || self.leaf == NIL {
875            return None;
876        }
877        let leaf = &self.tree.leaves[self.leaf as usize];
878        let row = leaf.rows.get(self.at);
879        self.left -= 1;
880        if self.at == 0 {
881            self.leaf = leaf.prev;
882            if self.leaf != NIL {
883                self.at = self.tree.leaves[self.leaf as usize].rows.len() - 1;
884            }
885        } else {
886            self.at -= 1;
887        }
888        Some(row)
889    }
890
891    fn size_hint(&self) -> (usize, Option<usize>) {
892        (self.left, Some(self.left))
893    }
894}
895
896impl ExactSizeIterator for Back<'_> {}
897
898#[cfg(test)]
899mod tests {
900    use super::*;
901
902    /// The rows in order, which is the only thing any of this has to get right.
903    fn rows(tree: &Rank) -> Vec<u32> {
904        tree.iter_from(0).collect()
905    }
906
907    /// Every count on every branch says how many rows are under it, every leaf
908    /// but the root has something in it, and the links agree with the tree.
909    fn sound(tree: &Rank) {
910        let total = check(tree, tree.root, tree.depth);
911        assert_eq!(
912            total, tree.len,
913            "the root's counts do not add up to the length"
914        );
915        let mut walked = 0;
916        let mut at = tree.head;
917        let mut prev = NIL;
918        while at != NIL {
919            assert_eq!(tree.leaves[at as usize].prev, prev, "a back link is wrong");
920            walked += tree.leaves[at as usize].rows.len();
921            prev = at;
922            at = tree.leaves[at as usize].next;
923        }
924        assert_eq!(prev, tree.tail, "the tail is not the end of the chain");
925        assert_eq!(walked, tree.len, "the leaf chain does not hold every row");
926    }
927
928    fn check(tree: &Rank, id: u32, level: u8) -> usize {
929        if level == 0 {
930            return tree.leaves[id as usize].rows.len();
931        }
932        let b = &tree.branches[id as usize];
933        assert!(!b.kids.is_empty(), "a branch with no kids");
934        let mut total = 0;
935        for (i, &kid) in b.kids.iter().enumerate() {
936            let under = check(tree, kid, level - 1);
937            assert_eq!(
938                under, b.counts[i] as usize,
939                "a count does not match what is under it"
940            );
941            assert_eq!(
942                b.firsts[i],
943                tree.first_of(kid, level - 1),
944                "a first row is stale"
945            );
946            total += under;
947        }
948        total
949    }
950
951    #[test]
952    fn an_empty_tree_answers_nothing() {
953        let tree = Rank::new();
954        assert_eq!(tree.len(), 0);
955        assert!(tree.is_empty());
956        assert_eq!(tree.row_at(0), None);
957        assert_eq!(tree.seek(|_| Ordering::Greater), 0);
958        assert_eq!(rows(&tree), Vec::<u32>::new());
959    }
960
961    #[test]
962    fn a_sorted_run_of_appends_fills_its_leaves() {
963        let mut tree = Rank::new();
964        let n = 10_000;
965        for i in 0..n {
966            tree.insert_at(i as usize, i);
967        }
968        sound(&tree);
969        assert_eq!(rows(&tree), (0..n).collect::<Vec<_>>());
970        // The whole point of not splitting a full leaf that is being appended to
971        // is that the leaves come out full. Four bytes a row plus the odd branch
972        // is under five, and a tree that split down the middle would be at eight.
973        let per = tree.bytes() as f64 / n as f64;
974        assert!(per < 5.0, "{per} bytes a row on a sorted run");
975    }
976
977    #[test]
978    fn a_sorted_run_of_prepends_fills_its_leaves_too() {
979        let mut tree = Rank::new();
980        let n = 10_000;
981        for i in 0..n {
982            tree.insert_at(0, i);
983        }
984        sound(&tree);
985        assert_eq!(rows(&tree), (0..n).rev().collect::<Vec<_>>());
986        let per = tree.bytes() as f64 / n as f64;
987        assert!(per < 5.0, "{per} bytes a row on a reversed run");
988    }
989
990    #[test]
991    fn a_row_can_go_in_anywhere_and_come_out_where_it_went() {
992        let mut tree = Rank::new();
993        let mut model: Vec<u32> = Vec::new();
994        let mut seed = 0x9E37_79B9_7F4A_7C15u64;
995        let roll = |seed: &mut u64, n: usize| {
996            *seed ^= *seed << 13;
997            *seed ^= *seed >> 7;
998            *seed ^= *seed << 17;
999            (*seed % (n as u64 + 1)) as usize
1000        };
1001        for i in 0..4_000u32 {
1002            let at = roll(&mut seed, model.len());
1003            tree.insert_at(at, i);
1004            model.insert(at, i);
1005        }
1006        sound(&tree);
1007        assert_eq!(rows(&tree), model);
1008        for rank in [0, 1, 999, 3_999] {
1009            assert_eq!(tree.row_at(rank), Some(model[rank]));
1010        }
1011        assert_eq!(tree.row_at(4_000), None);
1012    }
1013
1014    #[test]
1015    fn taking_rows_out_puts_the_tree_back_together() {
1016        let mut tree = Rank::new();
1017        for i in 0..5_000u32 {
1018            tree.insert_at(i as usize, i);
1019        }
1020        let mut model: Vec<u32> = (0..5_000).collect();
1021        let mut seed = 0x2545_F491_4F6C_DD1Du64;
1022        while !model.is_empty() {
1023            seed ^= seed << 13;
1024            seed ^= seed >> 7;
1025            seed ^= seed << 17;
1026            let at = (seed % model.len() as u64) as usize;
1027            assert_eq!(tree.remove_at(at), model.remove(at));
1028            if model.len().is_multiple_of(97) {
1029                sound(&tree);
1030                assert_eq!(rows(&tree), model);
1031            }
1032        }
1033        sound(&tree);
1034        assert_eq!(tree.len(), 0);
1035        assert_eq!(tree.depth, 0, "an emptied tree should be one leaf again");
1036    }
1037
1038    #[test]
1039    fn a_tree_that_has_been_emptied_reuses_what_it_had() {
1040        let mut tree = Rank::new();
1041        for i in 0..2_000u32 {
1042            tree.insert_at(i as usize, i);
1043        }
1044        let leaves = tree.leaves.len();
1045        let branches = tree.branches.len();
1046        for _ in 0..2_000 {
1047            tree.remove_at(0);
1048        }
1049        for i in 0..2_000u32 {
1050            tree.insert_at(i as usize, i);
1051        }
1052        sound(&tree);
1053        assert_eq!(tree.leaves.len(), leaves, "leaves were not reused");
1054        assert_eq!(tree.branches.len(), branches, "branches were not reused");
1055    }
1056
1057    /// A search over a sequence sorted by the value at each row, which is what
1058    /// the sorted set will do with a score.
1059    #[test]
1060    fn a_search_finds_where_a_value_belongs() {
1061        let mut tree = Rank::new();
1062        // Row i holds the value i * 10, so the gaps are where the interesting
1063        // answers are.
1064        let value = |row: u32| i64::from(row) * 10;
1065        for i in 0..3_000u32 {
1066            tree.insert_at(i as usize, i);
1067        }
1068        for want in [0i64, 5, 10, 15, 29_990, 29_995, 30_000, 40_000] {
1069            let lower = tree.seek(|row| want.cmp(&value(row)));
1070            let expect = (0..3_000).filter(|&r| value(r) < want).count();
1071            assert_eq!(lower, expect, "lower bound of {want}");
1072        }
1073        // The upper bound is the same descent with a probe that never says it
1074        // has found what it is looking for, which is how a range that includes
1075        // its end is written against a search that excludes it.
1076        let upper = tree.seek(|row| match 100i64.cmp(&value(row)) {
1077            Ordering::Equal => Ordering::Greater,
1078            other => other,
1079        });
1080        assert_eq!(upper, 11);
1081    }
1082
1083    #[test]
1084    fn a_search_over_a_run_of_equal_values_finds_both_of_its_ends() {
1085        let mut tree = Rank::new();
1086        // A thousand rows, all with the same value, which is what a zset that is
1087        // being used as an ordered set looks like.
1088        for i in 0..1_000u32 {
1089            tree.insert_at(i as usize, i);
1090        }
1091        let value = |_row: u32| 7i64;
1092        let first = tree.seek(|row| 7i64.cmp(&value(row)));
1093        let past = tree.seek(|row| match 7i64.cmp(&value(row)) {
1094            Ordering::Equal => Ordering::Greater,
1095            other => other,
1096        });
1097        assert_eq!(first, 0);
1098        assert_eq!(past, 1_000);
1099    }
1100
1101    #[test]
1102    fn a_walk_can_start_anywhere_and_go_either_way() {
1103        let mut tree = Rank::new();
1104        for i in 0..1_000u32 {
1105            tree.insert_at(i as usize, i);
1106        }
1107        assert_eq!(tree.iter_from(998).collect::<Vec<_>>(), vec![998, 999]);
1108        assert_eq!(tree.iter_from(1_000).count(), 0);
1109        assert_eq!(tree.iter_back_from(2).collect::<Vec<_>>(), vec![2, 1, 0]);
1110        assert_eq!(tree.iter_back_from(999).count(), 1_000);
1111        assert_eq!(tree.iter_back_from(1_000).count(), 0);
1112        // A range in the middle is a descent and then a walk, and the count it
1113        // reports up front is what lets a reply write its header first.
1114        let mut walk = tree.iter_from(500);
1115        assert_eq!(walk.len(), 500);
1116        assert_eq!(walk.next(), Some(500));
1117        assert_eq!(walk.len(), 499);
1118    }
1119
1120    #[test]
1121    fn a_million_rows_cost_under_five_bytes_each() {
1122        let mut tree = Rank::new();
1123        let n = 1_000_000u32;
1124        for i in 0..n {
1125            tree.insert_at(i as usize, i);
1126        }
1127        sound(&tree);
1128        let per = tree.bytes() as f64 / f64::from(n);
1129        // G8 asks for three bytes an element for the zset index. This is the
1130        // three byte row number plus a fifth of a byte of interior, and the
1131        // interior is what a fanout of a hundred and twenty eight costs. The
1132        // remaining fifth is not going anywhere without giving up either the
1133        // branch nodes or the `Vec` header on each of them, and neither is worth
1134        // it, so this is the number and it is reported rather than rounded.
1135        assert!(per < 3.4, "{per} bytes a row");
1136    }
1137}