use alloc::vec::Vec;
use crate::bounds::{Bounds, union_all};
use crate::indexable::Indexable;
#[derive(Debug, Clone)]
pub enum Node<T> {
Leaf(Vec<T>),
Branch(Vec<(Bounds, Node<T>)>),
}
impl<T: Indexable> Node<T> {
#[must_use]
pub fn bounds(&self) -> Option<Bounds> {
match self {
Node::Leaf(values) => {
if values.is_empty() {
None
} else {
let boxes: Vec<Bounds> = values.iter().map(Indexable::bounds).collect();
Some(union_all(&boxes))
}
}
Node::Branch(children) => {
if children.is_empty() {
None
} else {
let boxes: Vec<Bounds> = children.iter().map(|(b, _)| *b).collect();
Some(union_all(&boxes))
}
}
}
}
#[must_use]
pub fn entry_count(&self) -> usize {
match self {
Node::Leaf(values) => values.len(),
Node::Branch(children) => children.len(),
}
}
#[must_use]
pub fn value_count(&self) -> usize {
match self {
Node::Leaf(values) => values.len(),
Node::Branch(children) => children.iter().map(|(_, child)| child.value_count()).sum(),
}
}
#[must_use]
pub fn height(&self) -> usize {
match self {
Node::Leaf(_) => 1,
Node::Branch(children) => {
1 + children
.iter()
.map(|(_, child)| child.height())
.max()
.unwrap_or(0)
}
}
}
}
#[cfg(test)]
mod tests {
use super::Node;
use crate::bounds::Bounds;
#[test]
fn leaf_bounds_union_of_values() {
let leaf: Node<Bounds> = Node::Leaf(alloc::vec![
Bounds::point([0.0, 0.0]),
Bounds::point([2.0, 3.0]),
]);
assert_eq!(leaf.bounds(), Some(Bounds::new([0.0, 0.0], [2.0, 3.0])));
assert_eq!(leaf.entry_count(), 2);
assert_eq!(leaf.height(), 1);
}
#[test]
fn branch_bounds_and_height() {
let leaf_a: Node<Bounds> = Node::Leaf(alloc::vec![Bounds::point([0.0, 0.0])]);
let leaf_b: Node<Bounds> = Node::Leaf(alloc::vec![Bounds::point([5.0, 5.0])]);
let branch: Node<Bounds> = Node::Branch(alloc::vec![
(leaf_a.bounds().unwrap(), leaf_a),
(leaf_b.bounds().unwrap(), leaf_b),
]);
assert_eq!(branch.bounds(), Some(Bounds::new([0.0, 0.0], [5.0, 5.0])));
assert_eq!(branch.height(), 2);
assert_eq!(branch.value_count(), 2);
}
#[test]
fn empty_leaf_has_no_bounds() {
let leaf: Node<Bounds> = Node::Leaf(alloc::vec![]);
assert_eq!(leaf.bounds(), None);
}
#[test]
fn empty_branch_has_no_bounds_or_values() {
let branch: Node<Bounds> = Node::Branch(alloc::vec![]);
assert_eq!(branch.bounds(), None);
assert_eq!(branch.entry_count(), 0);
assert_eq!(branch.value_count(), 0);
assert_eq!(branch.height(), 1);
}
}