use serde::{Deserialize, Serialize};
use crate::topology::node_id::NodeId;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum NodeKind {
Container,
Leaf,
}
impl NodeKind {
pub fn is_leaf(&self) -> bool {
matches!(self, Self::Leaf)
}
pub fn is_container(&self) -> bool {
matches!(self, Self::Container)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Node {
pub id: NodeId,
pub label: String,
pub node_type: String,
pub node_kind: NodeKind,
pub children: Vec<Node>,
}
impl Node {
pub fn container(id: NodeId, label: String, node_type: &str) -> Self {
Self {
id,
label,
node_type: node_type.to_owned(),
node_kind: NodeKind::Container,
children: Vec::new(),
}
}
pub fn leaf(id: NodeId, label: String, node_type: &str) -> Self {
Self {
id,
label,
node_type: node_type.to_owned(),
node_kind: NodeKind::Leaf,
children: Vec::new(),
}
}
pub fn root(id: NodeId, label: String, node_type: &str) -> Self {
Self::container(id, label, node_type)
}
#[must_use]
pub fn with_child(mut self, child: Node) -> Self {
self.children.push(child);
self
}
#[must_use]
pub fn with_children(mut self, children: Vec<Node>) -> Self {
self.children.extend(children);
self
}
pub fn count(&self) -> usize {
1 + self.children.iter().map(Node::count).sum::<usize>()
}
pub fn leaf_nodes(&self) -> Vec<&Node> {
if self.node_kind.is_leaf() {
return vec![self];
}
self.children.iter().flat_map(Node::leaf_nodes).collect()
}
pub fn find(&self, id: &NodeId) -> Option<&Node> {
if &self.id == id {
return Some(self);
}
self.children.iter().find_map(|c| c.find(id))
}
pub fn to_view(&self) -> NodeView {
NodeView {
id: self.id.canonical(),
label: self.label.clone(),
node_type: self.node_type.clone(),
node_kind: match self.node_kind {
NodeKind::Container => "container".to_owned(),
NodeKind::Leaf => "leaf".to_owned(),
},
children: Vec::new(),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct NodeView {
pub id: String,
pub label: String,
pub node_type: String,
pub node_kind: String,
pub children: Vec<NodeView>,
}
impl NodeView {
pub fn is_leaf(&self) -> bool {
self.node_kind == "leaf"
}
pub fn is_container(&self) -> bool {
self.node_kind == "container"
}
}
impl From<Node> for NodeView {
fn from(node: Node) -> Self {
node.to_view()
}
}