#![deny(missing_docs)]
pub use config::{Config, RecursiveMode};
pub use error::{Error, ErrorKind, Result};
pub use event::{Event, EventKind};
use std::path::Path;
#[allow(dead_code)]
#[cfg(feature = "crossbeam-channel")]
pub(crate) type Receiver<T> = crossbeam_channel::Receiver<T>;
#[allow(dead_code)]
#[cfg(not(feature = "crossbeam-channel"))]
pub(crate) type Receiver<T> = std::sync::mpsc::Receiver<T>;
#[allow(dead_code)]
#[cfg(feature = "crossbeam-channel")]
pub(crate) type Sender<T> = crossbeam_channel::Sender<T>;
#[allow(dead_code)]
#[cfg(not(feature = "crossbeam-channel"))]
pub(crate) type Sender<T> = std::sync::mpsc::Sender<T>;
#[allow(dead_code)]
#[cfg(feature = "crossbeam-channel")]
pub(crate) type BoundSender<T> = crossbeam_channel::Sender<T>;
#[allow(dead_code)]
#[cfg(not(feature = "crossbeam-channel"))]
pub(crate) type BoundSender<T> = std::sync::mpsc::SyncSender<T>;
#[allow(dead_code)]
#[inline]
pub(crate) fn unbounded<T>() -> (Sender<T>, Receiver<T>) {
#[cfg(feature = "crossbeam-channel")]
return crossbeam_channel::unbounded();
#[cfg(not(feature = "crossbeam-channel"))]
return std::sync::mpsc::channel();
}
#[allow(dead_code)]
#[inline]
pub(crate) fn bounded<T>(cap: usize) -> (BoundSender<T>, Receiver<T>) {
#[cfg(feature = "crossbeam-channel")]
return crossbeam_channel::bounded(cap);
#[cfg(not(feature = "crossbeam-channel"))]
return std::sync::mpsc::sync_channel(cap);
}
#[cfg(all(target_os = "macos", not(feature = "macos_kqueue")))]
pub use crate::fsevent::FsEventWatcher;
#[cfg(target_os = "linux")]
pub use crate::inotify::INotifyWatcher;
#[cfg(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonflybsd",
all(target_os = "macos", feature = "macos_kqueue")
))]
pub use crate::kqueue::KqueueWatcher;
pub use null::NullWatcher;
pub use poll::PollWatcher;
#[cfg(target_os = "windows")]
pub use windows::ReadDirectoryChangesWatcher;
#[cfg(all(target_os = "macos", not(feature = "macos_kqueue")))]
pub mod fsevent;
#[cfg(target_os = "linux")]
pub mod inotify;
#[cfg(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "dragonflybsd",
target_os = "netbsd",
all(target_os = "macos", feature = "macos_kqueue")
))]
pub mod kqueue;
#[cfg(target_os = "windows")]
pub mod windows;
pub mod event;
pub mod null;
pub mod poll;
mod config;
mod error;
pub trait EventHandler: Send + 'static {
fn handle_event(&mut self, event: Result<Event>);
}
impl<F> EventHandler for F
where
F: FnMut(Result<Event>) + Send + 'static,
{
fn handle_event(&mut self, event: Result<Event>) {
(self)(event);
}
}
#[cfg(feature = "crossbeam-channel")]
impl EventHandler for crossbeam_channel::Sender<Result<Event>> {
fn handle_event(&mut self, event: Result<Event>) {
let _ = self.send(event);
}
}
impl EventHandler for std::sync::mpsc::Sender<Result<Event>> {
fn handle_event(&mut self, event: Result<Event>) {
let _ = self.send(event);
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum WatcherKind {
Inotify,
Fsevent,
Kqueue,
PollWatcher,
ReadDirectoryChangesWatcher,
NullWatcher,
}
pub trait Watcher {
fn new<F: EventHandler>(event_handler: F, config: config::Config) -> Result<Self>
where
Self: Sized;
fn watch(&mut self, path: &Path, recursive_mode: RecursiveMode) -> Result<()>;
fn unwatch(&mut self, path: &Path) -> Result<()>;
fn configure(&mut self, _option: Config) -> Result<bool> {
Ok(false)
}
fn kind() -> WatcherKind
where
Self: Sized;
}
#[cfg(target_os = "linux")]
pub type RecommendedWatcher = INotifyWatcher;
#[cfg(all(target_os = "macos", not(feature = "macos_kqueue")))]
pub type RecommendedWatcher = FsEventWatcher;
#[cfg(target_os = "windows")]
pub type RecommendedWatcher = ReadDirectoryChangesWatcher;
#[cfg(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonflybsd",
all(target_os = "macos", feature = "macos_kqueue")
))]
pub type RecommendedWatcher = KqueueWatcher;
#[cfg(not(any(
target_os = "linux",
target_os = "macos",
target_os = "windows",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonflybsd"
)))]
pub type RecommendedWatcher = PollWatcher;
pub fn recommended_watcher<F>(event_handler: F) -> Result<RecommendedWatcher>
where
F: EventHandler,
{
RecommendedWatcher::new(event_handler, Config::default())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_object_safe() {
let _watcher: &dyn Watcher = &NullWatcher;
}
#[test]
fn test_debug_impl() {
macro_rules! assert_debug_impl {
($t:ty) => {{
trait NeedsDebug: std::fmt::Debug {}
impl NeedsDebug for $t {}
}};
}
assert_debug_impl!(Config);
assert_debug_impl!(Error);
assert_debug_impl!(ErrorKind);
assert_debug_impl!(event::AccessKind);
assert_debug_impl!(event::AccessMode);
assert_debug_impl!(event::CreateKind);
assert_debug_impl!(event::DataChange);
assert_debug_impl!(event::EventAttributes);
assert_debug_impl!(event::Flag);
assert_debug_impl!(event::MetadataKind);
assert_debug_impl!(event::ModifyKind);
assert_debug_impl!(event::RemoveKind);
assert_debug_impl!(event::RenameMode);
assert_debug_impl!(Event);
assert_debug_impl!(EventKind);
assert_debug_impl!(NullWatcher);
assert_debug_impl!(PollWatcher);
assert_debug_impl!(RecommendedWatcher);
assert_debug_impl!(RecursiveMode);
assert_debug_impl!(WatcherKind);
}
}