tendrils_core/
tendril_report.rs

1use crate::{
2    FsoType,
3    InvalidTendrilError,
4    RawTendril,
5    TendrilActionError,
6    TendrilActionSuccess,
7};
8use std::marker::PhantomData;
9use std::path::PathBuf;
10
11/// Generic report format for any operation on a [`RawTendril`]
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub struct TendrilReport<T: TendrilLog> {
14    /// The original tendril bundle that this tendril was expanded from.
15    pub raw_tendril: RawTendril,
16
17    // TODO: `local` no longer needed if `raw_tendril` is here?
18    /// The tendril's relative local path.
19    pub local: String,
20    /// Result containing the log from the operation, provided
21    /// the tendril was valid.
22    /// Otherwise, it contains the [`InvalidTendrilError`].
23    pub log: Result<T, InvalidTendrilError>,
24}
25
26/// Generic log information for any operation on a tendril
27pub trait TendrilLog {
28    /// The type of the file system object in the Tendrils repo.
29    /// `None` if it does not exist.
30    fn local_type(&self) -> &Option<FsoType>;
31
32    /// The type of the file system object at its device-specific
33    /// location.
34    /// `None` if it does not exist.
35    fn remote_type(&self) -> &Option<FsoType>;
36
37    /// The full path to the remote. This shows the result after resolving
38    /// all environment/other variables in the path.
39    fn resolved_path(&self) -> &PathBuf;
40}
41
42/// Contains the metadata from a single tendrils action.
43#[derive(Clone, Debug, Eq, PartialEq)]
44pub struct ActionLog {
45    local_type: Option<FsoType>,
46    remote_type: Option<FsoType>,
47    resolved_path: PathBuf,
48    /// Result of this individual action.
49    pub result: Result<TendrilActionSuccess, TendrilActionError>,
50}
51
52impl ActionLog {
53    pub fn new(
54        local_type: Option<FsoType>,
55        remote_type: Option<FsoType>,
56        resolved_path: PathBuf,
57        result: Result<TendrilActionSuccess, TendrilActionError>,
58    ) -> ActionLog {
59        ActionLog { local_type, remote_type, resolved_path, result }
60    }
61}
62
63impl TendrilLog for ActionLog {
64    fn local_type(&self) -> &Option<FsoType> {
65        &self.local_type
66    }
67
68    fn remote_type(&self) -> &Option<FsoType> {
69        &self.remote_type
70    }
71
72    fn resolved_path(&self) -> &PathBuf {
73        &self.resolved_path
74    }
75}
76
77/// Contains various updater functions for live feedback during a tendrils
78/// command.
79pub trait UpdateHandler<L>
80where
81    L: TendrilLog
82{
83    /// Accepts `value` indicating the total count
84    /// of all raw tendrils that will be processed.
85    fn count(&mut self, value: i32);
86
87    /// Accepts `raw` indicating the tendril that will be processed.
88    /// This is called *before* processing.
89    fn before(&mut self, raw: RawTendril);
90
91    /// Accepts `report` containing the result of the operation.
92    /// This is called *after* processing.
93    fn after(&mut self, report: TendrilReport<L>);
94}
95
96/// Accepts callbacks to be called by the [`UpdateHandler`] methods.
97pub struct CallbackUpdater<A, B, C, L>
98where
99    A: FnMut(TendrilReport<L>),
100    B: FnMut(RawTendril),
101    C: FnMut(i32),
102    L: TendrilLog,
103{
104    pub count: C,
105    pub before: B,
106    pub after: A,
107    _marker: PhantomData<L>,
108}
109
110impl<A, B, C, L> CallbackUpdater<A, B, C, L>
111where
112    A: FnMut(TendrilReport<L>),
113    B: FnMut(RawTendril),
114    C: FnMut(i32),
115    L: TendrilLog,
116{
117    pub fn new(count: C, before: B, after: A) -> CallbackUpdater<A, B, C, L> {
118        CallbackUpdater {
119            count,
120            before,
121            after,
122            _marker: PhantomData,
123        }
124    }
125
126    #[cfg(test)]
127    pub fn default() -> CallbackUpdater<impl FnMut(TendrilReport<L>), impl FnMut(RawTendril), impl FnMut(i32), L> {
128        CallbackUpdater {
129            count: |_| {},
130            before: |_| {},
131            after: |_| {},
132            _marker: PhantomData,
133        }
134    }
135}
136
137impl<A, B, C, L> UpdateHandler<L> for CallbackUpdater<A, B, C, L>
138where
139    A: FnMut(TendrilReport<L>),
140    B: FnMut(RawTendril),
141    C: FnMut(i32),
142    L: TendrilLog,
143{
144    fn count(&mut self, total: i32) {
145        (self.count)(total)
146    }
147
148    fn before(&mut self, raw: RawTendril) {
149        (self.before)(raw)
150    }
151
152    fn after(&mut self, report: TendrilReport<L>) {
153        (self.after)(report)
154    }
155}