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}