1mod memory;
2mod mountable;
3
4#[cfg(feature = "native-fs")]
5mod overlay;
6#[cfg(feature = "native-fs")]
7mod readwrite;
8
9#[cfg(test)]
10mod tests;
11
12#[cfg(all(test, feature = "native-fs"))]
13mod readwrite_tests;
14
15#[cfg(all(test, feature = "native-fs"))]
16mod overlay_tests;
17
18#[cfg(test)]
19mod mountable_tests;
20
21pub use memory::InMemoryFs;
22pub use mountable::MountableFs;
23
24#[cfg(feature = "native-fs")]
25pub use overlay::OverlayFs;
26#[cfg(feature = "native-fs")]
27pub use readwrite::ReadWriteFs;
28
29use crate::error::VfsError;
30use crate::platform::SystemTime;
31use std::path::{Path, PathBuf};
32use std::sync::Arc;
33
34pub(crate) fn vfs_path_is_absolute(path: &Path) -> bool {
38 path.to_str().is_some_and(|s| s.starts_with('/'))
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct Metadata {
44 pub node_type: NodeType,
45 pub size: u64,
46 pub mode: u32,
47 pub mtime: SystemTime,
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub enum NodeType {
53 File,
54 Directory,
55 Symlink,
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct DirEntry {
61 pub name: String,
62 pub node_type: NodeType,
63}
64
65#[derive(Debug, Clone)]
67pub enum FsNode {
68 File {
69 content: Vec<u8>,
70 mode: u32,
71 mtime: SystemTime,
72 },
73 Directory {
74 children: std::collections::BTreeMap<String, FsNode>,
75 mode: u32,
76 mtime: SystemTime,
77 },
78 Symlink {
79 target: PathBuf,
80 mtime: SystemTime,
81 },
82}
83
84#[derive(Debug, Clone, Default)]
86pub struct GlobOptions {
87 pub dotglob: bool,
89 pub nocaseglob: bool,
91 pub globstar: bool,
94 pub extglob: bool,
96}
97
98pub trait VirtualFs: Send + Sync {
103 fn read_file(&self, path: &Path) -> Result<Vec<u8>, VfsError>;
105 fn write_file(&self, path: &Path, content: &[u8]) -> Result<(), VfsError>;
106 fn append_file(&self, path: &Path, content: &[u8]) -> Result<(), VfsError>;
107 fn remove_file(&self, path: &Path) -> Result<(), VfsError>;
108
109 fn mkdir(&self, path: &Path) -> Result<(), VfsError>;
111 fn mkdir_p(&self, path: &Path) -> Result<(), VfsError>;
112 fn readdir(&self, path: &Path) -> Result<Vec<DirEntry>, VfsError>;
113 fn remove_dir(&self, path: &Path) -> Result<(), VfsError>;
114 fn remove_dir_all(&self, path: &Path) -> Result<(), VfsError>;
115
116 fn exists(&self, path: &Path) -> bool;
118 fn stat(&self, path: &Path) -> Result<Metadata, VfsError>;
119 fn lstat(&self, path: &Path) -> Result<Metadata, VfsError>;
120 fn chmod(&self, path: &Path, mode: u32) -> Result<(), VfsError>;
121 fn utimes(&self, path: &Path, mtime: SystemTime) -> Result<(), VfsError>;
122
123 fn symlink(&self, target: &Path, link: &Path) -> Result<(), VfsError>;
125 fn hardlink(&self, src: &Path, dst: &Path) -> Result<(), VfsError>;
126 fn readlink(&self, path: &Path) -> Result<PathBuf, VfsError>;
127
128 fn canonicalize(&self, path: &Path) -> Result<PathBuf, VfsError>;
130
131 fn copy(&self, src: &Path, dst: &Path) -> Result<(), VfsError>;
133 fn rename(&self, src: &Path, dst: &Path) -> Result<(), VfsError>;
134
135 fn glob(&self, pattern: &str, cwd: &Path) -> Result<Vec<PathBuf>, VfsError>;
137
138 fn glob_with_opts(
143 &self,
144 pattern: &str,
145 cwd: &Path,
146 _opts: &GlobOptions,
147 ) -> Result<Vec<PathBuf>, VfsError> {
148 self.glob(pattern, cwd)
149 }
150
151 fn deep_clone(&self) -> Arc<dyn VirtualFs>;
161}