1use super::common::*;
2use super::Arx;
3use jbk::reader::Range;
4
5pub trait Operator<Context, Builder: FullBuilderTrait> {
6 fn on_start(&self, context: &mut Context) -> jbk::Result<()>;
7 fn on_stop(&self, context: &mut Context) -> jbk::Result<()>;
8 fn on_directory_enter(
9 &self,
10 context: &mut Context,
11 entry: &<Builder::Entry as EntryDef>::Dir,
12 ) -> jbk::Result<bool>;
13 fn on_directory_exit(
14 &self,
15 context: &mut Context,
16 entry: &<Builder::Entry as EntryDef>::Dir,
17 ) -> jbk::Result<()>;
18 fn on_file(
19 &self,
20 context: &mut Context,
21 entry: &<Builder::Entry as EntryDef>::File,
22 ) -> jbk::Result<()>;
23 fn on_link(
24 &self,
25 context: &mut Context,
26 entry: &<Builder::Entry as EntryDef>::Link,
27 ) -> jbk::Result<()>;
28}
29
30pub struct Walker<'a, Context> {
31 arx: &'a Arx,
32 context: Context,
33}
34
35impl<'a, Context> Walker<'a, Context> {
36 pub fn new(arx: &'a Arx, context: Context) -> Self {
37 Self { arx, context }
38 }
39
40 pub fn run<B>(&mut self, op: &dyn Operator<Context, B>) -> jbk::Result<()>
41 where
42 B: FullBuilderTrait,
43 {
44 let builder = RealBuilder::<B>::new(&self.arx.properties);
45
46 op.on_start(&mut self.context)?;
47 self._run(&self.arx.root_index, &builder, op)?;
48 op.on_stop(&mut self.context)
49 }
50
51 pub fn run_from_range<R: Range, B>(
52 &mut self,
53 op: &dyn Operator<Context, B>,
54 range: &R,
55 ) -> jbk::Result<()>
56 where
57 B: FullBuilderTrait,
58 {
59 let builder = RealBuilder::<B>::new(&self.arx.properties);
60
61 op.on_start(&mut self.context)?;
62 self._run(range, &builder, op)?;
63 op.on_stop(&mut self.context)
64 }
65
66 fn _run<R: Range, B>(
67 &mut self,
68 range: &R,
69 builder: &RealBuilder<B>,
70 op: &dyn Operator<Context, B>,
71 ) -> jbk::Result<()>
72 where
73 B: FullBuilderTrait,
74 {
75 let read_entry = ReadEntry::new(range, builder);
76 for entry in read_entry {
77 match entry? {
78 Entry::File(e) => op.on_file(&mut self.context, &e)?,
79 Entry::Link(e) => op.on_link(&mut self.context, &e)?,
80 Entry::Dir(range, e) => {
81 if op.on_directory_enter(&mut self.context, &e)? {
82 self._run(&range, builder, op)?;
83 }
84 op.on_directory_exit(&mut self.context, &e)?;
85 }
86 }
87 }
88 Ok(())
89 }
90}