vers_vecs/trees/bp/
mod.rs

1//! A succinct tree data structure backed by the balanced parenthesis representation.
2//! The tree supports navigation operations between parent, child, and sibling nodes in `O(log n)`
3//! time, as well as subtree size, level-order, and ancestor queries in `O(log n)` time.
4//! The tree is succinct (ideally sublinear space overhead) and pointer-less.
5
6use crate::bit_vec::fast_rs_vec::SelectIntoIter;
7use crate::trees::mmt::MinMaxTree;
8use crate::trees::{IsAncestor, LevelTree, SubtreeSize, Tree};
9use crate::{BitVec, RsVec};
10use std::cmp::{max, min};
11use std::iter::FusedIterator;
12
13/// The default block size for the tree, used in several const generics
14const DEFAULT_BLOCK_SIZE: usize = 512;
15
16const OPEN_PAREN: u64 = 1;
17const CLOSE_PAREN: u64 = 0;
18
19mod builder;
20// re-export the builders toplevel
21pub use builder::BpBuilder;
22
23#[cfg(feature = "bp_u16_lookup")]
24mod lookup;
25#[cfg(feature = "bp_u16_lookup")]
26use lookup::{process_block_bwd, process_block_fwd, LOOKUP_BLOCK_SIZE};
27
28#[cfg(not(feature = "bp_u16_lookup"))]
29mod lookup_query;
30#[cfg(not(feature = "bp_u16_lookup"))]
31use lookup_query::{process_block_bwd, process_block_fwd, LOOKUP_BLOCK_SIZE};
32
33/// A succinct tree data structure based on balanced parenthesis expressions.
34/// A tree with `n` nodes is encoded in a bit vector using `2n` bits plus the rank/select overhead
35/// of the [`RsVec`] implementation.
36/// Additionally, a small pointerless heap data structure stores
37/// additional meta information required to perform most tree operations.
38///
39/// The tree is thus pointer-less and succinct.
40/// It supports tree navigation operations between parent, child, and sibling nodes, both in
41/// depth-first search order and in level order.
42/// All operations run in `O(log n)` time with small overheads.
43///
44/// ## Lookup Table
45/// The tree internally uses a lookup table for subqueries on blocks of bits.
46/// The lookup table requires 4 KiB of memory and is compiled into the binary.
47/// If the `bp_u16_lookup` feature is enabled, a larger lookup table is used, which requires 128 KiB of
48/// memory, but answers queries faster.
49///
50/// ## Block Size
51/// The tree has a block size of 512 bits by default, which can be changed by setting the
52/// `BLOCK_SIZE` generic parameter.
53/// This block size is expected to be a good choice for most applications,
54/// as it will fit a cache line.
55///
56/// If you want to tune the parameter,
57/// the block size should be chosen based on the expected size of the tree and the available memory.
58/// Smaller block sizes increase the size of the supporting data structure but reduce the time
59/// complexity of some operations by a constant amount.
60/// Larger block sizes are best combined with the `bp_u16_lookup` feature to keep the query time
61/// low.
62/// In any case, benchmarking for the specific use case is recommended for tuning.
63///
64/// ## Unbalanced Parentheses
65/// The tree is implemented in a way to theoretically support unbalanced parenthesis expressions
66/// (which encode invalid trees) without panicking.
67/// However, some operations may behave erratically if the parenthesis expression isn't balanced.
68/// Generally, operations specify if they require a balanced tree.
69///
70/// The results of the operations are unspecified,
71/// meaning no guarantees are made about the stability of the results across versions
72/// (except the operations not panicking).
73/// However, for research purposes, this behavior can be useful and should yield expected results
74/// in most cases.
75///
76/// Only the basic operations like [`fwd_search`] and [`bwd_search`],
77/// as well as the tree navigation operations
78/// (defined by the traits [`Tree`], [`IsAncestor`], [`LevelTree`], and [`SubtreeSize`]),
79/// are included in this guarantee.
80/// Additional operations like iterators may panic if the tree is unbalanced (this is documented per
81/// operation).
82///
83/// # Examples
84///
85/// The high-level approach to building a tree is to use the [`BpBuilder`] to construct the tree
86/// using depth-first traversal of all its nodes.
87/// ```rust
88/// # #![allow(long_running_const_eval)] // for some reason this is needed for test cases
89/// use vers_vecs::{BitVec, BpBuilder, BpTree, TreeBuilder, Tree};
90///
91/// let mut builder = BpBuilder::<512>::new();
92///
93/// // build the tree by depth-first traversal
94/// builder.enter_node();
95/// builder.enter_node();
96/// builder.enter_node();
97/// builder.leave_node();
98/// builder.enter_node();
99/// builder.leave_node();
100/// builder.leave_node();
101/// builder.enter_node();
102/// builder.leave_node();
103/// builder.leave_node();
104///
105/// let tree = builder.build().unwrap();
106/// let root = tree.root().unwrap();
107/// assert_eq!(root, 0);
108/// assert_eq!(tree.first_child(root), Some(1));
109/// assert_eq!(tree.next_sibling(1), Some(7));
110/// assert_eq!(tree.next_sibling(7), None);
111///
112/// assert_eq!(root, 0);
113/// assert_eq!(tree.depth(2), 2);
114/// assert_eq!(tree.depth(7), 1);
115/// ```
116///
117/// Alternatively, the tree can be constructed from a [`BitVec`] containing the parenthesis
118/// expression directly.
119/// This is also how trees with unbalanced parenthesis expressions can be constructed.
120///
121/// ```rust
122/// # #![allow(long_running_const_eval)]
123/// use vers_vecs::{BitVec, BpTree, Tree};
124/// let bv = BitVec::pack_sequence_u8(&[0b1101_0111, 0b0010_0100], 8);
125/// let tree = BpTree::<4>::from_bit_vector(bv);
126///
127/// let nodes = tree.dfs_iter().collect::<Vec<_>>();
128/// assert_eq!(nodes, vec![0, 1, 2, 4, 6, 7, 10, 13]);
129/// ```
130///
131/// [`RsVec`]: RsVec
132/// [`fwd_search`]: BpTree::fwd_search
133/// [`bwd_search`]: BpTree::bwd_search
134/// [`Tree`]: Tree
135/// [`IsAncestor`]: IsAncestor
136/// [`LevelTree`]: LevelTree
137/// [`SubtreeSize`]: SubtreeSize
138/// [`BpBuilder`]: BpBuilder
139/// [`BitVec`]: BitVec
140#[derive(Clone, Debug)]
141#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
142pub struct BpTree<const BLOCK_SIZE: usize = DEFAULT_BLOCK_SIZE> {
143    vec: RsVec,
144    min_max_tree: MinMaxTree,
145}
146
147impl<const BLOCK_SIZE: usize> BpTree<BLOCK_SIZE> {
148    /// Construct a new `BpTree` from a given bit vector.
149    #[must_use]
150    pub fn from_bit_vector(bv: BitVec) -> Self {
151        let min_max_tree = MinMaxTree::excess_tree(&bv, BLOCK_SIZE);
152        let vec = bv.into();
153        Self { vec, min_max_tree }
154    }
155
156    /// Search for a position where the excess relative to the starting `index` is `relative_excess`.
157    /// Returns `None` if no such position exists.
158    /// The initial position is never considered in the search.
159    /// Searches forward in the bit vector.
160    ///
161    /// # Arguments
162    /// - `index`: The starting index.
163    /// - `relative_excess`: The desired relative excess value.
164    pub fn fwd_search(&self, index: usize, mut relative_excess: i64) -> Option<usize> {
165        // check for greater than or equal length minus one, because the last element
166        // won't ever have a result from fwd_search
167        if index >= (self.vec.len() - 1) {
168            return None;
169        }
170
171        let block_index = (index + 1) / BLOCK_SIZE;
172        self.fwd_search_block(index, block_index, &mut relative_excess)
173            .map_or_else(
174                |()| {
175                    // find the block that contains the desired relative excess
176                    let block = self.min_max_tree.fwd_search(block_index, relative_excess);
177
178                    // check the result block for the exact position
179                    block.and_then(|(block, mut relative_excess)| {
180                        self.fwd_search_block(block * BLOCK_SIZE - 1, block, &mut relative_excess)
181                            .ok()
182                    })
183                },
184                Some,
185            )
186    }
187
188    /// Perform the forward search within one block. If this doesn't yield a result, the caller must
189    /// continue the search in the min-max-tree.
190    ///
191    /// Returns Ok(index) if an index with the desired relative excess is found, or None(excess)
192    /// with the excess at the end of the current block if no index with the desired relative excess
193    /// is found.
194    #[inline(always)]
195    fn fwd_search_block(
196        &self,
197        start_index: usize,
198        block_index: usize,
199        relative_excess: &mut i64,
200    ) -> Result<usize, ()> {
201        let block_boundary = min((block_index + 1) * BLOCK_SIZE, self.vec.len());
202
203        // the boundary at which we can start with table lookups
204        let lookup_boundary = min(
205            (start_index + 1).div_ceil(LOOKUP_BLOCK_SIZE as usize) * LOOKUP_BLOCK_SIZE as usize,
206            block_boundary,
207        );
208        for i in start_index + 1..lookup_boundary {
209            let bit = self.vec.get_unchecked(i);
210            *relative_excess -= if bit == 1 { 1 } else { -1 };
211
212            if *relative_excess == 0 {
213                return Ok(i);
214            }
215        }
216
217        // the boundary up to which we can use table lookups
218        let upper_lookup_boundary = max(
219            lookup_boundary,
220            (block_boundary / LOOKUP_BLOCK_SIZE as usize) * LOOKUP_BLOCK_SIZE as usize,
221        );
222
223        for i in (lookup_boundary..upper_lookup_boundary).step_by(LOOKUP_BLOCK_SIZE as usize) {
224            if let Ok(idx) = process_block_fwd(
225                self.vec
226                    .get_bits_unchecked(i, LOOKUP_BLOCK_SIZE as usize)
227                    .try_into()
228                    .unwrap(),
229                relative_excess,
230            ) {
231                return Ok(i + idx as usize);
232            }
233        }
234
235        // if the upper_lookup_boundary isn't the block_boundary (which happens in non-full blocks, i.e. the last
236        // block in the vector)
237        for i in upper_lookup_boundary..block_boundary {
238            let bit = self.vec.get_unchecked(i);
239            *relative_excess -= if bit == 1 { 1 } else { -1 };
240
241            if *relative_excess == 0 {
242                return Ok(i);
243            }
244        }
245
246        Err(())
247    }
248
249    /// Search for a position where the excess relative to the starting `index` is `relative_excess`.
250    /// Returns `None` if no such position exists.
251    /// The initial position is never considered in the search.
252    /// Searches backward in the bit vector.
253    ///
254    /// # Arguments
255    /// - `index`: The starting index.
256    /// - `relative_excess`: The desired relative excess value.
257    pub fn bwd_search(&self, index: usize, mut relative_excess: i64) -> Option<usize> {
258        if index >= self.vec.len() {
259            return None;
260        }
261
262        // if the index is 0, we cant have a valid result anyway, and this would overflow the
263        // subtraction below, so we report None
264        if index == 0 {
265            return None;
266        }
267
268        // calculate the block we start searching in. It starts at index - 1, so we don't accidentally
269        // search the mM tree and immediately find `index` as the position
270        let block_index = (index - 1) / BLOCK_SIZE;
271
272        // check the current block
273        self.bwd_search_block(index, block_index, &mut relative_excess)
274            .map_or_else(
275                |()| {
276                    // find the block that contains the desired relative excess
277                    let block = self.min_max_tree.bwd_search(block_index, relative_excess);
278
279                    // check the result block for the exact position
280                    block.and_then(|(block, mut relative_excess)| {
281                        self.bwd_search_block((block + 1) * BLOCK_SIZE, block, &mut relative_excess)
282                            .ok()
283                    })
284                },
285                Some,
286            )
287    }
288
289    /// Perform the backward search within one block. If this doesn't yield a result, the caller must
290    /// continue the search in the min-max-tree.
291    ///
292    /// Returns Ok(index) if an index with the desired relative excess is found, or None(excess)
293    /// with the excess at the end of the current block if no index with the desired relative excess
294    /// is found.
295    #[inline(always)]
296    fn bwd_search_block(
297        &self,
298        start_index: usize,
299        block_index: usize,
300        relative_excess: &mut i64,
301    ) -> Result<usize, ()> {
302        let block_boundary = min(block_index * BLOCK_SIZE, self.vec.len());
303
304        // the boundary at which we can start with table lookups
305        let lookup_boundary = max(
306            ((start_index - 1) / LOOKUP_BLOCK_SIZE as usize) * LOOKUP_BLOCK_SIZE as usize,
307            block_boundary,
308        );
309        for i in (lookup_boundary..start_index).rev() {
310            let bit = self.vec.get_unchecked(i);
311            *relative_excess += if bit == 1 { 1 } else { -1 };
312
313            if *relative_excess == 0 {
314                return Ok(i);
315            }
316        }
317
318        for i in (block_boundary..lookup_boundary)
319            .step_by(LOOKUP_BLOCK_SIZE as usize)
320            .rev()
321        {
322            if let Ok(idx) = process_block_bwd(
323                self.vec
324                    .get_bits_unchecked(i, LOOKUP_BLOCK_SIZE as usize)
325                    .try_into()
326                    .unwrap(),
327                relative_excess,
328            ) {
329                return Ok(i + idx as usize);
330            }
331        }
332
333        Err(())
334    }
335
336    /// Find the position of the matching closing parenthesis for the opening parenthesis at `index`.
337    /// If the bit at `index` is not an opening parenthesis, the result is meaningless.
338    /// If there is no matching closing parenthesis, `None` is returned.
339    #[must_use]
340    pub fn close(&self, index: usize) -> Option<usize> {
341        if index >= self.vec.len() {
342            return None;
343        }
344
345        self.fwd_search(index, -1)
346    }
347
348    /// Find the position of the matching opening parenthesis for the closing parenthesis at `index`.
349    /// If the bit at `index` is not a closing parenthesis, the result is meaningless.
350    /// If there is no matching opening parenthesis, `None` is returned.
351    #[must_use]
352    pub fn open(&self, index: usize) -> Option<usize> {
353        if index >= self.vec.len() {
354            return None;
355        }
356
357        self.bwd_search(index, -1)
358    }
359
360    /// Find the position of the opening parenthesis that encloses the position `index`.
361    /// This works regardless of whether the bit at `index` is an opening or closing parenthesis.
362    /// If there is no enclosing parenthesis, `None` is returned.
363    #[must_use]
364    pub fn enclose(&self, index: usize) -> Option<usize> {
365        if index >= self.vec.len() {
366            return None;
367        }
368
369        self.bwd_search(
370            index,
371            if self.vec.get_unchecked(index) == 1 {
372                -1
373            } else {
374                -2
375            },
376        )
377    }
378
379    /// Get the excess of open parentheses up to and including the position `index`.
380    /// The excess is the number of open parentheses minus the number of closing parentheses.
381    /// If `index` is out of bounds, the total excess of the parentheses expression is returned.
382    #[must_use]
383    pub fn excess(&self, index: usize) -> i64 {
384        debug_assert!(index < self.vec.len(), "Index out of bounds");
385        self.vec.rank1(index + 1) as i64 - self.vec.rank0(index + 1) as i64
386    }
387
388    /// Iterate over the nodes of the tree.
389    /// The iterator yields the nodes in depth-first (pre-)order.
390    /// This method is an alias for [`dfs_iter`].
391    ///
392    /// If the tree is unbalanced, the iterator returns the node handles in the order they appear in
393    /// the parenthesis expression, and it will return handles that don't have a matching closing
394    /// parenthesis.
395    ///
396    /// [`dfs_iter`]: BpTree::dfs_iter
397    pub fn iter(
398        &self,
399    ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
400        self.dfs_iter()
401    }
402
403    /// Iterate over the nodes of the tree in depth-first (pre-)order.
404    /// This is the most efficient way to iterate over all nodes of the tree.
405    ///
406    /// If the tree is unbalanced, the iterator returns the node handles in the order they appear in
407    /// the parenthesis expression, and it will return handles that don't have a matching closing
408    /// parenthesis.
409    pub fn dfs_iter(
410        &self,
411    ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
412        self.vec.iter1()
413    }
414
415    /// Iterate over the nodes of a valid tree in depth-first (post-)order.
416    /// This is slower than the pre-order iteration.
417    ///
418    /// # Panics
419    /// The iterator may panic at any point if the parenthesis expression is unbalanced.
420    pub fn dfs_post_iter(
421        &self,
422    ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
423        self.vec.iter0().map(|n| self.open(n).unwrap())
424    }
425
426    /// Iterate over a subtree rooted at `node` in depth-first (pre-)order.
427    /// The iteration starts with the node itself.
428    ///
429    /// Calling this method on an invalid node handle, or an unbalanced parenthesis expression,
430    /// will produce an iterator over an unspecified subset of nodes.
431    pub fn subtree_iter(
432        &self,
433        node: <BpTree<BLOCK_SIZE> as Tree>::NodeHandle,
434    ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
435        debug_assert!(
436            self.vec.get(node) == Some(OPEN_PAREN),
437            "Node handle is invalid"
438        );
439
440        let index = self.vec.rank1(node);
441        let close = self.close(node).unwrap_or(node);
442        let subtree_size = self.vec.rank1(close) - index;
443
444        self.vec.iter1().skip(index).take(subtree_size)
445    }
446
447    /// Iterate over a subtree rooted at `node` in depth-first (post-)order.
448    /// This is slower than the pre-order iteration.
449    /// The iteration ends with the node itself.
450    ///
451    /// # Panics
452    /// Calling this method on an invalid node handle, or an unbalanced parenthesis expression,
453    /// will produce an iterator over an unspecified subset of nodes, or panic either during
454    /// construction or iteration.
455    pub fn subtree_post_iter(
456        &self,
457        node: <BpTree<BLOCK_SIZE> as Tree>::NodeHandle,
458    ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
459        debug_assert!(
460            self.vec.get(node) == Some(OPEN_PAREN),
461            "Node handle is invalid"
462        );
463
464        let index = self.vec.rank0(node);
465        let close = self.close(node).unwrap_or(node);
466        let subtree_size = self.vec.rank0(close) + 1 - index;
467
468        self.vec
469            .iter0()
470            .skip(index)
471            .take(subtree_size)
472            .map(|n| self.open(n).unwrap())
473    }
474
475    /// Iterate over the children of a node in the tree.
476    /// The iterator yields the children in the order they appear in the parenthesis expression.
477    /// If the node is a leaf, the iterator is empty.
478    /// If the node is not a valid node handle, or the tree is unbalanced,
479    /// the iterator will produce an unspecified subset of the tree's nodes.
480    pub fn children(
481        &self,
482        node: <BpTree<BLOCK_SIZE> as Tree>::NodeHandle,
483    ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
484        debug_assert!(
485            self.vec.get(node) == Some(OPEN_PAREN),
486            "Node handle is invalid"
487        );
488
489        ChildrenIter::<BLOCK_SIZE, true>::new(self, node)
490    }
491
492    /// Iterate over the children of a node in the tree in reverse order.
493    /// The iterator yields the children in the reverse order they appear in the parenthesis expression.
494    /// If the node is a leaf, the iterator is empty.
495    /// If the node is not a valid node handle, or the tree is unbalanced,
496    /// the iterator will produce an unspecified subset of the tree's nodes.
497    pub fn rev_children(
498        &self,
499        node: <BpTree<BLOCK_SIZE> as Tree>::NodeHandle,
500    ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
501        debug_assert!(
502            self.vec.get(node) == Some(OPEN_PAREN),
503            "Node handle is invalid"
504        );
505
506        ChildrenIter::<BLOCK_SIZE, false>::new(self, node)
507    }
508
509    /// Transform the tree into a [`RsVec`] containing the balanced parenthesis expression.
510    /// This consumes the tree and returns the underlying bit vector with the rank and select
511    /// support structure.
512    /// The remaining min-max-tree support structure of the `BpTree` is discarded.
513    /// Since the tree is innately immutable, this is the only way to access the underlying bit
514    /// vector for potential modification.
515    /// Modification requires turning the `RsVec` back into a `BitVec`, discarding the rank and select
516    /// support structure, however.
517    ///
518    /// # Examples
519    /// ```rust
520    /// use vers_vecs::{BitVec, RsVec, BpTree, Tree};
521    ///
522    /// let bv = BitVec::pack_sequence_u8(&[0b1101_0111, 0b0010_0100], 8);
523    /// let tree = BpTree::<4>::from_bit_vector(bv);
524    /// assert_eq!(tree.size(), 8);
525    ///
526    /// let rs_vec = tree.into_parentheses_vec();
527    /// let mut bv = rs_vec.into_bit_vec();
528    ///
529    /// bv.flip_bit(15);
530    /// bv.append_bits(0, 2);
531    /// let tree = BpTree::<4>::from_bit_vector(bv);
532    /// assert_eq!(tree.size(), 9);
533    /// ```
534    #[must_use]
535    pub fn into_parentheses_vec(self) -> RsVec {
536        self.vec
537    }
538
539    /// Returns the number of bytes used on the heap for this tree. This does not include
540    /// allocated space that is not used (e.g. by the allocation behavior of `Vec`).
541    #[must_use]
542    pub fn heap_size(&self) -> usize {
543        self.vec.heap_size() + self.min_max_tree.heap_size()
544    }
545}
546
547impl<const BLOCK_SIZE: usize> Tree for BpTree<BLOCK_SIZE> {
548    type NodeHandle = usize;
549
550    fn root(&self) -> Option<Self::NodeHandle> {
551        if self.vec.is_empty() {
552            None
553        } else {
554            Some(0)
555        }
556    }
557
558    fn parent(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
559        debug_assert!(
560            self.vec.get(node) == Some(OPEN_PAREN),
561            "Node handle is invalid"
562        );
563
564        self.enclose(node)
565    }
566
567    fn first_child(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
568        debug_assert!(
569            self.vec.get(node) == Some(OPEN_PAREN),
570            "Node handle is invalid"
571        );
572
573        if let Some(bit) = self.vec.get(node + 1) {
574            if bit == OPEN_PAREN {
575                return Some(node + 1);
576            }
577        }
578
579        None
580    }
581
582    fn next_sibling(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
583        debug_assert!(
584            self.vec.get(node) == Some(OPEN_PAREN),
585            "Node handle is invalid"
586        );
587        self.close(node).and_then(|i| {
588            self.vec
589                .get(i + 1)
590                .and_then(|bit| if bit == OPEN_PAREN { Some(i + 1) } else { None })
591        })
592    }
593
594    fn previous_sibling(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
595        debug_assert!(
596            self.vec.get(node) == Some(OPEN_PAREN),
597            "Node handle is invalid"
598        );
599        if node == 0 {
600            None
601        } else {
602            self.vec.get(node - 1).and_then(|bit| {
603                if bit == CLOSE_PAREN {
604                    self.open(node - 1)
605                } else {
606                    None
607                }
608            })
609        }
610    }
611
612    fn last_child(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
613        debug_assert!(
614            self.vec.get(node) == Some(OPEN_PAREN),
615            "Node handle is invalid"
616        );
617        self.vec.get(node + 1).and_then(|bit| {
618            if bit == OPEN_PAREN {
619                if let Some(i) = self.close(node) {
620                    self.open(i - 1)
621                } else {
622                    None
623                }
624            } else {
625                None
626            }
627        })
628    }
629
630    fn node_index(&self, node: Self::NodeHandle) -> usize {
631        debug_assert!(
632            self.vec.get(node) == Some(OPEN_PAREN),
633            "Node handle is invalid"
634        );
635        self.vec.rank1(node)
636    }
637
638    fn node_handle(&self, index: usize) -> Self::NodeHandle {
639        self.vec.select1(index)
640    }
641
642    fn is_leaf(&self, node: Self::NodeHandle) -> bool {
643        debug_assert!(
644            self.vec.get(node) == Some(OPEN_PAREN),
645            "Node handle is invalid"
646        );
647        self.vec.get(node + 1) == Some(CLOSE_PAREN)
648    }
649
650    fn depth(&self, node: Self::NodeHandle) -> u64 {
651        debug_assert!(
652            self.vec.get(node) == Some(OPEN_PAREN),
653            "Node handle is invalid"
654        );
655        let excess: u64 = self.excess(node).try_into().unwrap_or(0);
656        excess.saturating_sub(1)
657    }
658
659    fn size(&self) -> usize {
660        self.vec.rank1(self.vec.len())
661    }
662
663    fn is_empty(&self) -> bool {
664        self.vec.is_empty()
665    }
666}
667
668impl<const BLOCK_SIZE: usize> IsAncestor for BpTree<BLOCK_SIZE> {
669    fn is_ancestor(
670        &self,
671        ancestor: Self::NodeHandle,
672        descendant: Self::NodeHandle,
673    ) -> Option<bool> {
674        debug_assert!(
675            self.vec.get(ancestor) == Some(OPEN_PAREN),
676            "Node handle is invalid"
677        );
678        debug_assert!(
679            self.vec.get(descendant) == Some(OPEN_PAREN),
680            "Node handle is invalid"
681        );
682
683        self.close(ancestor)
684            .map(|closing| ancestor <= descendant && descendant < closing)
685    }
686}
687
688impl<const BLOCK_SIZE: usize> LevelTree for BpTree<BLOCK_SIZE> {
689    fn level_ancestor(&self, node: Self::NodeHandle, level: u64) -> Option<Self::NodeHandle> {
690        if level == 0 {
691            return Some(node);
692        }
693
694        #[allow(clippy::cast_possible_wrap)]
695        // if the level exceeds 2^63, we accept that the result is wrong
696        self.bwd_search(node, -(level as i64))
697    }
698
699    fn level_next(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
700        self.fwd_search(self.close(node)?, 1)
701    }
702
703    fn level_prev(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
704        self.open(self.bwd_search(node, 1)?)
705    }
706
707    fn level_leftmost(&self, level: u64) -> Option<Self::NodeHandle> {
708        // fwd_search doesn't support returning the input position
709        if level == 0 {
710            return Some(0);
711        }
712
713        #[allow(clippy::cast_possible_wrap)]
714        // if the level exceeds 2^63, we accept that the result is wrong
715        self.fwd_search(0, level as i64)
716    }
717
718    fn level_rightmost(&self, level: u64) -> Option<Self::NodeHandle> {
719        #[allow(clippy::cast_possible_wrap)]
720        // if the level exceeds 2^63, we accept that the result is wrong
721        self.open(self.bwd_search(self.size() * 2 - 1, level as i64)?)
722    }
723}
724
725impl<const BLOCK_SIZE: usize> SubtreeSize for BpTree<BLOCK_SIZE> {
726    fn subtree_size(&self, node: Self::NodeHandle) -> Option<usize> {
727        debug_assert!(
728            self.vec.get(node) == Some(OPEN_PAREN),
729            "Node handle is invalid"
730        );
731
732        self.close(node)
733            .map(|c| self.vec.rank1(c) - self.vec.rank1(node))
734    }
735}
736
737impl<const BLOCK_SIZE: usize> IntoIterator for BpTree<BLOCK_SIZE> {
738    type Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle;
739    type IntoIter = SelectIntoIter<false>;
740
741    fn into_iter(self) -> Self::IntoIter {
742        self.vec.into_iter1()
743    }
744}
745
746impl<const BLOCK_SIZE: usize> From<BitVec> for BpTree<BLOCK_SIZE> {
747    fn from(bv: BitVec) -> Self {
748        Self::from_bit_vector(bv)
749    }
750}
751
752impl<const BLOCK_SIZE: usize> From<BpTree<BLOCK_SIZE>> for BitVec {
753    fn from(value: BpTree<BLOCK_SIZE>) -> Self {
754        value.into_parentheses_vec().into_bit_vec()
755    }
756}
757
758impl<const BLOCK_SIZE: usize> From<BpTree<BLOCK_SIZE>> for RsVec {
759    fn from(value: BpTree<BLOCK_SIZE>) -> Self {
760        value.into_parentheses_vec()
761    }
762}
763
764/// An iterator over the children of a node.
765/// Calls to `next` return the next child node handle in the order they appear in the parenthesis
766/// expression.
767struct ChildrenIter<'a, const BLOCK_SIZE: usize, const FORWARD: bool> {
768    tree: &'a BpTree<BLOCK_SIZE>,
769    current_sibling: Option<usize>,
770}
771
772impl<'a, const BLOCK_SIZE: usize, const FORWARD: bool> ChildrenIter<'a, BLOCK_SIZE, FORWARD> {
773    fn new(tree: &'a BpTree<BLOCK_SIZE>, node: usize) -> Self {
774        Self {
775            tree,
776            current_sibling: if FORWARD {
777                tree.first_child(node)
778            } else {
779                tree.last_child(node)
780            },
781        }
782    }
783}
784
785impl<const BLOCK_SIZE: usize, const FORWARD: bool> Iterator
786    for ChildrenIter<'_, BLOCK_SIZE, FORWARD>
787{
788    type Item = usize;
789
790    fn next(&mut self) -> Option<Self::Item> {
791        let current = self.current_sibling?;
792        let next = if FORWARD {
793            self.tree.next_sibling(current)
794        } else {
795            self.tree.previous_sibling(current)
796        };
797        self.current_sibling = next;
798        Some(current)
799    }
800}
801
802impl<const BLOCK_SIZE: usize, const FORWARD: bool> FusedIterator
803    for ChildrenIter<'_, BLOCK_SIZE, FORWARD>
804{
805}
806
807#[cfg(test)]
808mod tests;