use crate::workspace::WorkspaceRoot;
use async_trait::async_trait;
use origin_domain::Result;
use std::fmt::Debug;
use tokio::sync::broadcast;
pub(crate) const BUFFER_SIZE: usize = 64;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WorkspaceChange {
Created { path: String },
Modified { path: String },
Removed { path: String },
}
impl WorkspaceChange {
pub fn created(path: impl Into<String>) -> Self {
Self::Created { path: path.into() }
}
pub fn modified(path: impl Into<String>) -> Self {
Self::Modified { path: path.into() }
}
pub fn removed(path: impl Into<String>) -> Self {
Self::Removed { path: path.into() }
}
pub fn path(&self) -> &str {
match self {
Self::Created { path } | Self::Modified { path } | Self::Removed { path } => path,
}
}
}
pub struct WatchHandle {
receiver: broadcast::Receiver<WorkspaceChange>,
}
impl Debug for WatchHandle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WatchHandle").finish_non_exhaustive()
}
}
impl WatchHandle {
pub fn new(receiver: broadcast::Receiver<WorkspaceChange>) -> Self {
Self { receiver }
}
pub async fn recv(&mut self) -> Result<WorkspaceChange, broadcast::error::RecvError> {
self.receiver.recv().await
}
pub fn try_recv(&mut self) -> Result<WorkspaceChange, broadcast::error::TryRecvError> {
self.receiver.try_recv()
}
}
#[async_trait]
pub trait WorkspaceWatcher: Debug + Send + Sync + 'static {
async fn watch(&self, root: &WorkspaceRoot) -> Result<WatchHandle>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn workspace_change_path_accessor() {
let change = WorkspaceChange::modified("src/main.rs");
assert_eq!(change.path(), "src/main.rs");
}
}