use crate::{
edge::Edge,
error::{Error, Result},
};
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(derive_more::Deref, derive_more::DerefMut)]
pub struct Node<D, P, C> {
pub idx: NodeIdx,
pub parents: Vec<(NodeIdx, P)>,
pub children: Vec<(NodeIdx, C)>,
#[deref]
#[deref_mut]
pub data: D,
}
impl<D, P, C> Node<D, P, C> {
pub fn new(idx: NodeIdx, data: D) -> Self {
Node {
idx,
parents: Vec::with_capacity(2),
children: Vec::with_capacity(4),
data
}
}
#[inline(always)]
pub fn parents(&self) -> impl DoubleEndedIterator<Item = (NodeIdx, &P)> + '_ {
self.parents.iter().map(|(pidx, pdata)| (*pidx, pdata))
}
#[inline(always)]
pub fn parent_idxs(&self) -> impl DoubleEndedIterator<Item = NodeIdx> + '_ {
self.parents.iter().map(|(pidx, _)| *pidx)
}
#[inline(always)]
pub fn parent_idx(&self) -> Result<NodeIdx> {
let parent_count = self.parents.len();
if parent_count == 1 {
Ok(self.parent_idxs().nth(0).unwrap())
} else {
return Err(Error::ExpectedSingleParent {
fidx: self.idx,
got: parent_count,
});
}
}
#[inline(always)]
pub fn parent_edges(
&self
) -> impl DoubleEndedIterator<Item = Edge<NodeIdx, &P>> + '_ {
self.parents.iter().map(|(pidx, pdata)| Edge {
src: self.idx,
dst: *pidx,
data: pdata
})
}
#[inline(always)]
pub fn parent_edges_mut(
&mut self
) -> impl DoubleEndedIterator<Item = Edge<NodeIdx, &mut P>> + '_ {
self.parents.iter_mut().map(|(pidx, pdata)| Edge {
src: self.idx,
dst: *pidx,
data: pdata
})
}
#[inline(always)]
pub fn count_parents(&self) -> usize {
self.parents.len()
}
#[inline(always)]
pub fn has_parents(&self) -> bool {
self.count_parents() != 0
}
#[inline(always)]
pub fn add_parent(&mut self, pidx: NodeIdx, pdata: P) {
self.parents.push((pidx, pdata));
}
#[inline]
pub fn insert_parent(&mut self, pidx: NodeIdx, pdata: P, pos: usize) {
self.parents.insert(pos, (pidx, pdata));
}
#[inline]
#[must_use]
#[rustfmt::skip]
pub fn remove_parent(&mut self, parent_idx: NodeIdx) -> Result<P> {
let ordinal = self.get_parent_ordinal(parent_idx)
.ok_or_else(|| Error::ParentNotFound {
node_idx: self.idx,
parent_idx: Some(parent_idx),
})?;
let (_, pdata) = self.parents.remove(ordinal);
Ok(pdata)
}
#[inline(always)]
pub fn children(&self) -> impl DoubleEndedIterator<Item = (NodeIdx, &C)> + '_ {
self.children.iter().map(|(idx, data)| (*idx, data))
}
#[inline(always)]
pub fn child_idxs(&self) -> impl DoubleEndedIterator<Item = NodeIdx> + '_ {
self.children.iter().map(|(idx, _)| *idx)
}
#[inline]
pub fn first_child_idx(&self) -> Option<NodeIdx> {
let child_count = self.children.len();
if child_count == 0 {
None
} else {
unsafe { Some(self.children.get_unchecked(0).0) }
}
}
#[inline]
pub fn last_child_idx(&self) -> Option<NodeIdx> {
let child_count = self.children.len();
if child_count == 0 {
None
} else {
self.nth_child_idx(child_count - 1)
}
}
#[inline]
pub fn nth_child_idx(&self, n: usize) -> Option<NodeIdx> {
let child_count = self.children.len();
if n < child_count {
unsafe { Some(self.children.get_unchecked(n).0) }
} else {
None
}
}
#[inline(always)]
pub fn child_edges(
&self
) -> impl DoubleEndedIterator<Item = Edge<NodeIdx, &C>> + '_ {
self.children.iter().map(|(cidx, cdata)| Edge {
src: self.idx,
dst: *cidx,
data: cdata
})
}
#[inline(always)]
pub fn count_children(&self) -> usize {
self.children.len()
}
#[inline(always)]
pub fn has_children(&self) -> bool {
self.count_children() != 0
}
#[inline(always)]
pub fn add_child(&mut self, cidx: NodeIdx, cdata: C) {
self.children.push((cidx, cdata));
}
#[inline]
pub fn insert_child(&mut self, cidx: NodeIdx, cdata: C, pos: usize) {
self.children.insert(pos, (cidx, cdata));
}
#[inline]
#[must_use]
#[rustfmt::skip]
pub fn remove_child(&mut self, child_idx: NodeIdx) -> Result<C> {
let ordinal = self.get_child_ordinal(child_idx)
.ok_or_else(|| Error::ChildNotFound {
node_idx: self.idx,
child_idx
})?;
let (_, cdata) = self.children.remove(ordinal);
Ok(cdata)
}
#[inline]
#[rustfmt::skip]
pub fn get_parent_ordinal(&self, parent_idx: NodeIdx) -> Option<usize> {
self.parent_idxs().position(|pidx| pidx == parent_idx)
}
#[inline]
#[rustfmt::skip]
pub fn get_child_ordinal(&self, child_idx: NodeIdx) -> Option<usize> {
self.child_idxs().position(|cidx| cidx == child_idx)
}
#[inline]
pub fn is_root_node(&self) -> bool {
self.parents.is_empty()
}
#[inline]
pub fn is_branch_node(&self) -> bool {
!self.is_leaf_node()
}
#[inline]
pub fn is_leaf_node(&self) -> bool {
self.children.is_empty()
}
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(derive_more::Deref, derive_more::From)]
pub struct NodeIdx(pub(crate) usize);
impl std::fmt::Debug for NodeIdx {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "NodeIdx({})", self.0)
}
}
impl std::fmt::Display for NodeIdx {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(derive_more::Deref, derive_more::From)]
pub struct NodeCount(usize);
impl NodeCount {
pub const ZERO: Self = Self(0);
}
impl std::ops::Add<Self> for NodeCount {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 + rhs.0)
}
}
impl std::ops::Sub<Self> for NodeCount {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self(self.0 - rhs.0)
}
}