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}