Crate orange_trees[][src]

Expand description

orange-trees

orange-trees is a Rust implementation of the Tree data structure

Get Started

Add orange-trees to your dependencies

orange-trees = "0.1.0"

Initialize a tree

Orange-trees provides three ways to initialize trees:

  1. using the node! macro
  2. Using the with_child constructor nested structure
  3. Using with_children
use orange_trees::{Tree, Node};

// Create a tree using macro
let tree: Tree<&'static str, &'static str> = Tree::new(
  node!("/", "/"
    , node!("/bin", "bin/"
      , node!("/bin/ls", "ls")
      , node!("/bin/pwd", "pwd")
    )
    , node!("/tmp", "tmp/"
      , node!("/tmp/dump.txt", "dump.txt")
      , node!("/tmp/omar.txt", "omar.txt")
    )
  )
);

// Create a tree using constructor
let tree: Tree<&'static str, &'static str> = 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("/tmp", "tmp/")
        .with_child(Node::new("/tmp/dump.txt", "dump.txt"))
        .with_child(Node::new("/tmp/omar.txt", "omar.txt"))
        .with_child(
          Node::new("/tmp/.cache", "cache/")
            .with_child(Node::new("/tmp/.cache/xyz.cache", "xyz.cache"))
        )
    ),
);

// With-children

let tree: Tree<String, &str> =
    Tree::new(Node::new("a".to_string(), "a").with_children(vec![
        Node::new("a1".to_string(), "a1"),
        Node::new("a2".to_string(), "a2"),
    ]));
Run

Query a tree

There are many functions to query nodes’ attributes, such as their value, their depth and their children. In addition to these, there are also functions to search nodes by predicate or by id.

use orange_trees::{Node, Tree};

let tree: Tree<&'static str, &'static str> = 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("/tmp", "tmp/")
        .with_child(Node::new("/tmp/dump.txt", "dump.txt"))
        .with_child(Node::new("/tmp/omar.txt", "omar.txt"))
        .with_child(
          Node::new("/tmp/.cache", "cache/")
            .with_child(Node::new("/tmp/.cache/xyz.cache", "xyz.cache"))
        )
    ),
);
// Query tree
let bin: &Node<&'static str, &'static str> = tree.root().query(&"/bin").unwrap();
assert_eq!(bin.id(), &"/bin");
assert_eq!(bin.value(), &"bin/");
assert_eq!(bin.children().len(), 2);
// Find all txt files
let txt_files: Vec<&Node<&'static str, &'static str>> = tree.root().find(&|x| x.value().ends_with(".txt") && x.is_leaf());
assert_eq!(txt_files.len(), 2);
// Count items
assert_eq!(tree.root().query(&"/bin").unwrap().count(), 3);
// Depth (max depth of the tree)
assert_eq!(tree.root().depth(), 4);
Run

Manipulate trees

Orange-trees provides a rich set of methods to manipulate nodes, which basically consists in:

  • Adding and removing children
  • Sorting node children
  • Truncating a node by depth
use orange_trees::{Node, Tree};

let mut tree: Tree<&'static str, &'static str> = 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("/tmp", "tmp/")
        .with_child(Node::new("/tmp/dump.txt", "dump.txt"))
        .with_child(Node::new("/tmp/omar.txt", "omar.txt"))
        .with_child(
          Node::new("/tmp/.cache", "cache/")
            .with_child(Node::new("/tmp/.cache/xyz.cache", "xyz.cache"))
        )
    ),
);

// Remove child
tree.root_mut().query_mut(&"/tmp").unwrap().remove_child(&"/tmp/.cache");
assert!(tree.root().query(&"/tmp/.cache").is_none());
// Add child
tree.root_mut().add_child(Node::new("/var", "var/"));
// Clear node
tree.root_mut().query_mut(&"/tmp").unwrap().clear();
assert_eq!(tree.root().query(&"/tmp").unwrap().count(), 1);
// Sort tree
let mut tree: Tree<&'static str, usize> = Tree::new(
    Node::new("/", 0)
        .with_child(Node::new("8", 8))
        .with_child(Node::new("7", 7))
        .with_child(Node::new("3", 3))
        .with_child(Node::new("1", 1))
        .with_child(Node::new("2", 2))
        .with_child(Node::new("9", 9))
        .with_child(Node::new("5", 5))
        .with_child(Node::new("4", 4))
        .with_child(Node::new("6", 6)),
);
tree.root_mut()
    .sort(|a, b| a.value().partial_cmp(b.value()).unwrap());
let values: Vec<usize> = tree.root().iter().map(|x| *x.value()).collect();
assert_eq!(values, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
Run

Working with routes

Whenever you want to track the state of the tree (such as tracking opened nodes or selected one), routes come handy to do so. Routes are basically the path, described by child index, to go from the parent node to the child node. You can get the route for a node and then the node associated to a route with two simple functions:

use orange_trees::{Node, Tree};

let tree: Tree<String, &str> = Tree::new(
    Node::new("/".to_string(), "/")
    .with_child(
        Node::new("/bin".to_string(), "bin/")
            .with_child(Node::new("/bin/ls".to_string(), "ls"))
            .with_child(Node::new("/bin/pwd".to_string(), "pwd")),
    )
    .with_child(
        Node::new("/home".to_string(), "home/").with_child(
            Node::new("/home/omar".to_string(), "omar/")
                .with_child(Node::new("/home/omar/readme.md".to_string(), "readme.md"))
                .with_child(Node::new(
                    "/home/omar/changelog.md".to_string(),
                    "changelog.md",
                )),
        ),
    ),
);
// -- node_by_route
assert_eq!(
    tree.root().node_by_route(&[1, 0, 1]).unwrap().id(),
    "/home/omar/changelog.md"
);
// -- Route by node
assert_eq!(
    tree.root()
        .route_by_node(&"/home/omar/changelog.md".to_string())
        .unwrap(),
    vec![1, 0, 1]
);
Run

Macros

node

Structs

Node

Node

Tree

Tree