nickel_lang_vector/vector.rs
1//! [`Vector`] is a persistent vector (also known as a "bitmapped vector trie").
2//!
3//! Most of the operations on `Vector` have similar asymptotic (but
4//! with a slower constant-factor) run-time to the same operations on the
5//! standard-library `Vec`. For example, you can quickly push an element to
6//! the back, or pop one from the back; random-access indexing is also fast.
7//! On the other hand, pushing/popping from the front or insertion/deletion in
8//! the middle are both slow. (Actually, we haven't even implemented these slow
9//! operations because we don't need them.)
10//!
11//! The main advantage that [`Vector`] has over [`std::vec::Vec`] is *persistence*:
12//! you can cheaply clone a `Vector` and then modify the clone. The clone and the
13//! original will share most of their storage.
14//!
15//! There's a good explanation of the data structure
16//! [here](https://hypirion.com/musings/understanding-persistent-vector-pt-1).
17//! Very briefly, a vector is stored as a tree with a fixed branching factor, where
18//! all leaves are the same distance from the root.
19//! Unlike most tree data-structures, it isn't balanced. Instead, it's "packed left"
20//! as much as possible.
21//!
22//! Persistence is achieved by cloning the path leading down
23//! to the node you want to modify: say you want to push a new element, and the're
24//! room for it in the right-most leaf. Then you clone the right-most leaf and
25//! add your new element. Then you clone the leaf's parent and populate it with
26//! pointers to the leaf's (unmodified) siblings, plus the leaf's new clone. Then
27//! you clone the leaf's grandparent and populate it with pointers to the leaf's
28//! (unmodified) uncles, plus the leaf's parent's new clone. You continue up the
29//! tree like this, and you end up with a tree where the path from the leaf to
30//! the root is new but everything else is shared with the previous version of
31//! the vector.
32//!
33//! In this implementation, the pointers in the tree are `Rc` pointers, and we
34//! use `Rc::make_mut` to clone-on-write: when a tree node is only present in
35//! the tree that we're modifying, the clones in the description above
36//! are replaced by direct modification.
37//!
38//! ## Branching factor `N`.
39//!
40//! `Vector` stores its data in a tree, and you get to choose the branching factor
41//! `N`. It must be a power of 2 between 2 and 128 (inclusive), and something like
42//! 32 seems to be reasonable. There is a trade-off involved, of course. Large
43//! values of `N` make traditional array operations -- like random access, pushing,
44//! and popping -- fast because the tree becomes very flat. On the other hand, the
45//! copy-on-write operations suffer when `N` is large because blocks of size `N`
46//! are the smallest units of shareable data.
47//!
48//! For example, if `N` is 128 and you have a vector of less than 128 entries,
49//! it will be stored in a single flat array of capacity 128. If you then clone
50//! the `Vector` and modify the clone, the whole length-128 array will be
51//! cloned. If the vector is stored as a taller tree, only the blocks on the
52//! path from the root to the modified entry will be duplicated. That is, modifying
53//! an entry in a `Vector` of length `n` and branching factor `N` has
54//! cost `O(N * log_N n)`.
55//!
56//! ## Comparison to `rpds`
57//!
58//! The same structure is implemented in [rpds](https://crates.io/crates/rpds),
59//! but our implementation is faster for Nickel's use-cases:
60//! - rpds's internal nodes are implemented with `Vec`, meaning that there's a
61//! double pointer indirection. We store our internal nodes inline.
62//! - rpds wraps its leaves in `Rc` pointers, but we are mainly interested in
63//! storing things that are already reference-counted under the hood. We store
64//! our leaves inline, and require that they be `Clone`.
65//! - we have optimized implementations of `Extend`, and support fast iteration
66//! over subslices.
67//! - we have better support for "consuming" operations, such as an
68//! implementation of `into_iter` that avoids cloning the data unless
69//! necessary for persistence.
70
71use std::{iter::Peekable, ops::Index, rc::Rc};
72
73use imbl_sized_chunks::Chunk;
74
75use crate::{Const, ValidBranchingConstant};
76
77// In principle we could decouple the size of the interior nodes from the size of the leaves.
78// This might make sense when `T` is large, because the interior nodes are always pointer-sized.
79type Interior<T, const N: usize> = Chunk<Rc<Node<T, N>>, N>;
80type ChunkIter<T, const N: usize> = imbl_sized_chunks::sized_chunk::Iter<T, N>;
81type InteriorChunkIter<T, const N: usize> = ChunkIter<Rc<Node<T, N>>, N>;
82
83// Can we improve the memory layout? We like N to be a power of 2 for
84// performance (because it allows adjusting the indices using just bitwise
85// operations), but it would also be cool if the total size of the node were a
86// nice round number (so it would exactly fit in a small integer number of cache
87// lines). The discriminant makes it hard to have both of these at once.
88// Since we always know (based on the tree height) which type we *expect* a node
89// to have, we could use a `union` instead of an `enum` (at the cost of lots of
90// unsafe code).
91//
92// `N` must be a power of 2; this is important for efficiency because it allows
93// the use of bitwise operations for a lot of things. I tried allowing `N` to
94// be arbitrary, hoping that the compiler would be smart enough to do the fast
95// thing when `N` is a power of 2. It wasn't.
96//
97// It would be nice to encode the power-of-2 restriction more efficiently (for
98// example, by parametrizing with `B` and setting `N = 1 << B`). This sort of
99// needs the `generic_const_exprs` feature to work, though.
100#[derive(Debug, Clone, PartialEq, Eq, Hash)]
101enum Node<T, const N: usize> {
102 Leaf { data: Chunk<T, N> },
103 Interior { children: Interior<T, N> },
104}
105
106/// `idx` is the global index into the root node, and we are some
107/// possibly-intermediate node at height `height` (where the leaf is at height
108/// zero). Which of our children does the global index belong to?
109fn extract_index<const N: usize>(idx: usize, height: u8) -> usize {
110 let shifted: usize = idx >> (N.ilog2() * u32::from(height));
111 shifted & (N - 1)
112}
113
114impl<T: Clone, const N: usize> Node<T, N>
115where
116 Const<N>: ValidBranchingConstant,
117{
118 /// An inefficient but correct (and simple) method for computing the length
119 /// of this subtree. We cache the length in the top-level vector, so this is
120 /// only used for sanity-checks.
121 fn len(&self) -> usize {
122 match self {
123 Node::Leaf { data } => data.len(),
124 Node::Interior { children } => {
125 // This could be faster if we used the tree height to compute
126 // the size of the packed part of the tree. But this function is
127 // only used for checking invariants, so speed isn't important.
128 children.iter().map(|c| c.len()).sum()
129 }
130 }
131 }
132
133 /// If this node is at height `height`, try to get the element at the given
134 /// index.
135 fn get(&self, height: u8, idx: usize) -> Option<&T> {
136 match self {
137 Node::Leaf { data } => {
138 debug_assert_eq!(height, 0);
139 data.get(idx & (N - 1))
140 }
141 Node::Interior { children } => {
142 let bucket_idx = extract_index::<N>(idx, height);
143 children
144 .get(bucket_idx)
145 .and_then(|child| child.get(height - 1, idx))
146 }
147 }
148 }
149
150 /// Set the element at the given index.
151 ///
152 /// The index is allowed to point to the uninitialized slot just past the
153 /// end of the initialized part, but it must point to a valid index within
154 /// this node (i.e. if this node is full then it can't point past the end).
155 ///
156 /// Panics if the index is invalid.
157 fn set(&mut self, height: u8, idx: usize, elt: T) {
158 match self {
159 Node::Leaf { data } => {
160 let idx = idx & (N - 1);
161 debug_assert_eq!(height, 0);
162 debug_assert!(idx <= data.len());
163 if idx < data.len() {
164 data.set(idx, elt);
165 } else {
166 data.push_back(elt);
167 }
168 }
169 Node::Interior { children } => {
170 let bucket_idx = extract_index::<N>(idx, height);
171 assert!(height >= 1);
172 assert!(bucket_idx <= children.len());
173 if bucket_idx < children.len() {
174 Rc::make_mut(&mut children[bucket_idx]).set(height - 1, idx, elt);
175 } else {
176 let mut leaf = Chunk::new();
177 leaf.push_back(elt);
178
179 let mut child = Node::Leaf { data: leaf };
180 for _ in 1..height {
181 let mut children = Chunk::new();
182 children.push_back(Rc::new(child));
183 child = Node::Interior { children };
184 }
185 children.push_back(Rc::new(child));
186 }
187 }
188 }
189 }
190
191 /// Deletes and returns the last element of this subtree (which is assumed to be non-empty).
192 ///
193 /// Returns true if popping made this subtree empty.
194 fn pop(&mut self) -> (T, bool) {
195 match self {
196 Node::Leaf { data } => {
197 debug_assert!(!data.is_empty());
198 let ret = data.pop_back();
199 (ret, data.is_empty())
200 }
201 Node::Interior { children } => {
202 let (ret, child_empty) =
203 Rc::make_mut(children.last_mut().expect("empty interior node")).pop();
204 if child_empty {
205 children.pop_back();
206 }
207 (ret, children.is_empty())
208 }
209 }
210 }
211
212 /// Shrinks the length of this subtree to `len`.
213 ///
214 /// Assumes that the length is less than this node's current length.
215 fn truncate(&mut self, height: u8, len: usize) {
216 match self {
217 Node::Leaf { data } => {
218 debug_assert!(height == 0);
219 data.drop_right(len);
220 }
221 Node::Interior { children } => {
222 // If `len` is small enough, we may just want to drop some children
223 // and their entire subtrees.
224 let max_child_len = N.pow(u32::from(height));
225 let num_full_children = len / max_child_len;
226 let extra = len % max_child_len;
227 if extra > 0 {
228 children.drop_right(num_full_children + 1);
229 Rc::make_mut(&mut children[num_full_children]).truncate(height - 1, extra);
230 } else {
231 children.drop_right(num_full_children);
232 }
233 }
234 }
235 }
236}
237
238/// A persistent vector.
239#[derive(Clone, Debug, PartialEq, Eq, Hash)]
240pub struct Vector<T, const N: usize>
241where
242 Const<N>: ValidBranchingConstant,
243{
244 root: Option<Rc<Node<T, N>>>,
245 length: usize,
246 // TODO: could save some space by taking 8 bits out of length
247 height: u8,
248}
249
250/// A borrowed iterator over a [`Vector`].
251#[derive(Debug, Clone)]
252pub struct Iter<'a, T, const N: usize>
253where
254 Const<N>: ValidBranchingConstant,
255{
256 stack: Vec<std::slice::Iter<'a, Rc<Node<T, N>>>>,
257 leaf: std::slice::Iter<'a, T>,
258}
259
260impl<'a, T, const N: usize> Iterator for Iter<'a, T, N>
261where
262 Const<N>: ValidBranchingConstant,
263{
264 type Item = &'a T;
265
266 fn next(&mut self) -> Option<Self::Item> {
267 if let Some(ret) = self.leaf.next() {
268 Some(ret)
269 } else {
270 let height = self.stack.len();
271 let mut next = loop {
272 match self.stack.last_mut() {
273 Some(iter) => {
274 if let Some(next) = iter.next() {
275 break next;
276 } else {
277 self.stack.pop();
278 }
279 }
280 None => {
281 return None;
282 }
283 }
284 };
285
286 let cur_len = self.stack.len();
287 for _ in cur_len..height {
288 let Node::Interior { children } = next.as_ref() else {
289 unreachable!();
290 };
291 let mut children_iter = children.iter();
292 next = children_iter.next().expect("empty interior node");
293 self.stack.push(children_iter);
294 }
295
296 let Node::Leaf { data } = next.as_ref() else {
297 unreachable!();
298 };
299 debug_assert!(!data.is_empty());
300 self.leaf = data.iter();
301 self.leaf.next()
302 }
303 }
304}
305
306/// A mutable iterator over a [`Vector`].
307#[derive(Debug)]
308pub struct IterMut<'a, T, const N: usize>
309where
310 Const<N>: ValidBranchingConstant,
311{
312 stack: Vec<std::slice::IterMut<'a, Rc<Node<T, N>>>>,
313 leaf: std::slice::IterMut<'a, T>,
314}
315
316impl<'a, T, const N: usize> Iterator for IterMut<'a, T, N>
317where
318 Const<N>: ValidBranchingConstant,
319 T: Clone,
320{
321 type Item = &'a mut T;
322
323 fn next(&mut self) -> Option<Self::Item> {
324 if let Some(ret) = self.leaf.next() {
325 Some(ret)
326 } else {
327 let height = self.stack.len();
328 let mut next = loop {
329 match self.stack.last_mut() {
330 Some(iter) => {
331 if let Some(next) = iter.next() {
332 break next;
333 } else {
334 self.stack.pop();
335 }
336 }
337 None => {
338 return None;
339 }
340 }
341 };
342
343 let cur_len = self.stack.len();
344 for _ in cur_len..height {
345 let Node::Interior { children } = Rc::make_mut(next) else {
346 unreachable!();
347 };
348 let mut children_iter = children.iter_mut();
349 next = children_iter.next().expect("empty interior node");
350 self.stack.push(children_iter);
351 }
352
353 let Node::Leaf { data } = Rc::make_mut(next) else {
354 unreachable!();
355 };
356 debug_assert!(!data.is_empty());
357 self.leaf = data.iter_mut();
358 self.leaf.next()
359 }
360 }
361}
362
363/// An owned iterator over a [`Vector`].
364//
365// `IntoIter` and `Iter` share a bunch of almost-identical code, and if we
366// ever want an `IterMut` then it will also be similar. I tried to make a
367// common implementation by defining something like
368//
369// ```rust
370// struct GenericIter<InteriorIter, LeafIter>
371// where InteriorIter: Iterator<Item = Either<InteriorIter, LeafIter>>,
372// {
373// stack: Vec<InteriorIter>,
374// leaf: LeafIter,
375// }
376// ```
377//
378// but it came with a massive 500% performance penalty. I didn't look carefully
379// into why.
380pub struct IntoIter<T, const N: usize> {
381 stack: Vec<InteriorChunkIter<T, N>>,
382 leaf: ChunkIter<T, N>,
383}
384
385impl<T: Clone, const N: usize> Iterator for IntoIter<T, N> {
386 type Item = T;
387
388 fn next(&mut self) -> Option<Self::Item> {
389 if let Some(ret) = self.leaf.next() {
390 Some(ret)
391 } else {
392 let height = self.stack.len();
393 let mut next = loop {
394 match self.stack.last_mut() {
395 Some(iter) => {
396 if let Some(next) = iter.next() {
397 break next;
398 } else {
399 self.stack.pop();
400 }
401 }
402 None => {
403 return None;
404 }
405 }
406 };
407
408 let cur_len = self.stack.len();
409 for _ in cur_len..height {
410 let Node::Interior { children } = Rc::unwrap_or_clone(next) else {
411 unreachable!();
412 };
413 let mut children_iter = children.into_iter();
414 next = children_iter.next().expect("empty interior node");
415 self.stack.push(children_iter);
416 }
417
418 let Node::Leaf { data } = Rc::unwrap_or_clone(next) else {
419 unreachable!();
420 };
421 debug_assert!(!data.is_empty());
422 self.leaf = data.into_iter();
423 self.leaf.next()
424 }
425 }
426}
427
428impl<T: Clone, const N: usize> Extend<T> for Vector<T, N>
429where
430 Const<N>: ValidBranchingConstant,
431{
432 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
433 // Make the iterator peekable, because we need to check if there's an
434 // element remaining before we mutate the tree to make room for it.
435 let mut iter = iter.into_iter().peekable();
436
437 // Extends a node from an iterator, but does not increase the height of
438 // the node. If the node fills up, the iterator may not be fully consumed.
439 //
440 // Returns the number of elements consumed from the iterator.
441 fn extend_rec<T: Clone, I: Iterator<Item = T>, const N: usize>(
442 iter: &mut Peekable<I>,
443 node: &mut Interior<T, N>,
444 height: u8,
445 ) -> usize {
446 debug_assert!(height >= 1);
447 let mut consumed = 0;
448
449 if height == 1 {
450 // If there's a leaf that isn't filled, fill it.
451 if let Some(last_child) = node.last_mut() {
452 // Usually, we assert that there's a last child because the
453 // interior nodes are guaranteed to be non-empty. But within
454 // this function we sometimes create empty interior nodes to
455 // be filled later.
456 // TODO: can avoid the clone if it's already full
457 let Node::Leaf { data } = Rc::make_mut(last_child) else {
458 unreachable!();
459 };
460 let old_len = data.len();
461 data.extend(iter.take(N - data.len()));
462 consumed += data.len() - old_len;
463 }
464
465 while !node.is_full() && iter.peek().is_some() {
466 let data: Chunk<T, N> = iter.take(N).collect();
467 consumed += data.len();
468 node.push_back(Rc::new(Node::Leaf { data }));
469 }
470 } else {
471 if let Some(child) = node.last_mut() {
472 let Node::Interior { children } = Rc::make_mut(child) else {
473 unreachable!();
474 };
475
476 consumed += extend_rec(iter, children, height - 1);
477 }
478
479 while !node.is_full() && iter.peek().is_some() {
480 let mut new_child: Interior<T, N> = Chunk::new();
481 consumed += extend_rec(iter, &mut new_child, height - 1);
482 node.push_back(Rc::new(Node::Interior {
483 children: new_child,
484 }));
485 }
486 }
487
488 consumed
489 }
490
491 if iter.peek().is_some() && self.root.is_none() {
492 self.root = Some(Rc::new(Node::Leaf {
493 data: Chunk::default(),
494 }));
495 }
496 while iter.peek().is_some() {
497 // Unwrap: we ensured that if the iterator has anything, the root is present.
498 let consumed = match Rc::make_mut(self.root.as_mut().unwrap()) {
499 Node::Leaf { data } => {
500 let old_len = data.len();
501 data.extend((&mut iter).take(N - data.len()));
502 data.len() - old_len
503 }
504 Node::Interior { children } => extend_rec(&mut iter, children, self.height),
505 };
506 self.length += consumed;
507
508 // Check if there's more left in the iterator, and add a level if there is.
509 if iter.peek().is_some() {
510 self.add_level();
511 }
512 }
513 }
514}
515
516fn height_for_length<const N: usize>(length: usize) -> u8 {
517 // Length zero through N has height zero, length N + 1 through N^2 has height 1, etc.
518 // The unwrap is fine unless someone has a usize that's more than 256 bits.
519 length.saturating_sub(1).max(1).ilog(N).try_into().unwrap()
520}
521
522impl<T, const N: usize> Vector<T, N>
523where
524 Const<N>: ValidBranchingConstant,
525{
526 /// Create a new, empty, vector.
527 pub fn new() -> Self {
528 Self {
529 root: None,
530 length: 0,
531 height: 0,
532 }
533 }
534
535 /// The number of elements in this vector.
536 pub fn len(&self) -> usize {
537 self.length
538 }
539
540 /// Returns `true` if the length is zero.
541 pub fn is_empty(&self) -> bool {
542 self.length == 0
543 }
544}
545
546impl<T: Clone, const N: usize> Vector<T, N>
547where
548 Const<N>: ValidBranchingConstant,
549{
550 // Vectors must always be "packed to the left": every child that isn't the
551 // right-most child of its parent must have a complete subtree.
552 //
553 // This function checks that invariant. It's only used in tests.
554 fn is_packed(&self) -> bool {
555 fn is_packed_rec<T: Clone, const N: usize>(n: &Node<T, N>, right_most: bool) -> bool {
556 match n {
557 Node::Leaf { data } => data.is_full() || right_most,
558 Node::Interior { children } => {
559 if let Some((tail, others)) = children.split_last() {
560 others.iter().all(|n| is_packed_rec(n, false)) && is_packed_rec(tail, true)
561 } else {
562 debug_assert!(false, "empty node");
563 false
564 }
565 }
566 }
567 }
568
569 match &self.root {
570 None => true,
571 Some(root) => is_packed_rec(root, true),
572 }
573 }
574
575 /// Checks our internal invariants.
576 ///
577 /// It's public so that it can be used in out-of-crate tests.
578 #[doc(hidden)]
579 pub fn check_invariants(&self) {
580 assert!(self.is_packed());
581 assert_eq!(self.length, self.root.as_ref().map_or(0, |root| root.len()));
582 if let Some(root) = self.root.as_ref()
583 && let Node::Interior { children } = root.as_ref()
584 {
585 assert!(children.len() > 1);
586 }
587 assert_eq!(self.height, height_for_length::<N>(self.len()));
588 }
589
590 // Is this vector as full as it can be without increasing the height?
591 fn is_full(&self) -> bool {
592 self.root.is_none() || self.length == N.pow(u32::from(self.height) + 1)
593 }
594
595 /// Gets an element at a given index, or `None` if `idx` is out-of-bounds.
596 pub fn get(&self, idx: usize) -> Option<&T> {
597 self.root.as_ref().and_then(|r| r.get(self.height, idx))
598 }
599
600 /// Sets an element at a given index.
601 ///
602 /// Panics if the index is out of bounds.
603 pub fn set(&mut self, idx: usize, elt: T) {
604 if idx >= self.length {
605 panic!("index {idx} out of bounds, length is {}", self.length);
606 }
607
608 if let Some(root) = self.root.as_mut() {
609 Rc::make_mut(root).set(self.height, idx, elt);
610 }
611 }
612
613 // Increases the height of the tree by one, temporarily breaking the invariant that
614 // the root must have at least two children.
615 fn add_level(&mut self) {
616 match &mut self.root {
617 None => {
618 // We don't increment height in this case: height zero is used for both
619 // the empty vector and a vector with just one leaf.
620 // (Maybe we should use height 1 in the latter case?)
621 self.root = Some(Rc::new(Node::Leaf { data: Chunk::new() }));
622 }
623 Some(root) => {
624 let old_root = std::mem::replace(
625 root,
626 Rc::new(Node::Interior {
627 children: Chunk::new(),
628 }),
629 );
630
631 // TODO: maybe we can avoid the make_mut and the fallible destructuring?
632 // It seems a little tricky to do so without increasing some ref-counts.
633 let Node::Interior { children } = Rc::make_mut(root) else {
634 unreachable!();
635 };
636 children.push_back(old_root);
637 self.height += 1;
638 }
639 }
640 }
641
642 /// Adds an element to the end of this array.
643 ///
644 /// Runs in time complexity `O(log n)` where `n` is the array length.
645 pub fn push(&mut self, elt: T) {
646 if self.is_full() {
647 self.add_level();
648 }
649 let idx = self.len();
650 // unwrap: self.add_level ensures that the root is non-empty
651 Rc::make_mut(self.root.as_mut().unwrap()).set(self.height, idx, elt);
652 self.length += 1;
653 }
654
655 /// Removes and returns the element at the end of this array, or
656 /// `None` if we're empty.
657 ///
658 /// Runs in time complexity `O(log self.len())`.
659 pub fn pop(&mut self) -> Option<T> {
660 if self.is_empty() {
661 None
662 } else {
663 // Unwrap: if we aren't empty, we have a root.
664 let root_mut = Rc::make_mut(self.root.as_mut().unwrap());
665 let (ret, _empty) = root_mut.pop();
666 self.length -= 1;
667
668 // If we've shrunk the root down to a single child, reduce the tree height by 1.
669 if let Node::Interior { children } = root_mut
670 && children.len() == 1
671 {
672 self.root = Some(children.pop_back());
673 self.height -= 1;
674 }
675 Some(ret)
676 }
677 }
678
679 /// If `len` is less than our length, shortens this vector to length `len`.
680 ///
681 /// If `len` is greater than or equal to our length, does nothing.
682 ///
683 /// The running time is `O(log self.len() + (len - self.len()))`. That
684 /// is, it is linear in the number of elements to be discarded. Even if
685 /// the elements to be discarded have trivial destructors, we still need
686 /// to destroy (and potentially de-allocate) a linear number of internal
687 /// nodes. However, the constant factor in this linear term should be quite
688 /// small; you can expect that `truncate` is much faster than multiple calls
689 /// to `pop`.
690 pub fn truncate(&mut self, len: usize) {
691 if len >= self.length {
692 return;
693 }
694
695 let new_height = height_for_length::<N>(len);
696 if new_height < self.height {
697 // unwrap: if we were empty, we would have returned at the `len >= self.length` check.
698 let mut new_root = self.root.as_ref().unwrap();
699 for _ in new_height..self.height {
700 let Node::Interior { children } = new_root.as_ref() else {
701 unreachable!();
702 };
703 new_root = children.first().expect("empty interior node");
704 }
705 self.root = Some(Rc::clone(new_root));
706 self.height = new_height;
707 }
708
709 // unwrap: if we were empty, we would have returned at the `len >= self.length` check.
710 Rc::make_mut(self.root.as_mut().unwrap()).truncate(self.height, len);
711
712 self.length = len;
713 }
714
715 /// Returns an iterator over all elements in this vector.
716 ///
717 /// Iterator construction runs in `O(log self.len())` time. Each step
718 /// of the iteration runs in amortized constant time, worst-case `O(log
719 /// self.len())` time.
720 pub fn iter(&self) -> Iter<'_, T, N> {
721 self.into_iter()
722 }
723
724 /// Returns a mutable iterator over all elements in this vector.
725 ///
726 /// Iterator construction runs in `O(log self.len())` time. Each step
727 /// of the iteration runs in amortized constant time, worst-case `O(log
728 /// self.len())` time.
729 pub fn iter_mut(&mut self) -> IterMut<'_, T, N> {
730 self.into_iter()
731 }
732
733 /// Returns an iterator over borrowed elements in this vector, starting at a
734 /// specific index.
735 ///
736 /// Iterator construction runs in `O(log self.len())` time. Each step
737 /// of the iteration runs in amortized constant time, worst-case
738 /// `O(log self.len())` time. In particular, if `idx` is large then this is
739 /// much more efficient than calling `iter` and then advancing past `idx`
740 /// elements.
741 pub fn iter_starting_at(&self, idx: usize) -> Iter<'_, T, N> {
742 if idx == self.len() {
743 return Iter {
744 stack: Vec::new(),
745 leaf: [].iter(),
746 };
747 }
748 if idx > self.len() {
749 panic!("out of bounds");
750 }
751
752 let mut stack = Vec::with_capacity(self.height.into());
753 // unwrap: if we got past the initial tests on `idx`, we must be non-empty
754 // and so we have a root
755 let mut node = self.root.as_ref().unwrap().as_ref();
756 let mut height = self.height;
757
758 while let Node::Interior { children } = node {
759 let bucket_idx = extract_index::<N>(idx, height);
760 let mut node_iter = children[bucket_idx..].iter();
761
762 // expect: we've checked that `idx` is strictly less than the length,
763 // so this interior iterator should be non-empty also.
764 node = node_iter.next().expect("empty interior node");
765 stack.push(node_iter);
766
767 height = height.checked_sub(1).expect("invalid height");
768 }
769
770 let Node::Leaf { data } = node else {
771 unreachable!();
772 };
773 Iter {
774 stack,
775 leaf: data[(idx & (N - 1))..].iter(),
776 }
777 }
778
779 /// Returns an iterator over mutable elements in this vector, starting at a
780 /// specific index.
781 ///
782 /// Iterator construction runs in `O(log self.len())` time. Each step
783 /// of the iteration runs in amortized constant time, worst-case
784 /// `O(log self.len())` time. In particular, if `idx` is large then this is
785 /// much more efficient than calling `iter` and then advancing past `idx`
786 /// elements.
787 pub fn iter_mut_starting_at(&mut self, idx: usize) -> IterMut<'_, T, N> {
788 if idx == self.len() {
789 return IterMut {
790 stack: Vec::new(),
791 leaf: [].iter_mut(),
792 };
793 }
794 if idx > self.len() {
795 panic!("out of bounds");
796 }
797
798 let mut stack = Vec::with_capacity(self.height.into());
799 // unwrap: if we got past the initial tests on `idx`, we must be non-empty
800 // and so we have a root
801 let mut node = self.root.as_mut().unwrap();
802 let mut height = self.height;
803
804 while let Node::Interior { .. } = node.as_ref() {
805 let Node::Interior { children } = Rc::make_mut(node) else {
806 unreachable!("but we just checked it");
807 };
808
809 let bucket_idx = extract_index::<N>(idx, height);
810 let mut node_iter = children[bucket_idx..].iter_mut();
811
812 // expect: we've checked that `idx` is strictly less than the length,
813 // so this interior iterator should be non-empty also.
814 node = node_iter.next().expect("empty interior node");
815 stack.push(node_iter);
816
817 height = height.checked_sub(1).expect("invalid height");
818 }
819
820 let Node::Leaf { data } = Rc::make_mut(node) else {
821 unreachable!();
822 };
823 IterMut {
824 stack,
825 leaf: data[(idx & (N - 1))..].iter_mut(),
826 }
827 }
828
829 /// Returns an iterator over borrowed elements in this vector, starting at a
830 /// specific index.
831 ///
832 /// Iterator construction runs in `O(log self.len() + idx)` time. Each step
833 /// of the iteration runs in amortized constant time, worst-case
834 /// `O(log self.len())` time. Unlike the borrowed `iter_starting_at`, this is
835 /// not asymptotically faster than calling `into_iter` and then advancing
836 /// past `idx` elements, because we need to destruct and then potentially
837 /// de-allocate a linear (in `idx`) number of things. However, this method
838 /// should be faster in practice than iterating over `idx` elements.
839 pub fn into_iter_starting_at(self, mut idx: usize) -> IntoIter<T, N> {
840 if idx == self.len() {
841 return IntoIter {
842 stack: Vec::new(),
843 leaf: Chunk::new().into_iter(),
844 };
845 }
846 if idx > self.len() {
847 panic!("out of bounds");
848 }
849
850 let mut stack = Vec::with_capacity(self.height.into());
851 // unwrap: if we got past the initial tests on `idx`, we must be non-empty
852 // and so we have a root
853 let mut node = Rc::unwrap_or_clone(self.root.unwrap());
854 let mut height = self.height;
855
856 while let Node::Interior { mut children } = node {
857 let bucket_idx = extract_index::<N>(idx, height);
858 children.drop_left(bucket_idx);
859 let mut node_iter = children.into_iter();
860 node = Rc::unwrap_or_clone(node_iter.next().expect("empty interior node"));
861 stack.push(node_iter);
862
863 height = height.checked_sub(1).expect("invalid height");
864 }
865
866 let Node::Leaf { mut data } = node else {
867 unreachable!();
868 };
869 idx &= N - 1;
870 data.drop_left(idx);
871 IntoIter {
872 stack,
873 leaf: data.into_iter(),
874 }
875 }
876}
877
878impl<'a, T, const N: usize> IntoIterator for &'a Vector<T, N>
879where
880 Const<N>: ValidBranchingConstant,
881{
882 type Item = &'a T;
883 type IntoIter = Iter<'a, T, N>;
884
885 fn into_iter(self) -> Self::IntoIter {
886 let mut stack = Vec::with_capacity(self.height.into());
887 let Some(root) = &self.root else {
888 return Iter {
889 stack,
890 leaf: [].iter(),
891 };
892 };
893
894 let mut node = root.as_ref();
895 while let Node::Interior { children } = node {
896 let mut node_iter = children.iter();
897 node = node_iter.next().expect("empty interior node");
898 stack.push(node_iter);
899 }
900
901 let Node::Leaf { data } = node else {
902 unreachable!();
903 };
904 Iter {
905 stack,
906 leaf: data.iter(),
907 }
908 }
909}
910
911impl<'a, T, const N: usize> IntoIterator for &'a mut Vector<T, N>
912where
913 Const<N>: ValidBranchingConstant,
914 T: Clone,
915{
916 type Item = &'a mut T;
917 type IntoIter = IterMut<'a, T, N>;
918
919 fn into_iter(self) -> Self::IntoIter {
920 let mut stack = Vec::with_capacity(self.height.into());
921 let Some(root) = &mut self.root else {
922 return IterMut {
923 stack,
924 leaf: [].iter_mut(),
925 };
926 };
927
928 let mut node = root;
929 while let Node::Interior { .. } = node.as_ref() {
930 let Node::Interior { children } = Rc::make_mut(node) else {
931 unreachable!("but we just checked it");
932 };
933 let mut node_iter = children.iter_mut();
934 node = node_iter.next().expect("empty interior node");
935 stack.push(node_iter);
936 }
937
938 let Node::Leaf { data } = Rc::make_mut(node) else {
939 unreachable!();
940 };
941 IterMut {
942 stack,
943 leaf: data.iter_mut(),
944 }
945 }
946}
947
948impl<T: Clone, const N: usize> IntoIterator for Vector<T, N>
949where
950 Const<N>: ValidBranchingConstant,
951{
952 type Item = T;
953 type IntoIter = IntoIter<T, N>;
954
955 fn into_iter(self) -> Self::IntoIter {
956 let mut stack = Vec::with_capacity(self.height.into());
957 let Some(root) = self.root else {
958 return IntoIter {
959 stack,
960 leaf: Chunk::new().into_iter(),
961 };
962 };
963
964 let mut node = Rc::unwrap_or_clone(root);
965 while let Node::Interior { children } = node {
966 let mut node_iter = children.into_iter();
967 node = Rc::unwrap_or_clone(node_iter.next().expect("empty interior node"));
968 stack.push(node_iter);
969 }
970
971 let Node::Leaf { data } = node else {
972 unreachable!();
973 };
974 IntoIter {
975 stack,
976 leaf: data.into_iter(),
977 }
978 }
979}
980
981impl<T, const N: usize> Default for Vector<T, N>
982where
983 Const<N>: ValidBranchingConstant,
984{
985 fn default() -> Self {
986 Self::new()
987 }
988}
989
990impl<T: Clone, const N: usize> FromIterator<T> for Vector<T, N>
991where
992 Const<N>: ValidBranchingConstant,
993{
994 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
995 let mut ret = Vector::default();
996 ret.extend(iter);
997 ret
998 }
999}
1000
1001impl<T: Clone, const N: usize> Index<usize> for Vector<T, N>
1002where
1003 Const<N>: ValidBranchingConstant,
1004{
1005 type Output = T;
1006
1007 fn index(&self, index: usize) -> &Self::Output {
1008 self.get(index).expect("index out of range")
1009 }
1010}
1011
1012#[cfg(test)]
1013mod tests {
1014 use super::*;
1015
1016 #[test]
1017 fn basic() {
1018 let mut vec = Vector::<u32, 2>::new();
1019 vec.check_invariants();
1020 vec.push(1);
1021 assert_eq!(vec.get(0), Some(&1));
1022 assert_eq!(vec.get(1), None);
1023 vec.check_invariants();
1024
1025 vec.push(2);
1026 vec.check_invariants();
1027 vec.push(3);
1028 vec.check_invariants();
1029 assert_eq!(vec.get(0), Some(&1));
1030 assert_eq!(vec.get(1), Some(&2));
1031 assert_eq!(vec.get(2), Some(&3));
1032 assert_eq!(vec.get(3), None);
1033
1034 let mut iter = vec.iter();
1035 assert_eq!(iter.next(), Some(&1));
1036 assert_eq!(iter.next(), Some(&2));
1037 assert_eq!(iter.next(), Some(&3));
1038 assert_eq!(iter.next(), None);
1039
1040 assert_eq!(vec.iter().copied().collect::<Vec<_>>(), vec![1, 2, 3]);
1041
1042 assert_eq!(vec.pop(), Some(3));
1043 vec.check_invariants();
1044 vec.push(3);
1045 vec.check_invariants();
1046
1047 vec.extend([1, 2, 3]);
1048 vec.check_invariants();
1049 let mut iter = vec.iter();
1050 assert_eq!(iter.next(), Some(&1));
1051 assert_eq!(iter.next(), Some(&2));
1052 assert_eq!(iter.next(), Some(&3));
1053 assert_eq!(iter.next(), Some(&1));
1054 assert_eq!(iter.next(), Some(&2));
1055 assert_eq!(iter.next(), Some(&3));
1056 assert_eq!(iter.next(), None);
1057
1058 assert_eq!(6, vec.len());
1059 assert_eq!(
1060 vec.iter().copied().collect::<Vec<_>>(),
1061 vec![1, 2, 3, 1, 2, 3]
1062 );
1063 assert_eq!(vec.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 1, 2, 3]);
1064 }
1065}