//! File-watching //! //! When serving a directory not in oneshot-mode, this can be used to update listings. use super::*; use std::{path::PathBuf, time::Duration}; use std::sync::Arc; use std::ops::Deref; use notify::{ Watcher, RecursiveMode, watcher, //TODO: set up wrapper around the notify callback thread that puts events into a async tokio::mpsc (or broadcast?) sender. }; use tokio::sync::{ broadcast, mpsc, }; //use tokio_uring // Don't do this here, have a seperate thread using this (if we end up using it, we probably should since we probably don't need multiple threads reading/writing files at once.) pub trait Receiver { type Error; fn recv(&mut self) -> Result; } pub trait Sender { type Error; fn send(&self, val: T) -> Result<(), Self::Error>; } pub trait Channel: Sized { type Sender: Sender; type Receiver: Receiver; fn split(self) -> (Self::Sender, Self::Receiver); } impl Channel for (S, R) where S: Sender, R: Receiver { type Sender = S; type Receiver = R; #[inline(always)] fn split(self) -> (Self::Sender, Self::Receiver) { self } } impl Sender for broadcast::Sender { type Error = broadcast::error::SendError; fn send(&self, val: T) -> Result<(), Self::Error> { self.send(val)?; Ok(()) } } impl Receiver for broadcast::Receiver where T: Clone { type Error = broadcast::error::TryRecvError; fn recv(&mut self) -> Result { broadcast::Receiver::try_recv(self) } } impl Sender for mpsc::Sender { type Error = mpsc::error::TrySendError; fn send(&self, val: T) -> Result<(), Self::Error> { self.try_send(val) } } impl Receiver for mpsc::Receiver { type Error = mpsc::error::TryRecvError; fn recv(&mut self) -> Result { self.try_recv() } } impl Sender for mpsc::UnboundedSender { type Error = mpsc::error::SendError; fn send(&self, val: T) -> Result<(), Self::Error> { self.send(val) } } impl Receiver for mpsc::UnboundedReceiver { type Error = mpsc::error::TryRecvError; fn recv(&mut self) -> Result { self.try_recv() } } #[derive(Debug, Clone, PartialEq)] pub struct WatchEvent(Arc); impl WatchEvent { #[inline(always)] pub fn debounced(&self) -> ¬ify::DebouncedEvent { &self.0 } } impl AsRef for WatchEvent { #[inline] fn as_ref(&self) -> ¬ify::DebouncedEvent { self.debounced() } } impl Deref for WatchEvent { type Target = notify::DebouncedEvent; #[inline] fn deref(&self) -> &Self::Target { self.debounced() } } #[derive(Debug, Clone, PartialEq, Eq)] pub struct Mode { pub recurse: RecursiveMode, pub delay: Duration, } /// Start a new watcher thread. /// /// # Returns /// * A receiver that gets the events from the watcher /// * A future that completes when the thread exits pub fn watch<'a, C>(path: PathBuf, mode: Mode, chan: impl FnOnce() -> C + 'a) -> (C::Receiver, impl Future + Send + Sync + 'static) where C: Channel, C::Sender: Send + 'static, { let (otx, orx) = chan().split(); let (stx, trx) = std::sync::mpsc::channel(); let mut watcher = watcher(stx, mode.delay).unwrap(); let passing = tokio::spawn(async move { match trx.try_recv() { Ok(ev) => otx.send(WatchEvent(Arc::new(ev))).map_err(|_| ()).unwrap(), Err(_) => (),//tokio::time::sleep(mode.delay).await, FUCK, WHY can't we await here... ALL of this bullshit above with the traits is useless. just return the damn sync `Receiver`. } }); { use futures::prelude::*; (orx, passing.map(|_| ())) } }