1use std::collections::VecDeque;
2use std::fmt::{Display, Write};
3
4pub trait TreeChild<T: TreeLike> {
5 fn children<'a>(&self) -> Option<T::RefIter<'a>>
6 where
7 Self: 'a;
8}
9
10pub trait TreeLike: Sized {
11 type Child<'a>: TreeChild<Self>
12 where
13 Self: 'a;
14 type RefIter<'a>: Iterator<Item = Self::Child<'a>> + TreeChildIter<'a, Self>
15 where
16 Self: 'a;
17 fn children(&self) -> Option<Self::RefIter<'_>>;
18 #[inline]
19 fn dfs(&self) -> Option<DFSIter<Self>> {
20 self.children().map(TreeChildIter::dfs)
21 }
22 #[inline]
23 fn bfs(&self) -> Option<BFSIter<Self>> {
24 self.children().map(TreeChildIter::bfs)
25 }
26
27 #[cfg(feature = "rayon")]
28 fn bfs_par<'a>(&'a self) -> Option<spliter::ParSpliter<BFSIter<'a, Self>>>
29 where
30 Self::Child<'a>: Send,
31 Self::RefIter<'a>: Send,
32 {
33 self.children().map(TreeChildIter::par_iter)
34 }
35
36 #[inline]
37 #[allow(clippy::missing_errors_doc)]
38 fn dfs_with_close<
39 'a,
40 R,
41 SG,
42 SL,
43 Open: FnMut(&mut SG, Self::Child<'a>) -> Result<DFSContinuation<SL>, R>,
44 Close: FnMut(&mut SG, SL) -> Result<(), R>,
45 >(
46 &'a self,
47 state: &mut SG,
48 open: Open,
49 close: Close,
50 ) -> Result<(), R> {
51 self.children().map_or(Ok(()), |d| {
52 TreeChildIter::<'a, Self>::dfs_with_close(d, state, open, close)
53 })
54 }
55
56 #[inline]
57 #[allow(clippy::missing_errors_doc)]
58 fn display_nested<'a>(
59 &'a self,
60 f: &mut std::fmt::Formatter<'_>,
61 open: impl Fn(
62 &Self::Child<'a>,
63 &mut Indentor,
64 &mut std::fmt::Formatter<'_>,
65 ) -> Result<DFSContinuation<()>, std::fmt::Error>,
66 close: impl Fn(&Self::Child<'a>, &mut std::fmt::Formatter<'_>) -> std::fmt::Result,
67 indent: Option<Indentor>,
68 ) -> std::fmt::Result {
69 self.children().map_or(Ok(()), |d| {
70 TreeChildIter::<'a, Self>::display_nested(d, f, open, close, indent)
71 })
72 }
73
74 #[inline]
75 #[allow(clippy::missing_errors_doc)]
76 fn display_children<'a, I: Into<Self::RefIter<'a>>>(
77 i: I,
78 f: &mut std::fmt::Formatter<'_>,
79 open: impl Fn(
80 &Self::Child<'a>,
81 &mut Indentor,
82 &mut std::fmt::Formatter<'_>,
83 ) -> Result<DFSContinuation<()>, std::fmt::Error>,
84 close: impl Fn(&Self::Child<'a>, &mut std::fmt::Formatter<'_>) -> std::fmt::Result,
85 indent: Option<Indentor>,
86 ) -> std::fmt::Result
87 where
88 Self: 'a,
89 {
90 i.into().display_nested(f, open, close, indent)
91 }
92}
93
94#[derive(Clone)]
95pub struct Indentor<'a>(&'a str, i32, std::cell::Cell<bool>);
96impl Default for Indentor<'_> {
97 fn default() -> Self {
98 Self(Self::DEFAULT, 0, std::cell::Cell::new(false))
99 }
100}
101impl Indentor<'_> {
102 const DEFAULT: &'static str = " ";
103 pub fn scoped<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
104 self.1 += 1;
105 let r = f(self);
106 self.1 -= 1;
107 r
108 }
109 #[must_use]
110 pub const fn new(indent_str: &str, indent: i32) -> Indentor<'_> {
111 Indentor(indent_str, indent, std::cell::Cell::new(false))
112 }
113 #[must_use]
114 pub const fn with(indent: i32) -> Indentor<'static> {
115 Indentor(Self::DEFAULT, indent, std::cell::Cell::new(false))
116 }
117 pub fn skip_next(&self) {
118 self.2.set(true);
119 }
120}
121impl Display for Indentor<'_> {
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 if self.2.replace(false) || self.1 == 0 {
124 return Ok(());
125 }
126 f.write_char('\n')?;
127 for _ in 0..self.1 {
128 write!(f, "{}", self.0)?;
129 }
130 Ok(())
131 }
132}
133
134pub enum DFSContinuation<SL> {
135 Continue,
136 OnClose(SL),
137 SkipChildren,
138 SkipNext,
139 SkipNextAndClose(SL),
140}
141
142pub trait TreeChildIter<'a, T: TreeLike<RefIter<'a> = Self> + 'a>: Iterator
143where
144 Self: Sized + 'a,
145{
146 #[inline]
147 fn dfs(self) -> DFSIter<'a, T> {
148 DFSIter {
149 stack: Vec::new(),
150 current: self,
151 }
152 }
153 #[inline]
154 fn bfs(self) -> BFSIter<'a, T> {
155 BFSIter {
156 stack: VecDeque::new(),
157 current: self,
158 }
159 }
160 #[cfg(feature = "rayon")]
161 #[inline]
162 fn par_iter(self) -> spliter::ParSpliter<BFSIter<'a, T>>
163 where
164 Self: Send,
165 T::Child<'a>: Send,
166 {
167 use rayon::iter::IntoParallelIterator;
168 use spliter::ParallelSpliterator;
169 self.bfs().par_split().into_par_iter()
170 }
171
172 #[allow(clippy::missing_errors_doc)]
173 #[allow(clippy::unnecessary_map_or)]
174 fn dfs_with_close<
175 R,
176 SG,
177 SL,
178 Open: FnMut(&mut SG, T::Child<'a>) -> Result<DFSContinuation<SL>, R>,
179 Close: FnMut(&mut SG, SL) -> Result<(), R>,
180 >(
181 self,
182 state: &mut SG,
183 mut open: Open,
184 mut close: Close,
185 ) -> Result<(), R> {
186 fn i_next<'a, SL, T: TreeLike + 'a>(
187 current: &mut (Option<SL>, T::RefIter<'a>),
188 stack: &mut Vec<(Option<SL>, T::RefIter<'a>)>,
189 ) -> Option<(bool, T::Child<'a>)> {
190 current.1.next().map(|c| {
191 (
192 c.children().map_or(false, |children| {
193 stack.push(std::mem::replace(current, (None, children)));
194 true
195 }),
196 c,
197 )
198 })
199 }
200
201 let mut stack = Vec::new();
202 let mut current = (None, self);
203 loop {
204 let r = if let Some(r) = i_next::<SL, T>(&mut current, &mut stack) {
205 Some(r)
206 } else {
207 loop {
208 if let Some(next) = stack.pop() {
209 let (old, _) = std::mem::replace(&mut current, next);
210 if let Some(s) = old {
211 close(state, s)?;
212 }
213 if let Some(c) = i_next::<SL, T>(&mut current, &mut stack) {
214 break Some(c);
215 }
216 } else {
217 break None;
218 }
219 }
220 };
221 if let Some((has_children, r)) = r {
222 match open(state, r)? {
223 DFSContinuation::Continue => (),
224 DFSContinuation::OnClose(s) if has_children => {
225 current.0 = Some(s);
226 }
227 DFSContinuation::OnClose(s) => close(state, s)?,
228 DFSContinuation::SkipChildren => {
229 if has_children {
230 current = stack.pop().unwrap_or_else(|| unreachable!());
231 }
232 }
233 DFSContinuation::SkipNext => {
234 current.1.next();
235 }
236 DFSContinuation::SkipNextAndClose(s) => {
237 if has_children {
238 current.1.next();
239 current.0 = Some(s);
240 } else {
241 close(state, s)?;
242 }
243 }
244 }
245 } else {
246 break;
247 }
248 }
249 Ok(())
250 }
251
252 #[allow(clippy::cast_sign_loss)]
253 #[allow(clippy::missing_errors_doc)]
254 fn display_nested(
255 self,
256 f: &mut std::fmt::Formatter<'_>,
257 open: impl Fn(
258 &T::Child<'a>,
259 &mut Indentor,
260 &mut std::fmt::Formatter<'_>,
261 ) -> Result<DFSContinuation<()>, std::fmt::Error>,
262 close: impl Fn(&T::Child<'a>, &mut std::fmt::Formatter<'_>) -> std::fmt::Result,
263 ind: Option<Indentor>,
264 ) -> std::fmt::Result {
265 let mut ind = ind.unwrap_or_default();
266 self.dfs_with_close(
267 &mut (f, &mut ind),
268 |(f, ind), c| {
269 ind.fmt(f)?;
270 Ok(match open(&c, ind, f)? {
271 DFSContinuation::OnClose(()) => {
272 ind.1 += 1;
273 DFSContinuation::OnClose(c)
274 }
275 DFSContinuation::Continue => DFSContinuation::Continue,
276 DFSContinuation::SkipChildren => DFSContinuation::SkipChildren,
277 DFSContinuation::SkipNext => DFSContinuation::SkipNext,
278 DFSContinuation::SkipNextAndClose(()) => {
279 ind.1 += 1;
280 DFSContinuation::SkipNextAndClose(c)
281 }
282 })
283 },
284 |(f, ind), c| {
285 ind.1 -= 1;
286 if ind.1 == 0 {
287 f.write_char('\n')
288 } else {
289 ind.fmt(f)
290 }?;
291 close(&c, f)
292 },
293 )
294 }
295}
296impl<'a, T: TreeLike<RefIter<'a> = I> + 'a, I: Iterator<Item = T::Child<'a>> + 'a>
297 TreeChildIter<'a, T> for I
298{
299}
300
301pub struct DFSIter<'a, T: TreeLike + 'a> {
302 stack: Vec<T::RefIter<'a>>,
303 current: T::RefIter<'a>,
304}
305impl<'a, T: TreeLike> DFSIter<'a, T> {
306 fn i_next(&mut self) -> Option<T::Child<'a>> {
307 if let Some(c) = self.current.next() {
308 if let Some(children) = c.children() {
309 self.stack
310 .push(std::mem::replace(&mut self.current, children));
311 }
312 Some(c)
313 } else {
314 None
315 }
316 }
317}
318impl<'a, T: TreeLike + 'a> Iterator for DFSIter<'a, T> {
319 type Item = T::Child<'a>;
320 fn next(&mut self) -> Option<Self::Item> {
321 self.i_next().or_else(|| {
322 while let Some(next) = self.stack.pop() {
323 self.current = next;
324 if let Some(c) = self.i_next() {
325 return Some(c);
326 }
327 }
328 None
329 })
330 }
331}
332
333pub struct BFSIter<'a, T: TreeLike + 'a> {
334 stack: VecDeque<T::RefIter<'a>>,
335 current: T::RefIter<'a>,
336}
337impl<'a, T: TreeLike + 'a> Iterator for BFSIter<'a, T> {
338 type Item = T::Child<'a>;
339 fn next(&mut self) -> Option<Self::Item> {
340 if let Some(c) = self.current.next() {
341 if let Some(children) = c.children() {
342 self.stack.push_back(children);
343 }
344 Some(c)
345 } else {
346 while let Some(next) = self.stack.pop_front() {
347 self.current = next;
348 if let Some(c) = self.current.next() {
349 return Some(c);
350 }
351 }
352 None
353 }
354 }
355}
356#[cfg(feature = "rayon")]
357impl<'a, T: TreeLike + 'a> spliter::Spliterator for BFSIter<'a, T> {
358 fn split(&mut self) -> Option<Self> {
359 if self.stack.len() < 2 {
360 return None;
361 }
362 let split = self.stack.len() / 2;
363 let mut new_stack = self.stack.split_off(split);
364 let new_curr = new_stack.pop_front().unwrap_or_else(|| unreachable!());
365 Some(BFSIter {
366 stack: new_stack,
367 current: new_curr,
368 })
369 }
370}
371
372impl TreeChild<Self> for std::fs::DirEntry {
373 fn children<'a>(&self) -> Option<<Self as TreeLike>::RefIter<'a>> {
374 <Self as TreeLike>::children(self)
375 }
376}
377
378impl TreeLike for std::fs::DirEntry {
379 type Child<'a> = Self;
380 type RefIter<'a> =
381 std::iter::FilterMap<std::fs::ReadDir, fn(std::io::Result<Self>) -> Option<Self>>;
382 #[allow(clippy::option_if_let_else)]
383 fn children(&self) -> Option<Self::RefIter<'_>> {
384 if let Ok(p) = std::fs::read_dir(self.path()) {
385 Some(p.filter_map(Result::ok))
386 } else {
387 None
388 }
389 }
390 }
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400 use std::fmt::{Display, Formatter, Write};
401
402 fn foo() -> TopFoo {
403 TopFoo {
404 children: vec![
405 FooChild::Leaf("a"),
406 FooChild::Foo1(Foo1 {
407 name: "b",
408 children: vec![
409 FooChild::Leaf("c"),
410 FooChild::Foo2(Foo2 {
411 name: "d",
412 children: vec![FooChild::Leaf("e"), FooChild::Leaf("f")],
413 }),
414 ],
415 }),
416 FooChild::Foo2(Foo2 {
417 name: "g",
418 children: vec![FooChild::Leaf("h"), FooChild::Leaf("i")],
419 }),
420 ],
421 }
422 }
423
424 #[test]
425 fn dfs() {
426 let foo = foo();
427 let dfs = foo
428 .dfs()
429 .unwrap_or_else(|| unreachable!())
430 .map(FooChild::name)
431 .collect::<Vec<_>>();
432 assert_eq!(dfs, vec!["a", "b", "c", "d", "e", "f", "g", "h", "i"]);
433 }
434 #[test]
435 fn bfs() {
436 let foo = foo();
437 let bfs = foo
438 .bfs()
439 .unwrap_or_else(|| unreachable!())
440 .map(FooChild::name)
441 .collect::<Vec<_>>();
442 assert_eq!(bfs, vec!["a", "b", "g", "c", "d", "h", "i", "e", "f"]);
443 }
444 #[test]
445 fn display() {
446 let foo = foo();
447 let expect = "<TopFoo>
448 <Leaf a/>
449 <Foo1>
450 <Leaf c/>
451 <Foo2>
452 <Leaf e/>
453 <Leaf f/>
454 </Foo2>
455 </Foo1>
456 <Foo2>
457 <Leaf h/>
458 <Leaf i/>
459 </Foo2>
460</TopFoo>";
461 let mut s = String::new();
462 write!(s, "{foo}").unwrap();
463 assert_eq!(s, expect);
464 }
465 struct TopFoo {
466 children: Vec<FooChild>,
467 }
468 impl TreeLike for TopFoo {
469 type Child<'a> = &'a FooChild;
470 type RefIter<'a> = std::slice::Iter<'a, FooChild>;
471 fn children(&self) -> Option<Self::RefIter<'_>> {
472 Some(self.children.iter())
473 }
474 }
475 impl Display for TopFoo {
476 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
477 write!(f, "<TopFoo>")?;
478 self.display_nested(
479 f,
480 |c, _, f| match *c {
481 FooChild::Leaf(s) => {
482 write!(f, "<Leaf {s}/>")?;
483 Ok(DFSContinuation::Continue)
484 }
485 FooChild::Foo1(_) => {
486 write!(f, "<Foo1>")?;
487 Ok(DFSContinuation::OnClose(()))
488 }
489 FooChild::Foo2(_) => {
490 write!(f, "<Foo2>")?;
491 Ok(DFSContinuation::OnClose(()))
492 }
493 },
494 |c, f| match *c {
495 FooChild::Leaf(_) => unreachable!(),
496 FooChild::Foo1(_) => write!(f, "</Foo1>"),
497 FooChild::Foo2(_) => write!(f, "</Foo2>"),
498 },
499 Some(Indentor::with(1)),
500 )?;
501 write!(f, "\n</TopFoo>")
502 }
503 }
504 struct Foo1 {
505 name: &'static str,
506 children: Vec<FooChild>,
507 }
508 struct Foo2 {
509 name: &'static str,
510 children: Vec<FooChild>,
511 }
512 enum FooChild {
513 Leaf(&'static str),
514 Foo1(Foo1),
515 Foo2(Foo2),
516 }
517 impl FooChild {
518 const fn name(&self) -> &'static str {
519 match self {
520 Self::Leaf(s) => s,
521 Self::Foo1(f) => f.name,
522 Self::Foo2(f) => f.name,
523 }
524 }
525 }
526 impl TreeChild<TopFoo> for &FooChild {
527 fn children<'b>(&self) -> Option<<TopFoo as TreeLike>::RefIter<'b>>
528 where
529 Self: 'b,
530 {
531 match self {
532 FooChild::Leaf(_) => None,
533 FooChild::Foo1(f) => Some(f.children.iter()),
534 FooChild::Foo2(f) => Some(f.children.iter()),
535 }
536 }
537 }
538}