Skip to main content

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