use tokio::sync::watch;
use crate::chroot::OwnedChroot;
use crate::error::Error;
use crate::session::{OneshotReceiver, PersistentReceiver, SessionState, WatchReceiver, WatchedEvent};
#[derive(Clone, Debug)]
pub struct StateWatcher {
receiver: watch::Receiver<SessionState>,
}
impl StateWatcher {
pub(super) fn new(receiver: watch::Receiver<SessionState>) -> StateWatcher {
StateWatcher { receiver }
}
pub fn state(&mut self) -> SessionState {
let state = self.receiver.borrow_and_update();
*state
}
pub async fn changed(&mut self) -> SessionState {
if self.receiver.changed().await.is_err() {
std::future::pending().await
}
self.state()
}
pub fn peek_state(&self) -> SessionState {
let state = self.receiver.borrow();
*state
}
}
#[derive(Debug)]
pub struct OneshotWatcher {
chroot: OwnedChroot,
receiver: OneshotReceiver,
}
impl OneshotWatcher {
fn new(chroot: OwnedChroot, receiver: OneshotReceiver) -> Self {
OneshotWatcher { chroot, receiver }
}
pub async fn changed(self) -> WatchedEvent {
let mut event = self.receiver.recv().await;
event.drain_root_path(self.chroot.root());
event
}
pub async fn remove(self) -> Result<(), Error> {
self.receiver.remove().await
}
}
#[derive(Debug)]
pub struct PersistentWatcher {
chroot: OwnedChroot,
receiver: PersistentReceiver,
}
impl PersistentWatcher {
fn new(chroot: OwnedChroot, receiver: PersistentReceiver) -> Self {
PersistentWatcher { chroot, receiver }
}
pub async fn changed(&mut self) -> WatchedEvent {
let mut event = self.receiver.recv().await;
event.drain_root_path(self.chroot.root());
event
}
pub async fn remove(self) -> Result<(), Error> {
self.receiver.remove().await
}
}
impl WatchReceiver {
pub fn into_oneshot(self, chroot: &OwnedChroot) -> OneshotWatcher {
match self {
WatchReceiver::None => unreachable!("expect oneshot watcher, got none watcher"),
WatchReceiver::Oneshot(receiver) => OneshotWatcher::new(chroot.clone(), receiver),
WatchReceiver::Persistent(_) => {
unreachable!("expect oneshot watcher, got persistent watcher")
},
}
}
pub fn into_persistent(self, chroot: &OwnedChroot) -> PersistentWatcher {
match self {
WatchReceiver::None => unreachable!("expect oneshot watcher, got none watcher"),
WatchReceiver::Oneshot(_) => {
unreachable!("expect oneshot watcher, got oneshot watcher")
},
WatchReceiver::Persistent(receiver) => PersistentWatcher::new(chroot.clone(), receiver),
}
}
}