use std::any::Any;
use std::fmt;
use std::sync::Arc;
use semver::Version;
use crate::release::Release;
pub trait UpdateDriver: Any {
fn start(&mut self, events: DriverEvents);
fn check(&mut self);
fn install(&mut self);
fn relaunch(&mut self);
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum DriverEvent {
Checking,
UpToDate,
Found(Release),
Downloading {
downloaded: u64,
total: Option<u64>,
},
Installing,
ReadyToRelaunch(Version),
Failed(String),
Settled,
}
#[derive(Clone)]
pub struct DriverEvents {
sink: Arc<dyn Fn(DriverEvent) + Send + Sync>,
}
impl DriverEvents {
pub fn new(sink: impl Fn(DriverEvent) + Send + Sync + 'static) -> Self {
Self {
sink: Arc::new(sink),
}
}
pub fn emit(&self, event: DriverEvent) {
(self.sink)(event);
}
}
impl fmt::Debug for DriverEvents {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DriverEvents").finish_non_exhaustive()
}
}
#[cfg(test)]
mod tests {
use std::sync::Mutex;
use super::*;
#[test]
fn events_reach_the_sink_from_any_clone() {
let seen = Arc::new(Mutex::new(Vec::new()));
let events = {
let seen = seen.clone();
DriverEvents::new(move |event| seen.lock().unwrap().push(format!("{event:?}")))
};
let clone = events.clone();
std::thread::spawn(move || clone.emit(DriverEvent::Checking))
.join()
.unwrap();
events.emit(DriverEvent::Settled);
assert_eq!(*seen.lock().unwrap(), ["Checking", "Settled"]);
}
}