use std::ops::Range;
use crate::SurfaceIndex;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct NodeIndex(pub usize);
impl From<usize> for NodeIndex {
#[inline(always)]
fn from(index: usize) -> Self {
NodeIndex(index)
}
}
impl NodeIndex {
#[inline(always)]
pub const fn root() -> Self {
Self(0)
}
#[inline(always)]
pub const fn left(self) -> Self {
Self(self.0 * 2 + 1)
}
#[inline(always)]
pub const fn right(self) -> Self {
Self(self.0 * 2 + 2)
}
#[inline]
pub const fn parent(self) -> Option<Self> {
if self.0 > 0 {
Some(Self((self.0 - 1) / 2))
} else {
None
}
}
#[inline(always)]
pub const fn level(self) -> usize {
(usize::BITS - (self.0 + 1).leading_zeros()) as usize
}
#[inline(always)]
pub const fn is_left(self) -> bool {
!self.0.is_multiple_of(2)
}
#[inline(always)]
pub const fn is_right(self) -> bool {
self.0.is_multiple_of(2)
}
#[inline]
pub(super) const fn children_at(self, level: usize) -> Range<usize> {
let base = 1 << level;
let s = (self.0 + 1) * base - 1;
let e = (self.0 + 2) * base - 1;
s..e
}
#[inline]
pub(super) const fn children_left(self, level: usize) -> Range<usize> {
let base = 1 << level;
let s = (self.0 + 1) * base - 1;
let e = (self.0 + 1) * base + (base / 2) - 1;
s..e
}
#[inline]
pub(super) const fn children_right(self, level: usize) -> Range<usize> {
let base = 1 << level;
let s = (self.0 + 1) * base + (base / 2) - 1;
let e = (self.0 + 2) * base - 1;
s..e
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct NodePath {
pub surface: SurfaceIndex,
pub node: NodeIndex,
}
impl NodePath {
pub const MAIN_ROOT: Self = Self {
surface: SurfaceIndex::main(),
node: NodeIndex::root(),
};
pub const fn new(surface: SurfaceIndex, node: NodeIndex) -> Self {
Self { surface, node }
}
pub const fn left_node(self) -> Self {
Self {
surface: self.surface,
node: self.node.left(),
}
}
pub const fn right_node(self) -> Self {
Self {
surface: self.surface,
node: self.node.right(),
}
}
}