use super::{Node, PropPayload, PropValue, StatefulTree, Tree, TuiTreeItem};
use std::collections::LinkedList;
impl Node {
pub(crate) fn from_prop_payload(
&mut self,
list: &mut LinkedList<PropPayload>,
) -> Option<Box<PropPayload>> {
match list.pop_front() {
Some(PropPayload::Tup3((
PropValue::Str(id),
PropValue::Str(label),
PropValue::Str(parent),
))) => {
let parent: &mut Node = self
.query_mut(parent.as_str())
.expect("Parent node doesn't exist");
parent.children.push(Node::new(id, label));
self.from_prop_payload(list)
}
None => None,
_ => panic!("Invalid payload"),
}
}
pub(crate) fn to_prop_payload(&self, depth: usize, parent: &str) -> PropPayload {
PropPayload::Linked(Self::to_payload_list(self, depth, parent))
}
fn to_payload_list(&self, depth: usize, parent: &str) -> LinkedList<PropPayload> {
let this: PropPayload = Self::to_prop_value(self, parent);
let mut items: LinkedList<PropPayload> = LinkedList::new();
items.push_back(this);
if depth > 0 {
self.children
.iter()
.for_each(|x| items.extend(Self::to_payload_list(x, depth - 1, self.id.as_str())));
}
items
}
fn to_prop_value(&self, parent: &str) -> PropPayload {
PropPayload::Tup3((
PropValue::Str(self.id.to_string()),
PropValue::Str(self.label.to_string()),
PropValue::Str(parent.to_string()),
))
}
}
impl<'a> Node {
fn to_tui_tree_item(&self) -> TuiTreeItem<'a> {
match self.children.is_empty() {
true => TuiTreeItem::new_leaf(self.label.clone()),
false => {
let children: Vec<TuiTreeItem> =
self.children.iter().map(|x| x.to_tui_tree_item()).collect();
TuiTreeItem::new(self.label.clone(), children)
}
}
}
}
impl From<&PropPayload> for Tree {
fn from(props: &PropPayload) -> Self {
let list: &LinkedList<PropPayload> = match props {
PropPayload::Linked(list) => list,
_ => panic!("Invalid payload"),
};
let mut list = list.clone();
let mut root: Node = match list.pop_front() {
Some(PropPayload::Tup3((PropValue::Str(id), PropValue::Str(label), _))) => {
Node::new(id, label)
}
_ => panic!("Invalid root"),
};
root.from_prop_payload(&mut list);
Tree::new(root)
}
}
impl<'a> From<&Tree> for StatefulTree<'a> {
fn from(tree: &Tree) -> Self {
let root: &Node = tree.root();
let children: Vec<TuiTreeItem> =
root.children.iter().map(|x| x.to_tui_tree_item()).collect();
StatefulTree::new().with_items(vec![TuiTreeItem::new(root.id.clone(), children)])
}
}
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_serializer_to_and_from_prop_value() {
let tree: Tree = Tree::new(
Node::new("/", "/")
.with_child(
Node::new("/bin", "bin/")
.with_child(Node::new("/bin/ls", "ls"))
.with_child(Node::new("/bin/pwd", "pwd")),
)
.with_child(
Node::new("/home", "home/").with_child(
Node::new("/home/omar", "omar/")
.with_child(Node::new("/home/omar/readme.md", "readme.md"))
.with_child(Node::new("/home/omar/changelog.md", "changelog.md")),
),
),
);
let props: PropPayload = tree.root().to_prop_payload(usize::MAX, "");
let tree: Tree = Tree::from(&props);
let root: &Node = tree.root();
assert_eq!(root.count(), 8);
assert_eq!(root.id.as_str(), "/");
assert_eq!(root.label.as_str(), "/");
assert_eq!(root.children.len(), 2);
let bin: &Node = &root.children[0];
assert_eq!(bin.id.as_str(), "/bin");
assert_eq!(bin.label.as_str(), "bin/");
assert_eq!(bin.children.len(), 2);
let bin_ids: Vec<&str> = bin.children.iter().map(|x| x.id.as_str()).collect();
assert_eq!(bin_ids, vec!["/bin/ls", "/bin/pwd"]);
let home: &Node = &tree.root.children[1];
assert_eq!(home.id.as_str(), "/home");
assert_eq!(home.label.as_str(), "home/");
assert_eq!(home.children.len(), 1);
let omar_home: &Node = &home.children[0];
let omar_home_ids: Vec<&str> = omar_home.children.iter().map(|x| x.id.as_str()).collect();
assert_eq!(
omar_home_ids,
vec!["/home/omar/readme.md", "/home/omar/changelog.md"]
);
assert_eq!(
tree.query("/home/omar/changelog.md").unwrap().id.as_str(),
"/home/omar/changelog.md"
);
}
#[test]
#[should_panic]
fn test_serializer_bad_props_payload() {
Tree::from(&PropPayload::None);
}
#[test]
#[should_panic]
fn test_serializer_bad_props_payload_2() {
let mut root: Node = Node::new("/", "/");
let mut list: LinkedList<PropPayload> = LinkedList::new();
list.push_back(PropPayload::One(PropValue::Bool(true)));
root.from_prop_payload(&mut list);
}
#[test]
#[should_panic]
fn test_serializer_bad_props_value() {
let mut linked_list: LinkedList<PropPayload> = LinkedList::new();
linked_list.push_back(PropPayload::One(PropValue::Str("pippo".to_string())));
Tree::from(&PropPayload::Linked(linked_list));
}
#[test]
fn test_serializer_tree_to_stateful_tree() {
let tree: Tree = Tree::new(
Node::new("/", "/")
.with_child(
Node::new("/bin", "bin/")
.with_child(Node::new("/bin/ls", "ls"))
.with_child(Node::new("/bin/pwd", "pwd")),
)
.with_child(
Node::new("/home", "home/").with_child(
Node::new("/home/omar", "omar/")
.with_child(Node::new("/home/omar/readme.md", "readme.md"))
.with_child(Node::new("/home/omar/changelog.md", "changelog.md")),
),
),
);
StatefulTree::from(&tree);
}
}