mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
65 lines
2.1 KiB
Rust
65 lines
2.1 KiB
Rust
use std::{hash::BuildHasherDefault, path::Path, sync::Arc};
|
|
|
|
use dashmap::DashMap;
|
|
use rustc_hash::FxHasher;
|
|
|
|
use crate::{package_json::PackageJson, FileMetadata, FileSystem, ResolveError};
|
|
|
|
pub type PackageJsonCache = DashMap<
|
|
Box<Path>,
|
|
Result<Option<Arc<PackageJson>>, ResolveError>,
|
|
BuildHasherDefault<FxHasher>,
|
|
>;
|
|
|
|
pub struct Cache<Fs> {
|
|
fs: Fs,
|
|
cache: DashMap<Box<Path>, Option<FileMetadata>, BuildHasherDefault<FxHasher>>,
|
|
package_json_cache: PackageJsonCache,
|
|
}
|
|
|
|
impl<Fs: FileSystem> Default for Cache<Fs> {
|
|
fn default() -> Self {
|
|
Self {
|
|
fs: Fs::default(),
|
|
cache: DashMap::default(),
|
|
package_json_cache: DashMap::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<Fs: FileSystem> Cache<Fs> {
|
|
pub fn new(fs: Fs) -> Self {
|
|
Self { fs, ..Self::default() }
|
|
}
|
|
|
|
fn metadata_cached(&self, path: &Path) -> Option<FileMetadata> {
|
|
if let Some(result) = self.cache.get(path) {
|
|
return *result;
|
|
}
|
|
let file_metadata = self.fs.symlink_metadata(path).ok();
|
|
self.cache.insert(path.to_path_buf().into_boxed_path(), file_metadata);
|
|
file_metadata
|
|
}
|
|
|
|
pub fn is_file(&self, path: &Path) -> bool {
|
|
self.metadata_cached(path).is_some_and(|m| m.is_file)
|
|
}
|
|
|
|
/// # Errors
|
|
///
|
|
/// * [ResolveError::JSONError]
|
|
pub fn read_package_json(&self, path: &Path) -> Result<Option<Arc<PackageJson>>, ResolveError> {
|
|
if let Some(result) = self.package_json_cache.get(path) {
|
|
return result.value().clone();
|
|
}
|
|
let Ok(package_json_string) = self.fs.read_to_string(path) else {
|
|
self.package_json_cache.insert(path.to_path_buf().into_boxed_path(), Ok(None));
|
|
return Ok(None);
|
|
};
|
|
let result = PackageJson::parse(path.to_path_buf(), &package_json_string)
|
|
.map(|package_json| Some(Arc::new(package_json)))
|
|
.map_err(|error| ResolveError::from_serde_json_error(path.to_path_buf(), &error));
|
|
self.package_json_cache.insert(path.to_path_buf().into_boxed_path(), result.clone());
|
|
result
|
|
}
|
|
}
|