ed-journals 0.13.0

Provides models for representing and parsing elite dangerous journal files
Documentation
use crate::fs::error::LogFSError;
use crate::fs::Unblocker;
use notify::event::{CreateKind, RemoveKind};
use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::path::Path;
use std::sync::Arc;

/// Watches a directory for changes and unblocks the associated blocker when a change occurs.
///
/// ```rust
/// use std::env::current_dir;
/// use ed_journals::fs::{auto_detect_journal_path, DirWatcher, SyncBlocker};
///
/// let path = current_dir()
///     .unwrap()
///     .join("..")
///     .join("test-files")
///     .join("journals");
///
/// let blocker = SyncBlocker::new();
/// let dir_watcher = DirWatcher::new(&path, &blocker).unwrap();
///
/// # return;
/// blocker.wait().unwrap();
/// // Something changed
/// ```
///
/// Keep in mind that this watcher needs to be kept in scope for as long as you want to receive
/// notifications.
pub struct DirWatcher {
    _watcher: RecommendedWatcher,
}

impl DirWatcher {
    /// Creates a new [DirWatcher] which will watch the provided path for changes.
    pub fn new<P: AsRef<Path>>(
        path: P,
        unblocker: impl Into<Arc<dyn Unblocker>>,
    ) -> Result<DirWatcher, LogFSError> {
        let unblocker = unblocker.into();

        let mut watcher =
            notify::recommended_watcher(move |event: notify::Result<notify::Event>| {
                let event: notify::Event = match event {
                    Ok(event) => event,
                    Err(error) => {
                        let _ = unblocker.unblock(Err(LogFSError::NotifyError(error)));
                        return;
                    }
                };

                #[cfg(target_family = "unix")]
                match event.kind {
                    EventKind::Create(CreateKind::File) | EventKind::Remove(RemoveKind::Any) => {
                        true
                    }
                    _ => return,
                };

                #[cfg(target_family = "windows")]
                match event.kind {
                    EventKind::Create(CreateKind::Any) | EventKind::Remove(RemoveKind::Any) => true,
                    _ => return,
                };

                let _ = unblocker.unblock(Ok(()));
            })?;

        watcher.watch(path.as_ref(), RecursiveMode::NonRecursive)?;

        Ok(DirWatcher { _watcher: watcher })
    }
}