Skip to main content

oak_vfs/
lib.rs

1#![feature(new_range_api)]
2#![warn(missing_docs)]
3//! Virtual File System (VFS) for the Oak language framework.
4//!
5//! This crate provides a unified interface for accessing source files,
6//! whether they are stored on disk or in memory, and provides
7//! mapping between line/column positions and byte offsets.
8
9use oak_core::{
10    Arc,
11    source::{Source, SourceId},
12};
13
14mod line_map;
15pub use line_map::LineMap;
16
17/// Type of a file in the VFS.
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub enum FileType {
21    /// A regular file.
22    File,
23    /// A directory.
24    Directory,
25    /// Other file types (e.g., symbolic links, sockets).
26    Other,
27}
28
29/// Metadata for a file or directory in the VFS.
30#[derive(Debug, Clone)]
31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
32pub struct FileMetadata {
33    /// The type of the file.
34    pub file_type: FileType,
35    /// The length of the file in bytes.
36    pub len: u64,
37    /// The last modification time as a Unix timestamp in seconds.
38    pub modified: Option<u64>,
39}
40
41/// Virtual File System implementation and utilities.
42pub mod vfs;
43pub use vfs::MemoryVfs;
44#[cfg(feature = "disk")]
45pub use vfs::{DiskVfs, DiskWatcher, VfsEvent, VfsWatcher};
46
47/// A trait for a Virtual File System that can provide source content and location mapping.
48///
49/// The `Vfs` trait provides a unified abstraction for file system operations,
50/// allowing the core framework to work with files from disk, memory, or network
51/// without being tied to a specific storage backend.
52///
53/// # Usage Scenario
54///
55/// The `Vfs` is typically used to:
56/// 1. Resolve URIs to source content via [`get_source`].
57/// 2. Map between [`SourceId`] and URI strings.
58/// 3. Provide metadata and directory listing for code navigation and discovery.
59/// 4. Manage [`LineMap`]s for translating byte offsets to line/column positions.
60pub trait Vfs: Send + Sync {
61    /// The type of source returned by this VFS.
62    type Source: Source + 'static;
63
64    /// Get the source for the given URI.
65    ///
66    /// # Arguments
67    /// * `uri` - The URI of the file to retrieve.
68    fn get_source(&self, uri: &str) -> Option<Self::Source>;
69
70    /// Get the URI for the given SourceId.
71    ///
72    /// # Arguments
73    /// * `id` - The ID of the source to retrieve the URI for.
74    fn get_uri(&self, id: SourceId) -> Option<Arc<str>>;
75
76    /// Get the SourceId for the given URI.
77    ///
78    /// # Arguments
79    /// * `uri` - The URI to retrieve the ID for.
80    fn get_id(&self, uri: &str) -> Option<SourceId>;
81
82    /// Check if a path exists at the given URI.
83    ///
84    /// # Arguments
85    /// * `uri` - The URI to check for existence.
86    fn exists(&self, uri: &str) -> bool;
87
88    /// Read the metadata for the given URI.
89    ///
90    /// # Arguments
91    /// * `uri` - The URI to retrieve metadata for.
92    fn metadata(&self, uri: &str) -> Option<FileMetadata>;
93
94    /// Read the contents of a directory at the given URI.
95    ///
96    /// # Arguments
97    /// * `uri` - The URI of the directory to read.
98    ///
99    /// # Returns
100    /// A list of URIs or names within the directory.
101    fn read_dir(&self, uri: &str) -> Option<Vec<Arc<str>>>;
102
103    /// Check if the given URI points to a file.
104    fn is_file(&self, uri: &str) -> bool {
105        self.metadata(uri).map(|m| m.file_type == FileType::File).unwrap_or(false)
106    }
107
108    /// Check if the given URI points to a directory.
109    fn is_dir(&self, uri: &str) -> bool {
110        self.metadata(uri).map(|m| m.file_type == FileType::Directory).unwrap_or(false)
111    }
112
113    /// Get a [`LineMap`] for the given URI.
114    ///
115    /// # Arguments
116    /// * `uri` - The URI to get the line map for.
117    fn line_map(&self, uri: &str) -> Option<LineMap> {
118        self.get_source(uri).map(|s| LineMap::from_source(&s))
119    }
120}
121
122/// A trait for a Virtual File System that supports writing.
123pub trait WritableVfs: Vfs {
124    /// Update or create a file with the given content.
125    fn write_file(&self, uri: &str, content: Arc<str>);
126
127    /// Remove a file from the VFS.
128    fn remove_file(&self, uri: &str);
129}