use crate::rstar::envelope::Envelope;
use crate::rstar::object::RTreeObject;
use crate::rstar::params::RTreeParams;
use alloc::vec::Vec;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(
serialize = "T: Serialize, E: Serialize",
deserialize = "T: Deserialize<'de>, E: Deserialize<'de>"
))
)]
pub enum RTreeNode<T, E = <T as RTreeObject>::Envelope> {
Leaf(T),
Parent(ParentNode<T, E>),
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ParentNode<T, E = <T as RTreeObject>::Envelope> {
pub(crate) children: Vec<RTreeNode<T, E>>,
pub(crate) envelope: E,
}
impl<T> RTreeObject for RTreeNode<T>
where
T: RTreeObject,
{
type Envelope = T::Envelope;
fn envelope(&self) -> Self::Envelope {
match self {
RTreeNode::Leaf(t) => t.envelope(),
RTreeNode::Parent(data) => data.envelope.clone(),
}
}
}
#[doc(hidden)]
impl<T, E> RTreeNode<T, E> {
pub fn is_leaf(&self) -> bool {
match self {
RTreeNode::Leaf(..) => true,
RTreeNode::Parent(..) => false,
}
}
}
impl<T> ParentNode<T>
where
T: RTreeObject,
{
pub fn children(&self) -> &[RTreeNode<T>] {
&self.children
}
pub fn envelope(&self) -> T::Envelope {
self.envelope.clone()
}
pub(crate) fn new_root<Params>() -> Self
where
Params: RTreeParams,
{
ParentNode {
envelope: Envelope::new_empty(),
children: Vec::with_capacity(Params::MAX_SIZE + 1),
}
}
pub(crate) fn new_parent(children: Vec<RTreeNode<T>>) -> Self {
let envelope = envelope_for_children(&children);
ParentNode { envelope, children }
}
#[cfg(test)]
#[allow(missing_docs)]
pub(crate) fn sanity_check<Params>(&self, check_max_size: bool) -> Option<usize>
where
Params: RTreeParams,
{
if self.children.is_empty() {
Some(0)
} else {
let mut result = None;
self.sanity_check_inner::<Params>(check_max_size, 1, &mut result);
result
}
}
#[cfg(test)]
fn sanity_check_inner<Params>(
&self,
check_max_size: bool,
height: usize,
leaf_height: &mut Option<usize>,
) where
Params: RTreeParams,
{
if height > 1 {
let min_size = Params::MIN_SIZE;
assert!(self.children.len() >= min_size);
}
let mut envelope = T::Envelope::new_empty();
if check_max_size {
let max_size = Params::MAX_SIZE;
assert!(self.children.len() <= max_size);
}
for child in &self.children {
match child {
RTreeNode::Leaf(t) => {
envelope.merge(&t.envelope());
if let Some(leaf_height) = leaf_height {
assert_eq!(height, *leaf_height);
} else {
*leaf_height = Some(height);
}
}
RTreeNode::Parent(data) => {
envelope.merge(&data.envelope);
data.sanity_check_inner::<Params>(check_max_size, height + 1, leaf_height);
}
}
}
assert!(self.envelope == envelope);
}
}
pub fn envelope_for_children<T>(children: &[RTreeNode<T>]) -> T::Envelope
where
T: RTreeObject,
{
let mut result = T::Envelope::new_empty();
for child in children {
result.merge(&child.envelope());
}
result
}