ego_binary_tree/
macros.rs

1/// Creates a binary tree from expressions.
2///
3/// # Examples
4///
5/// ```
6/// #[macro_use] extern crate ego_binary_tree;
7/// # fn main() {
8/// let tree = binary_tree!("root");
9/// # }
10/// ```
11///
12/// ```
13/// #[macro_use] extern crate ego_binary_tree;
14/// # fn main() {
15/// let tree = binary_tree! {
16///     "root" => {
17///         left: "child a",
18///         right: "child b" => {
19///             right: "grandchild a",
20///         },
21///     }
22/// };
23/// # }
24/// ```
25#[macro_export]
26macro_rules! binary_tree {
27    (@ $n:ident { }) => { };
28
29    // Node with only right node with children.
30    (@ $n:ident { right: $value:expr => $children:tt$(,)* }) => {
31        {
32            let mut node = $n.set_right($value);
33            binary_tree!(@ node $children)
34        }
35    };
36
37    // Node with only left node with children.
38    (@ $n:ident { left: $value:expr => $children:tt$(,)* }) => {
39        {
40            let mut node = $n.set_left($value);
41            binary_tree!(@ node $children)
42        }
43    };
44
45    // Node with only left leaf node.
46    (@ $n:ident { left: $value:expr$(,)* }) => {
47        { $n.set_left($value); }
48    };
49
50    // Node with only right leaf node.
51    (@ $n:ident { right: $value:expr$(,)* }) => {
52        { $n.set_right($value); }
53    };
54
55    // Node with left leaf and right with children.
56    (@ $n:ident { left: $left_value:expr, right: $right_value:expr => $right_children:tt$(,)* }) => {
57        {
58            $n.set_left($left_value);
59            let mut right_node = $n.set_right($right_value);
60            binary_tree!(@ right_node $right_children);
61        }
62    };
63
64    // Node with left and right leaf.
65    (@ $n:ident { left: $left_value:expr, right: $right_value:expr$(,)* }) => {
66        {
67            $n.set_left($left_value);
68            $n.set_right($right_value);
69        }
70    };
71
72    // Node with left with children and right leaf.
73    (@ $n:ident { left: $left_value:expr => $left_children:tt, right: $right_value:expr$(,)* }) => {
74        {
75            let mut left_node = $n.set_left($left_value);
76            binary_tree!(@ left_node $left_children);
77            $n.set_right($right_value);
78        }
79    };
80
81    // Node with both left and right nodes.
82    (@ $n:ident { left: $left_value:expr => $left_children:tt, right: $right_value:expr => $right_children:tt$(,)* }) => {
83        {
84            let mut left_node = $n.set_left($left_value);
85            binary_tree!(@ left_node $left_children);
86            let mut right_node = $n.set_right($right_value);
87            binary_tree!(@ right_node $right_children);
88        }
89    };
90
91    ($root:expr) => { $crate::BinaryTree::new($root) };
92
93    ($root:expr => $children:tt) => {
94        {
95            let mut tree = $crate::BinaryTree::new($root);
96            {
97                let mut node = tree.root_mut();
98                binary_tree!(@ node $children);
99            }
100            tree
101        }
102    };
103}
104
105#[cfg(test)]
106mod tests {
107    #[test]
108    fn macro_root_works() {
109        let tree = binary_tree!('a');
110        assert_eq!(tree.root().value(), &'a');
111    }
112
113    #[test]
114    fn complicated_tree_works() {
115        let tree = binary_tree! {
116            "root" => {
117                left: "left",
118                right: "right" => {
119                    right: "rightright" => {
120                        left: "rightrightleft"
121                    },
122                },
123            }
124        };
125        assert_eq!(tree.root().value(), &"root");
126
127        let left = tree.root().left().unwrap();
128        assert_eq!(left.value(), &"left");
129        assert!(left.left().is_none());
130        assert!(left.right().is_none());
131
132        let right = tree.root().right().unwrap();
133        assert_eq!(right.value(), &"right");
134        assert!(right.left().is_none());
135
136        let rightright = right.right().unwrap();
137        assert_eq!(rightright.value(), &"rightright");
138
139        let rightrightleft = rightright.left().unwrap();
140        assert_eq!(rightrightleft.value(), &"rightrightleft");
141    }
142}