libarx/
walk.rs

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}