use std::fmt::{Display, Formatter, Result as FmtResult};
#[derive(Clone, Debug)]
pub struct TreeNode {
pub identifier: usize,
pub label: Option<NameOrSupport>,
pub children: Option<[Box<TreeNode>; 2]>,
pub len: Option<f64>,
}
#[derive(Clone, Debug)]
pub enum NameOrSupport {
Name(String),
Support(usize),
}
impl Display for TreeNode {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{}", self.to_newick())
}
}
impl TreeNode {
pub fn leaf(identifier: usize, name: String, len: Option<f64>) -> Self {
Self {
identifier,
label: Some(NameOrSupport::Name(name)),
children: None,
len,
}
}
pub fn internal(
identifier: usize,
children: Option<[Box<TreeNode>; 2]>,
len: Option<f64>,
support: Option<usize>,
) -> Self {
Self {
identifier,
children: Some(children.unwrap()),
len,
label: match support {
Some(s) => Some(NameOrSupport::Support(s)),
None => None,
},
}
}
fn to_newick_recursion(&self) -> String {
match &self.children {
Some([left, right]) => {
let left_part = match left.len {
Some(len) => {
let left_str = left.to_newick_recursion();
format!("{}:{:.3}", left_str, len)
}
None => left.to_newick_recursion(),
};
let right_part = match right.len {
Some(len) => {
let right_str = right.to_newick_recursion();
format!("{}:{:.3}", right_str, len)
}
None => right.to_newick_recursion(),
};
let label_str = match self.label {
Some(NameOrSupport::Support(s)) => format!("{}", s),
Some(NameOrSupport::Name(ref n)) => n.clone(),
None => "".to_string(),
};
format!("({},{}){}", left_part, right_part, label_str)
}
None => match self.label {
Some(NameOrSupport::Support(s)) => format!("{}", s),
Some(NameOrSupport::Name(ref n)) => n.clone(),
None => "".to_string(),
},
}
}
pub fn to_newick(&self) -> String {
let mut newick = self.to_newick_recursion();
newick.push(';');
newick
}
}