Skip to main content

oak_vfs/
lib.rs

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