vstorage 0.9.0

Common API for various icalendar/vcard storages.
Documentation
// Copyright 2025-2026 Hugo Osvaldo Barrera
//
// SPDX-License-Identifier: EUPL-1.2

use futures_util::future::BoxFuture;
use tokio::sync::mpsc::{self, Receiver};

use crate::{
    ErrorKind, Result,
    watch::{Event, StorageMonitor},
};

use super::VdirStorage;

/// Monitor for a [`VdirStorage`] instance.
///
/// # Quirks
///
/// Due to limitations of the underlying platform-specific interfaces, it's possible that some
/// events are missed. When this happens, an [`Event::General`] is returned.
pub struct VdirMonitor {
    receiver: Receiver<Event>,
}

impl VdirMonitor {
    /// Create a new monitor for `storage`.
    ///
    /// # Errors
    ///
    /// If an error occurs setting up the underlying filesystem watcher.
    #[allow(unused)] // Only Linux uses params, others are not implemented.
    #[allow(clippy::unused_async)] // Non-Linux has no await points.
    pub async fn new(storage: &VdirStorage) -> Result<VdirMonitor> {
        let (sender, receiver) = mpsc::channel::<Event>(1);

        #[cfg(target_os = "linux")]
        {
            use crate::vdir::linux::{init_inotify, run_inotify_task};

            let path = storage.path.clone();
            let extension = storage.extension.clone();
            let inotify_watcher = init_inotify(&path).await?;
            tokio::spawn(async move {
                // Emit initial Event::General after inotify is set up.
                if sender.send(Event::General).await.is_err() {
                    return;
                }
                run_inotify_task(sender, path, extension, inotify_watcher).await;
            });

            return Ok(VdirMonitor { receiver });
        }

        // TODO: kqueue (or other platform-specific) backend here.

        #[allow(unreachable_code)]
        Err(ErrorKind::Unsupported.into())
    }
}

impl StorageMonitor for VdirMonitor {
    fn next_event(&mut self) -> BoxFuture<'_, Option<Event>> {
        Box::pin(async { self.receiver.recv().await })
    }
}