Skip to main content

rsynko_rsync/
program.rs

1use crate::*;
2use alux_ext::ext;
3use ambassador::delegatable_trait;
4
5/// Specifies running one transfer command and reading what it states.
6///
7/// The command is already decided; an interpreter only starts it, hands back what it wrote line
8/// by line, and states how it ended.
9#[delegatable_trait]
10pub trait SyncRunAlg: RsyncSorts {
11    /// Denotes failure to run the transfer.
12    type Error;
13    /// Carries one running transfer.
14    type Run;
15
16    /// Starts one transfer command.
17    ///
18    /// # Errors
19    ///
20    /// Returns the interpreter-specific failure to start it.
21    fn start_sync(&self, command: &Self::Command) -> Result<Self::Run, Self::Error>;
22
23    /// Reads the next line the running transfer wrote, and states when it has written its last.
24    ///
25    /// # Errors
26    ///
27    /// Returns the interpreter-specific failure to read from it.
28    fn next_sync_line(&self, run: &mut Self::Run) -> Result<Option<String>, Self::Error>;
29
30    /// Waits for the transfer to end and states whether it ended well.
31    ///
32    /// # Errors
33    ///
34    /// Returns the interpreter-specific failure the transfer ended with.
35    fn finish_sync(&self, run: Self::Run) -> Result<(), Self::Error>;
36}
37
38/// Specifies what an interpreter does with each thing a running transfer states.
39#[delegatable_trait]
40pub trait SyncWatchAlg: RsyncSorts {
41    /// Applies one observation of the running transfer.
42    fn watch_sync(&self, observation: &Self::Observation);
43}
44
45/// Derives one whole transfer from starting it, reading it, and finishing it.
46#[ext(name = SyncProgramExt)]
47pub impl<This> This
48where
49    This: SyncRunAlg + SyncWatchAlg + SyncChangeAlg + SyncObservationAlg + SyncObservationViewAlg,
50    This::Change: Clone,
51{
52    /// Runs one transfer and states every change it named, in the order it named them.
53    ///
54    /// Every line is watched as it arrives, so an interpreter following a transfer sees progress
55    /// while it runs rather than after it ends.
56    ///
57    /// # Errors
58    ///
59    /// Returns the failure that started, read, or ended the transfer.
60    fn run_sync(&self, command: &This::Command) -> Result<Vec<This::Change>, This::Error> {
61        let mut run = self.start_sync(command)?;
62        let mut changes = Vec::new();
63        while let Some(line) = self.next_sync_line(&mut run)? {
64            let observation = self.read_sync_line(&line);
65            self.watch_sync(&observation);
66            if let Some(change) = self.observation_change(&observation) {
67                changes.push(change.clone());
68            }
69        }
70        self.finish_sync(run)?;
71        Ok(changes)
72    }
73}