sise/serialize_tree.rs
1use alloc::vec::Vec;
2
3use crate::{Serializer, TreeNode};
4
5/// Serializes a tree of nodes into `serializer`.
6///
7/// # Example
8///
9/// ```
10/// use sise::sise_tree;
11///
12/// let tree = sise_tree!(["example", ["1", "2", "3"], ["a", "b", "c"]]);
13///
14/// let style = sise::SerializerStyle {
15/// line_break: "\n",
16/// indentation: " ",
17/// };
18///
19/// let mut result = String::new();
20/// let mut serializer = sise::Serializer::new(style, &mut result);
21///
22/// sise::serialize_tree(&mut serializer, &tree, usize::MAX);
23/// // Don't forget to finish the serializer
24/// serializer.finish(false);
25///
26/// let expected_result = "(example (1 2 3) (a b c))";
27/// assert_eq!(result, expected_result);
28/// ```
29///
30/// If you use multi-line style, atoms at the beginning of a list
31/// will be placed in the same line as the openning `(`:
32///
33/// ```
34/// use sise::sise_tree;
35///
36/// let tree = sise_tree!(["example", ["1", "2", "3"], ["a", "b", "c"]]);
37///
38/// let style = sise::SerializerStyle {
39/// line_break: "\n",
40/// indentation: " ",
41/// };
42///
43/// let mut result = String::new();
44/// let mut serializer = sise::Serializer::new(style, &mut result);
45///
46/// sise::serialize_tree(&mut serializer, &tree, 0);
47/// // Don't forget to finish the serializer
48/// serializer.finish(true);
49///
50/// let expected_result = "(example\n (1\n 2\n 3\n )\n (a\n b\n c\n )\n)\n";
51/// assert_eq!(result, expected_result);
52/// ```
53///
54/// It does not consume the serializer, so it can also be used to serialize
55/// a sub-tree:
56///
57/// ```
58/// use sise::sise_tree;
59///
60/// let tree = sise_tree!(["1", "2", "3"]);
61///
62/// let style = sise::SerializerStyle {
63/// line_break: "\n",
64/// indentation: " ",
65/// };
66///
67/// let mut result = String::new();
68/// let mut serializer = sise::Serializer::new(style, &mut result);
69///
70/// // Serialize the head
71/// serializer.begin_list(usize::MAX);
72/// serializer.put_atom("head", usize::MAX);
73///
74/// // Serialize the subtree
75/// sise::serialize_tree(&mut serializer, &tree, usize::MAX);
76///
77/// // Serialize the tail
78/// serializer.put_atom("tail", usize::MAX);
79/// serializer.end_list();
80/// serializer.finish(false);
81///
82/// let expected_result = "(head (1 2 3) tail)";
83/// assert_eq!(result, expected_result);
84/// ```
85pub fn serialize_tree(
86 serializer: &mut Serializer<'_, '_>,
87 root_node: &TreeNode,
88 break_line_at: usize,
89) {
90 enum State<'a> {
91 Beginning(&'a TreeNode),
92 Writing {
93 stack: Vec<core::slice::Iter<'a, TreeNode>>,
94 current_list: core::slice::Iter<'a, TreeNode>,
95 list_beginning: bool,
96 },
97 Finished,
98 }
99
100 let mut state = State::Beginning(root_node);
101
102 loop {
103 match state {
104 State::Beginning(node) => match node {
105 TreeNode::Atom(atom) => {
106 serializer.put_atom(atom, break_line_at);
107 state = State::Finished;
108 }
109 TreeNode::List(list) => {
110 serializer.begin_list(break_line_at);
111 state = State::Writing {
112 stack: Vec::new(),
113 current_list: list.iter(),
114 list_beginning: true,
115 };
116 }
117 },
118 State::Writing {
119 ref mut stack,
120 ref mut current_list,
121 ref mut list_beginning,
122 } => {
123 if let Some(node) = current_list.next() {
124 match node {
125 TreeNode::Atom(atom) => {
126 if *list_beginning {
127 serializer.put_atom(atom, usize::MAX);
128 } else {
129 serializer.put_atom(atom, break_line_at);
130 }
131 *list_beginning = false;
132 }
133 TreeNode::List(list) => {
134 serializer.begin_list(break_line_at);
135 stack.push(core::mem::replace(current_list, list.iter()));
136 *list_beginning = true;
137 }
138 }
139 } else {
140 serializer.end_list();
141 if let Some(parent_list) = stack.pop() {
142 *current_list = parent_list;
143 *list_beginning = false;
144 } else {
145 state = State::Finished;
146 }
147 }
148 }
149 State::Finished => return,
150 }
151 }
152}