pub mod simple_rnode;
use crate::node::simple_rnode::{
EdgeWeight, NodeTaxa, NodeWeight, RootedAnnotatedNode, RootedMetaNode, RootedTreeNode,
RootedWeightedNode, RootedZetaNode,
};
use std::fmt::{Debug, Display};
use std::sync::Arc;
pub type NodeID = usize;
const NO_PARENT: NodeID = NodeID::MAX;
#[cfg(feature = "serde")]
mod parent_as_option {
use super::{NodeID, NO_PARENT};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
pub(super) fn serialize<S: Serializer>(parent: &NodeID, ser: S) -> Result<S::Ok, S::Error> {
(*parent != NO_PARENT).then_some(*parent).serialize(ser)
}
pub(super) fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<NodeID, D::Error> {
Ok(Option::<NodeID>::deserialize(de)?.unwrap_or(NO_PARENT))
}
}
pub type PhyloNode = Node<String, f32, f32>;
pub type DemoNode = Node<u32, f32, f32>;
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Node<T, W, Z>
where
T: NodeTaxa,
W: EdgeWeight,
Z: NodeWeight,
{
id: NodeID,
#[cfg_attr(feature = "serde", serde(with = "parent_as_option"))]
parent: NodeID,
children: Vec<NodeID>,
taxa: Option<Arc<T>>,
weight: Option<W>,
zeta: Option<Z>,
annotation: Option<Arc<str>>,
}
impl<T, W, Z> RootedTreeNode for Node<T, W, Z>
where
T: NodeTaxa,
W: EdgeWeight,
Z: NodeWeight,
{
type NodeID = NodeID;
fn new(id: Self::NodeID) -> Self {
Node {
id,
parent: NO_PARENT,
children: vec![],
taxa: None,
weight: None,
zeta: None,
annotation: None,
}
}
fn get_id(&self) -> Self::NodeID {
self.id
}
fn set_id(&mut self, id: Self::NodeID) {
self.id = id
}
fn set_parent(&mut self, parent: Option<Self::NodeID>) {
self.parent = parent.unwrap_or(NO_PARENT);
}
fn get_parent(&self) -> Option<Self::NodeID> {
(self.parent != NO_PARENT).then_some(self.parent)
}
fn get_children(&self) -> &[Self::NodeID] {
&self.children
}
fn add_child(&mut self, child: Self::NodeID) {
if self.children.capacity() == 0 {
self.children.reserve_exact(2);
}
self.children.push(child);
}
fn remove_child(&mut self, child: &Self::NodeID) {
self.children.retain(|x| x != child);
}
}
impl<T, W, Z> Node<T, W, Z>
where
T: NodeTaxa,
W: EdgeWeight,
Z: NodeWeight,
{
pub fn heap_size(&self) -> usize {
self.children.capacity() * std::mem::size_of::<NodeID>()
}
#[cfg(feature = "simple_rooted_tree")]
pub(crate) fn get_taxa_arc(&self) -> Option<&Arc<T>> {
self.taxa.as_ref()
}
#[cfg(feature = "simple_rooted_tree")]
pub(crate) fn set_taxa_arc(&mut self, taxa: Option<Arc<T>>) {
self.taxa = taxa;
}
}
impl<T, W, Z> RootedMetaNode for Node<T, W, Z>
where
T: NodeTaxa,
W: EdgeWeight,
Z: NodeWeight,
{
type Meta = T;
fn get_taxa(&self) -> Option<&Self::Meta> {
self.taxa.as_deref()
}
fn set_taxa(&mut self, taxa: Option<Self::Meta>) {
self.taxa = taxa.map(Arc::new);
}
}
impl<T, W, Z> RootedWeightedNode for Node<T, W, Z>
where
T: NodeTaxa,
W: EdgeWeight,
Z: NodeWeight,
{
type Weight = W;
fn get_weight(&self) -> Option<Self::Weight> {
self.weight
}
fn set_weight(&mut self, w: Option<Self::Weight>) {
self.weight = w;
}
}
impl<T, W, Z> RootedZetaNode for Node<T, W, Z>
where
T: NodeTaxa,
W: EdgeWeight,
Z: NodeWeight,
{
type Zeta = Z;
fn get_zeta(&self) -> Option<Self::Zeta> {
self.zeta
}
fn set_zeta(&mut self, w: Option<Self::Zeta>) {
self.zeta = w;
}
}
impl<T, W, Z> RootedAnnotatedNode for Node<T, W, Z>
where
T: NodeTaxa,
W: EdgeWeight,
Z: NodeWeight,
{
fn get_annotation(&self) -> Option<&str> {
self.annotation.as_deref()
}
fn set_annotation(&mut self, annotation: Option<Arc<str>>) {
self.annotation = annotation;
}
}
impl<T, W, Z> Debug for Node<T, W, Z>
where
T: NodeTaxa,
W: EdgeWeight,
Z: NodeWeight,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}:{}:{}:{}:{}",
self.get_id(),
self.node_type(),
match self.get_taxa() {
None => "No Taxa".to_string(),
Some(t) => t.to_string(),
},
match self.get_weight() {
None => "Unweighted".to_string(),
Some(t) => t.to_string(),
},
match self.get_zeta() {
None => "No Zeta".to_string(),
Some(z) => z.to_string(),
}
)
}
}
impl<T, W, Z> Display for Node<T, W, Z>
where
T: NodeTaxa,
W: EdgeWeight,
Z: NodeWeight,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}:{}:{}:{}:{}",
self.get_id(),
self.node_type(),
match self.get_taxa() {
None => "None".to_string(),
Some(t) => t.to_string(),
},
match self.get_weight() {
None => "".to_string(),
Some(t) => t.to_string(),
},
match self.get_zeta() {
None => "No Zeta".to_string(),
Some(z) => z.to_string(),
}
)
}
}