Skip to content

Commit

Permalink
dev(compiler): add comments to vfs interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
Myriad-Dreamin committed Nov 11, 2023
1 parent a0dc8b5 commit 2c6c22f
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 149 deletions.
8 changes: 8 additions & 0 deletions compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@
//! - [`service::CompileDriver`]: A driver for the compiler. Examples:
//! - Single thread (Sync): <https://github.com/Myriad-Dreamin/typst.ts/blob/main/cli/src/main.rs>
//! - Multiple thread (Async): <https://github.com/Enter-tainer/typst-preview-vscode/blob/main/src/main.rs>
// #![warn(missing_docs)]
// #![warn(clippy::missing_docs_in_private_items)]
// #![warn(clippy::missing_errors_doc)]
// #![warn(clippy::missing_panics_doc)]
// #![warn(clippy::missing_safety_doc)]
// #![warn(clippy::undocumented_unsafe_blocks)]
// #![warn(missing_crate_level_docs)]
// #![warn(clippy::host_endian_bytes)]
// #![warn(missing_debug_implementations)]
// #![warn(missing_copy_implementations)]

Expand Down
8 changes: 8 additions & 0 deletions compiler/src/vfs/browser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,20 @@ use crate::time::SystemTime;

use super::AccessModel;

/// Provides proxy access model from typst compiler to some JavaScript
/// implementation.
#[derive(Debug)]
pub struct ProxyAccessModel {
/// The `this` value when calling the JavaScript functions
pub context: JsValue,
/// The JavaScript function to get the mtime of a file
pub mtime_fn: js_sys::Function,
/// The JavaScript function to check if a path corresponds to a file or a
/// directory
pub is_file_fn: js_sys::Function,
/// The JavaScript function to get the real path of a file
pub real_path_fn: js_sys::Function,
/// The JavaScript function to get the content of a file
pub read_all_fn: js_sys::Function,
}

Expand Down
44 changes: 31 additions & 13 deletions compiler/src/vfs/cached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,51 @@ use super::AccessModel;
/// incrementally query a value from a self holding state
type IncrQueryRef<S, E> = QueryRef<S, E, Option<S>>;

/// Holds the cached data of a single file
#[derive(Debug)]
pub struct FileCache<S> {
lifetime_cnt: usize,
pub struct CacheEntry<S> {
/// The last lifetime count when the cache is updated
last_access_lifetime: usize,
/// The cached mtime of the file
mtime: SystemTime,
/// Whether the file is a file, lazily triggered when mtime is changed
is_file: QueryRef<bool, FileError>,
/// The content of the file, lazily triggered when mtime is changed
read_all: QueryRef<Bytes, FileError>,
/// The incremental state of the source, lazily triggered when mtime is
/// changed
source_state: IncrQueryRef<S, FileError>,
}

/// Provides general cache to file access.
#[derive(Debug)]
pub struct CachedAccessModel<Inner: AccessModel, C> {
/// The underlying access model for real file access
inner: Inner,
/// The lifetime count which resembles [`crate::vfs::Vfs::lifetime_cnt`]
///
/// Note: The lifetime counter is incremented on resetting vfs.
lifetime_cnt: usize,
path_results: RwLock<HashMap<Arc<OsStr>, FileCache<C>>>,
/// The cache entries for each paths
cache_entries: RwLock<HashMap<Arc<OsStr>, CacheEntry<C>>>,
}

impl<Inner: AccessModel, C> CachedAccessModel<Inner, C> {
/// Create a new [`CachedAccessModel`] with the given inner access model
pub fn new(inner: Inner) -> Self {
CachedAccessModel {
inner,
lifetime_cnt: 0,
path_results: RwLock::new(HashMap::new()),
lifetime_cnt: 1,
cache_entries: RwLock::new(HashMap::new()),
}
}

/// Get the inner access model
pub fn inner(&self) -> &Inner {
&self.inner
}

/// Get the mutable reference to the inner access model
pub fn inner_mut(&mut self) -> &mut Inner {
&mut self.inner
}
Expand All @@ -54,13 +70,13 @@ impl<Inner: AccessModel, C: Clone> CachedAccessModel<Inner, C> {
fn cache_entry<T>(
&self,
src: &Path,
cb: impl FnOnce(&FileCache<C>) -> FileResult<T>,
cb: impl FnOnce(&CacheEntry<C>) -> FileResult<T>,
) -> FileResult<T> {
let path_key = src.as_os_str();
let path_results = self.path_results.upgradable_read();
let path_results = self.cache_entries.upgradable_read();
let entry = path_results.get(path_key);
let (new_mtime, prev_to_diff) = if let Some(entry) = entry {
if entry.lifetime_cnt == self.lifetime_cnt {
if entry.last_access_lifetime == self.lifetime_cnt {
return cb(entry);
}

Expand All @@ -85,8 +101,8 @@ impl<Inner: AccessModel, C: Clone> CachedAccessModel<Inner, C> {

path_results.insert(
path_key.into(),
FileCache {
lifetime_cnt: self.lifetime_cnt,
CacheEntry {
last_access_lifetime: self.lifetime_cnt,
mtime: new_mtime,
is_file: QueryRef::default(),
read_all: QueryRef::default(),
Expand All @@ -95,12 +111,14 @@ impl<Inner: AccessModel, C: Clone> CachedAccessModel<Inner, C> {
);

drop(path_results);
let path_results = self.path_results.read();
let path_results = self.cache_entries.read();
cb(path_results.get(path_key).unwrap())
}
}

impl<Inner: AccessModel, C: Clone> CachedAccessModel<Inner, C> {
/// This is not a common interface for access model, but it is used for vfs
/// incremental parsing.
pub fn read_all_diff(
&self,
src: &Path,
Expand All @@ -127,9 +145,9 @@ impl<Inner: AccessModel, C: Clone> AccessModel for CachedAccessModel<Inner, C> {
fn clear(&mut self) {
self.lifetime_cnt += 1;

let mut path_results = self.path_results.write();
let mut path_results = self.cache_entries.write();
let new_lifetime = self.lifetime_cnt;
path_results.retain(|_, v| new_lifetime - v.lifetime_cnt <= 30);
path_results.retain(|_, v| new_lifetime - v.last_access_lifetime <= 30);
}

fn mtime(&self, src: &Path) -> FileResult<SystemTime> {
Expand Down
5 changes: 5 additions & 0 deletions compiler/src/vfs/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ use crate::time::SystemTime;

use super::AccessModel;

/// Provides dummy access model.
///
/// Note: we can still perform compilation with dummy access model, since
/// [`Vfs`] will make a overlay access model over the provided dummy access
/// model.
#[derive(Default, Debug, Clone, Copy)]
pub struct DummyAccessModel;

Expand Down
Loading

0 comments on commit 2c6c22f

Please sign in to comment.