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}