1// Copyright 2018 Google LLC
2//
3// Use of this source code is governed by an MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT.
6
7//! A Vec-based container for a tree structure.
8
9use std::num::NonZeroUsize;
10use std::ops::{Add, Sub};
11
12use crate::parse::{Item, ItemBody};
13
14#[derive(Debug, Eq, PartialEq, Copy, Clone, PartialOrd)]
15pub(crate) struct TreeIndex(NonZeroUsize);
16
17impl TreeIndex {
18 fn new(i: usize) -> Self {
19 TreeIndex(NonZeroUsize::new(i).unwrap())
20 }
21
22 pub fn get(self) -> usize {
23 self.0.get()
24 }
25}
26
27impl Add<usize> for TreeIndex {
28 type Output = TreeIndex;
29
30 fn add(self, rhs: usize) -> Self {
31 let inner: usize = self.0.get() + rhs;
32 TreeIndex::new(inner)
33 }
34}
35
36impl Sub<usize> for TreeIndex {
37 type Output = TreeIndex;
38
39 fn sub(self, rhs: usize) -> Self {
40 let inner: usize = self.0.get().checked_sub(rhs).unwrap();
41 TreeIndex::new(inner)
42 }
43}
44
45#[derive(Debug, Clone, Copy)]
46pub(crate) struct Node<T> {
47 pub child: Option<TreeIndex>,
48 pub next: Option<TreeIndex>,
49 pub item: T,
50}
51
52/// A tree abstraction, intended for fast building as a preorder traversal.
53#[derive(Clone)]
54pub(crate) struct Tree<T> {
55 nodes: Vec<Node<T>>,
56 spine: Vec<TreeIndex>, // indices of nodes on path to current node
57 cur: Option<TreeIndex>,
58}
59
60impl<T: Default> Tree<T> {
61 // Indices start at one, so we place a dummy value at index zero.
62 // The alternative would be subtracting one from every TreeIndex
63 // every time we convert it to usize to index our nodes.
64 pub(crate) fn with_capacity(cap: usize) -> Tree<T> {
65 let mut nodes = Vec::with_capacity(cap);
66 nodes.push(Node {
67 child: None,
68 next: None,
69 item: <T as Default>::default(),
70 });
71 Tree {
72 nodes,
73 spine: Vec::new(),
74 cur: None,
75 }
76 }
77
78 /// Returns the index of the element currently in focus.
79 pub(crate) fn cur(&self) -> Option<TreeIndex> {
80 self.cur
81 }
82
83 /// Append one item to the current position in the tree.
84 pub(crate) fn append(&mut self, item: T) -> TreeIndex {
85 let ix = self.create_node(item);
86 let this = Some(ix);
87
88 if let Some(ix) = self.cur {
89 self[ix].next = this;
90 } else if let Some(&parent) = self.spine.last() {
91 self[parent].child = this;
92 }
93 self.cur = this;
94 ix
95 }
96
97 /// Create an isolated node.
98 pub(crate) fn create_node(&mut self, item: T) -> TreeIndex {
99 let this = self.nodes.len();
100 self.nodes.push(Node {
101 child: None,
102 next: None,
103 item,
104 });
105 TreeIndex::new(this)
106 }
107
108 /// Push down one level, so that new items become children of the current node.
109 /// The new focus index is returned.
110 pub(crate) fn push(&mut self) -> TreeIndex {
111 let cur_ix = self.cur.unwrap();
112 self.spine.push(cur_ix);
113 self.cur = self[cur_ix].child;
114 cur_ix
115 }
116
117 /// Pop back up a level.
118 pub(crate) fn pop(&mut self) -> Option<TreeIndex> {
119 let ix = Some(self.spine.pop()?);
120 self.cur = ix;
121 ix
122 }
123
124 /// Look at the parent node.
125 pub(crate) fn peek_up(&self) -> Option<TreeIndex> {
126 self.spine.last().copied()
127 }
128
129 /// Look at grandparent node.
130 pub(crate) fn peek_grandparent(&self) -> Option<TreeIndex> {
131 if self.spine.len() >= 2 {
132 Some(self.spine[self.spine.len() - 2])
133 } else {
134 None
135 }
136 }
137
138 /// Returns true when there are no nodes other than the root node
139 /// in the tree, false otherwise.
140 pub(crate) fn is_empty(&self) -> bool {
141 self.nodes.len() <= 1
142 }
143
144 /// Returns the length of the spine.
145 pub(crate) fn spine_len(&self) -> usize {
146 self.spine.len()
147 }
148
149 /// Resets the focus to the first node added to the tree, if it exists.
150 pub(crate) fn reset(&mut self) {
151 self.cur = if self.is_empty() {
152 None
153 } else {
154 Some(TreeIndex::new(1))
155 };
156 self.spine.clear();
157 }
158
159 /// Walks the spine from a root node up to, but not including, the current node.
160 pub(crate) fn walk_spine(&self) -> impl std::iter::DoubleEndedIterator<Item = &TreeIndex> {
161 self.spine.iter()
162 }
163
164 /// Moves focus to the next sibling of the given node.
165 pub(crate) fn next_sibling(&mut self, cur_ix: TreeIndex) -> Option<TreeIndex> {
166 self.cur = self[cur_ix].next;
167 self.cur
168 }
169}
170
171impl Tree<Item> {
172 /// Truncates the preceding siblings to the given end position,
173 /// and returns the new current node.
174 pub(crate) fn truncate_siblings(&mut self, bytes: &[u8], end_byte_ix: usize) {
175 let parent_ix = self.peek_up().unwrap();
176 let mut next_child_ix = self[parent_ix].child;
177 let mut prev_child_ix = None;
178
179 // drop or truncate children based on its range
180 while let Some(child_ix) = next_child_ix {
181 let child_end = self[child_ix].item.end;
182 if child_end < end_byte_ix {
183 // preserve this node, and go to the next
184 prev_child_ix = Some(child_ix);
185 next_child_ix = self[child_ix].next;
186 continue;
187 } else if child_end == end_byte_ix {
188 // this will be the last node
189 self[child_ix].next = None;
190 // focus to the new last child (this node)
191 self.cur = Some(child_ix);
192 } else if self[child_ix].item.start == end_byte_ix {
193 // check whether the previous character is a backslash
194 let is_previous_char_backslash_escape =
195 end_byte_ix.checked_sub(1).map_or(false, |prev| {
196 (bytes[prev] == b'\\') && (self[child_ix].item.body == ItemBody::Text)
197 });
198 if is_previous_char_backslash_escape {
199 // rescue the backslash as a plain text content
200 let last_byte_ix = end_byte_ix - 1;
201 self[child_ix].item.start = last_byte_ix;
202 self[child_ix].item.end = end_byte_ix;
203 self.cur = Some(child_ix);
204 } else if let Some(prev_child_ix) = prev_child_ix {
205 // the node will become empty. drop the node
206 // a preceding sibling exists
207 self[prev_child_ix].next = None;
208 self.cur = Some(prev_child_ix);
209 } else {
210 // no preceding siblings. remove the node from the parent
211 self[parent_ix].child = None;
212 self.cur = None;
213 }
214 } else {
215 debug_assert!(self[child_ix].item.start < end_byte_ix);
216 debug_assert!(end_byte_ix < child_end);
217 // truncate the node
218 self[child_ix].item.end = end_byte_ix;
219 self[child_ix].next = None;
220 // focus to the new last child
221 self.cur = Some(child_ix);
222 }
223 break;
224 }
225 }
226}
227
228impl<T> std::fmt::Debug for Tree<T>
229where
230 T: std::fmt::Debug,
231{
232 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
233 fn debug_tree<T>(
234 tree: &Tree<T>,
235 cur: TreeIndex,
236 indent: usize,
237 f: &mut std::fmt::Formatter,
238 ) -> std::fmt::Result
239 where
240 T: std::fmt::Debug,
241 {
242 for _ in 0..indent {
243 write!(f, " ")?;
244 }
245 writeln!(f, "{:?}", &tree[cur].item)?;
246 if let Some(child_ix) = tree[cur].child {
247 debug_tree(tree, child_ix, indent + 1, f)?;
248 }
249 if let Some(next_ix) = tree[cur].next {
250 debug_tree(tree, next_ix, indent, f)?;
251 }
252 Ok(())
253 }
254
255 if self.nodes.len() > 1 {
256 let cur = TreeIndex(NonZeroUsize::new(1).unwrap());
257 debug_tree(self, cur, 0, f)
258 } else {
259 write!(f, "Empty tree")
260 }
261 }
262}
263
264impl<T> std::ops::Index<TreeIndex> for Tree<T> {
265 type Output = Node<T>;
266
267 fn index(&self, ix: TreeIndex) -> &Self::Output {
268 self.nodes.index(ix.get())
269 }
270}
271
272impl<T> std::ops::IndexMut<TreeIndex> for Tree<T> {
273 fn index_mut(&mut self, ix: TreeIndex) -> &mut Node<T> {
274 self.nodes.index_mut(index:ix.get())
275 }
276}
277