ego_binary_tree/
macros.rs

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

    // Node with only right node with children.
    (@ $n:ident { right: $value:expr => $children:tt$(,)* }) => {
        {
            let mut node = $n.set_right($value);
            binary_tree!(@ node $children)
        }
    };

    // Node with only left node with children.
    (@ $n:ident { left: $value:expr => $children:tt$(,)* }) => {
        {
            let mut node = $n.set_left($value);
            binary_tree!(@ node $children)
        }
    };

    // Node with only left leaf node.
    (@ $n:ident { left: $value:expr$(,)* }) => {
        { $n.set_left($value); }
    };

    // Node with only right leaf node.
    (@ $n:ident { right: $value:expr$(,)* }) => {
        { $n.set_right($value); }
    };

    // Node with left leaf and right with children.
    (@ $n:ident { left: $left_value:expr, right: $right_value:expr => $right_children:tt$(,)* }) => {
        {
            $n.set_left($left_value);
            let mut right_node = $n.set_right($right_value);
            binary_tree!(@ right_node $right_children);
        }
    };

    // Node with left and right leaf.
    (@ $n:ident { left: $left_value:expr, right: $right_value:expr$(,)* }) => {
        {
            $n.set_left($left_value);
            $n.set_right($right_value);
        }
    };

    // Node with left with children and right leaf.
    (@ $n:ident { left: $left_value:expr => $left_children:tt, right: $right_value:expr$(,)* }) => {
        {
            let mut left_node = $n.set_left($left_value);
            binary_tree!(@ left_node $left_children);
            $n.set_right($right_value);
        }
    };

    // Node with both left and right nodes.
    (@ $n:ident { left: $left_value:expr => $left_children:tt, right: $right_value:expr => $right_children:tt$(,)* }) => {
        {
            let mut left_node = $n.set_left($left_value);
            binary_tree!(@ left_node $left_children);
            let mut right_node = $n.set_right($right_value);
            binary_tree!(@ right_node $right_children);
        }
    };

    ($root:expr) => { $crate::BinaryTree::new($root) };

    ($root:expr => $children:tt) => {
        {
            let mut tree = $crate::BinaryTree::new($root);
            {
                let mut node = tree.root_mut();
                binary_tree!(@ node $children);
            }
            tree
        }
    };
}

#[cfg(test)]
mod tests {
    #[test]
    fn macro_root_works() {
        let tree = binary_tree!('a');
        assert_eq!(tree.root().value(), &'a');
    }

    #[test]
    fn complicated_tree_works() {
        let tree = binary_tree! {
            "root" => {
                left: "left",
                right: "right" => {
                    right: "rightright" => {
                        left: "rightrightleft"
                    },
                },
            }
        };
        assert_eq!(tree.root().value(), &"root");

        let left = tree.root().left().unwrap();
        assert_eq!(left.value(), &"left");
        assert!(left.left().is_none());
        assert!(left.right().is_none());

        let right = tree.root().right().unwrap();
        assert_eq!(right.value(), &"right");
        assert!(right.left().is_none());

        let rightright = right.right().unwrap();
        assert_eq!(rightright.value(), &"rightright");

        let rightrightleft = rightright.left().unwrap();
        assert_eq!(rightrightleft.value(), &"rightrightleft");
    }
}