rolldown_common 1.2.17

This crate is mostly for sharing code between rolldwon crates.
Documentation
use std::{borrow::Borrow, fmt::Display, path::Path, sync::Arc};

use rolldown_std_utils::normalize_path_buf;

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct WatchPath(Arc<Path>);

impl WatchPath {
  pub fn new(path: impl AsRef<Path>, cwd: &Path) -> Self {
    Self(Arc::from(normalize_path_buf(cwd.join(path))))
  }

  #[inline]
  pub fn as_path(&self) -> &Path {
    &self.0
  }
}

impl Borrow<Path> for WatchPath {
  fn borrow(&self) -> &Path {
    self.as_path()
  }
}

impl Display for WatchPath {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    self.as_path().display().fmt(f)
  }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum WatcherChangeKind {
  Create,
  Update,
  Delete,
}

impl Display for WatcherChangeKind {
  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    match self {
      WatcherChangeKind::Create => write!(f, "create"),
      WatcherChangeKind::Update => write!(f, "update"),
      WatcherChangeKind::Delete => write!(f, "delete"),
    }
  }
}

#[cfg(all(test, not(windows)))]
mod tests {
  use super::*;

  #[test]
  fn watch_path() {
    let cwd = Path::new("/project");
    let watch_path = WatchPath::new("src/./pages/../content/", cwd);
    assert_eq!(watch_path.as_path(), Path::new("/project/src/content"));
    assert_eq!(WatchPath::new("/other/dir", cwd).as_path(), Path::new("/other/dir"));

    let watch_paths = rustc_hash::FxHashSet::from_iter([watch_path]);
    let is_watched =
      |path: &str| Path::new(path).ancestors().any(|ancestor| watch_paths.contains(ancestor));
    assert!(is_watched("/project/src/content/nested/index.js"));
    assert!(!is_watched("/project/src/content-other/index.js"));
  }
}