1use replace_with::replace_with_or_abort;
2use std::{hash::Hash, mem};
3use tracing::{debug, error, trace, trace_span};
4
5use crate::path::Path;
6
7use super::{
8 diff::{DiffApplyError, DiffMap, DiffNode},
9 iter::depth::Traversal,
10 CombinationMode, DiffTree, NodeIDX, Tree,
11};
12
13pub type TreeBuilder<N, B> = Tree<Option<N>, B>;
15
16impl<N, B> Tree<N, B>
17where
18 N: Default,
19 B: Default + Eq + Hash + Clone,
20{
21 pub(super) fn extend(&mut self, path: &Path<B>, from_idx: Option<NodeIDX>) -> Vec<NodeIDX> {
23 match self.get_idx(path, from_idx) {
24 Ok(idx) => vec![idx],
25 Err(node) => {
26 let mut idxs = Vec::new();
27 let (mut node_idx, path_idx) = node.unwrap_or_else(|| {
28 self.insert_root(Default::default());
30 idxs.push(0);
31 (0, 0)
32 });
33 for branch in path.iter().skip(path_idx) {
34 node_idx = self
35 .insert_at(node_idx, branch.clone(), Default::default())
36 .1;
37 idxs.push(node_idx);
38 }
39 idxs
40 }
41 }
42 }
43 pub fn insert_extend(&mut self, path: &Path<B>, value: N) -> N {
45 let idx = *self.extend(path, None).last().unwrap();
46 mem::replace(&mut self.nodes[idx].value, value)
47 }
48
49 pub fn ix(&mut self, path: impl Into<Path<B>>, value: N) -> &mut Self {
53 let ph: Path<B> = path.into();
54 self.insert_extend(&ph, value);
55 self
56 }
57
58 pub fn force_apply_extend(&mut self, diff: DiffTree<N, B>) -> bool {
62 self.force_apply_with(
63 diff,
64 |entry, now| {
65 entry.insert_extend(now);
66 true
67 },
68 |entry| {
69 replace_with_or_abort(entry, |e| e.remove_subtree());
70 true
71 },
72 )
73 }
74}
75
76impl<N, B> Tree<N, B>
77where
78 N: Default + Eq,
79 B: Default + Eq + Hash + Clone,
80{
81 pub fn combine_extend(&mut self, tree: Tree<N, B>, mode: CombinationMode) -> bool {
82 self.combine_with(tree, mode, |entry, now| {
83 entry.insert_extend(now);
84 true
85 })
86 }
87 pub fn trim_default(&mut self) {
89 let mut removable = Vec::new();
90 let mut start = Path::new();
91 let mut path = Path::new();
92 for step in self.iter_on::<&N>() {
93 let old_path = path.clone();
95 path.apply_deref(&step);
96 if start.len() >= path.len() {
97 removable.push(start);
99 start = Path::new();
100 }
101 if **step.data() == N::default() {
102 if start.is_empty() {
104 start = path.clone();
106 }
107 } else {
108 if !start.is_empty() {
110 removable.push(old_path.path_to(path.len()));
112 }
113 }
114 }
115
116 for ph in removable {
118 self.remove_subtree(&ph)
119 .unwrap_or_else(|_| unreachable!("Could not trim a trimmable subtree"));
120 }
121 }
122}
123
124impl<N, B> Tree<N, B>
125where
126 N: Default + Eq,
127 B: Default + Eq + Hash + Clone,
128{
129 pub fn apply_extend(&mut self, diff: DiffTree<N, B>) -> Result<bool, DiffApplyError<B>> {
130 diff.is_applicable_extend(self)?;
132
133 Ok(self.force_apply_extend(diff))
135 }
136
137 pub fn apply_diff_extend(
138 &mut self,
139 path: Path<B>,
140 diff: DiffNode<N>,
141 ) -> Result<(), DiffApplyError<B>> {
142 self.apply_diff_with(path, diff, |entry, v| {
143 entry.insert_extend(v);
144 Ok(())
145 })
146 }
147
148 pub fn apply_map_extend(&mut self, map: DiffMap<N, B>) -> bool {
149 map.into_iter().fold(true, |mut res, (ph, diff)| {
150 if self.apply_diff_extend(ph, diff).is_err() {
151 res = false;
152 }
153 res
154 })
155 }
156
157 pub fn remove_subtree_trim(&mut self, path: &Path<B>) -> Result<(), Option<Path<B>>> {
159 let mut path = path.clone();
160 self.remove_subtree(&path)?;
162
163 if let Some(branch) = path.pop_last() {
165 let mut parents = self
167 .get_path_idxs(&path)
168 .map_err(|r| path.path_to(*r.unwrap_or((vec![0], 0)).0.last().unwrap_or(&0)))?;
169
170 while let Some(idx) = parents.pop() {
172 if self.nodes[idx].value == Default::default()
173 && parents.last().map(|&i| self.nodes[i].children.len()) == Some(1)
174 {
175 self.remove_subtree_at(*parents.last().unwrap(), path.pop_last().unwrap());
176 } else {
177 break;
178 }
179 }
180
181 if !parents.is_empty() {
183 self.nodes[*parents.last().unwrap()]
184 .children
185 .remove(&branch);
186 }
187 }
188 Ok(())
189 }
190}
191
192impl<N, B> TreeBuilder<N, B>
193where
194 N: Default,
195 B: Default + Eq + Hash + Clone,
196{
197 pub fn is_buildable(&self) -> bool {
198 let mut iter = self.iter_on::<&Option<N>>();
200
201 if let Some(Traversal::Start(Some(_))) = iter.next() {
202 } else {
204 return false;
205 };
206 iter.try_fold(Path::new(), |mut ph, node| {
207 (ph.apply_deref(&node) && node.take().is_some()).then_some(ph)
209 })
210 .is_some()
211 }
212
213 pub fn build(self) -> Tree<N, B> {
214 self.into_iter()
216 .try_fold((Tree::new(), Path::new()), |(mut tree, mut ph), node| {
217 match node {
218 Traversal::Start(data) => {
219 tree.insert_root(data.unwrap());
220 }
221 Traversal::Step { up, branch, data } => {
222 let value = data.unwrap();
223 let parent_idx = ph.last().map(|(_, idx)| *idx).unwrap_or(0);
224
225 (0..up).for_each(|_| {
227 ph.pop_last();
228 });
229 ph.push_last((branch.clone(), tree.insert_at(parent_idx, branch, value).1));
231 }
232 };
233 Some((tree, ph))
234 })
235 .map(|(tree, _)| tree)
236 .unwrap()
237 }
238}