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