bias_vfs/impls/
altroot.rs1use crate::{
4 error::VfsErrorKind, FileSystem, SeekAndRead, SeekAndWrite, VfsMetadata, VfsPath, VfsResult,
5};
6
7use std::path::PathBuf;
8use std::time::SystemTime;
9
10#[derive(Debug, Clone)]
17pub struct AltrootFS {
18 root: VfsPath,
19}
20
21impl AltrootFS {
22 pub fn new(root: VfsPath) -> Self {
24 AltrootFS { root }
25 }
26}
27
28impl AltrootFS {
29 #[allow(clippy::manual_strip)] fn path(&self, path: &str) -> VfsResult<VfsPath> {
31 if path.is_empty() {
32 return Ok(self.root.clone());
33 }
34 if path.starts_with('/') {
35 return self.root.join(&path[1..]);
36 }
37 self.root.join(path)
38 }
39}
40
41impl FileSystem for AltrootFS {
42 fn read_dir(&self, path: &str) -> VfsResult<Box<dyn Iterator<Item = String> + Send>> {
43 self.path(path)?
44 .read_dir()
45 .map(|result| result.map(|path| path.filename()))
46 .map(|entries| Box::new(entries) as Box<dyn Iterator<Item = String> + Send>)
47 }
48
49 fn create_dir(&self, path: &str) -> VfsResult<()> {
50 self.path(path)?.create_dir()
51 }
52
53 fn open_file(&self, path: &str) -> VfsResult<Box<dyn SeekAndRead + Send>> {
54 self.path(path)?.open_file()
55 }
56
57 fn create_file(&self, path: &str) -> VfsResult<Box<dyn SeekAndWrite + Send>> {
58 self.path(path)?.create_file()
59 }
60
61 fn append_file(&self, path: &str) -> VfsResult<Box<dyn SeekAndWrite + Send>> {
62 self.path(path)?.append_file()
63 }
64
65 fn metadata(&self, path: &str) -> VfsResult<VfsMetadata> {
66 self.path(path)?.metadata()
67 }
68
69 fn set_creation_time(&self, path: &str, time: SystemTime) -> VfsResult<()> {
70 self.path(path)?.set_creation_time(time)
71 }
72
73 fn set_modification_time(&self, path: &str, time: SystemTime) -> VfsResult<()> {
74 self.path(path)?.set_modification_time(time)
75 }
76
77 fn set_access_time(&self, path: &str, time: SystemTime) -> VfsResult<()> {
78 self.path(path)?.set_access_time(time)
79 }
80
81 fn exists(&self, path: &str) -> VfsResult<bool> {
82 self.path(path)
83 .map(|path| path.exists())
84 .unwrap_or(Ok(false))
85 }
86
87 fn remove_file(&self, path: &str) -> VfsResult<()> {
88 self.path(path)?.remove_file()
89 }
90
91 fn remove_dir(&self, path: &str) -> VfsResult<()> {
92 self.path(path)?.remove_dir()
93 }
94
95 fn copy_file(&self, src: &str, dest: &str) -> VfsResult<()> {
96 if dest.is_empty() {
97 return Err(VfsErrorKind::NotSupported.into());
98 }
99 self.path(src)?.copy_file(&self.path(dest)?)
100 }
101
102 fn real_path(&self, path: &str) -> VfsResult<PathBuf> {
103 self.root.filesystem().real_path(path)
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110 use crate::MemoryFS;
111 test_vfs!({
112 let memory_root: VfsPath = MemoryFS::new().into();
113 let altroot_path = memory_root.join("altroot").unwrap();
114 altroot_path.create_dir().unwrap();
115 AltrootFS::new(altroot_path)
116 });
117
118 #[test]
119 fn parent() {
120 let memory_root: VfsPath = MemoryFS::new().into();
121 let altroot_path = memory_root.join("altroot").unwrap();
122 altroot_path.create_dir().unwrap();
123 let altroot: VfsPath = AltrootFS::new(altroot_path.clone()).into();
124 assert_eq!(altroot.parent(), altroot.root());
125 assert_eq!(altroot_path.parent(), memory_root);
126 }
127}
128
129#[cfg(test)]
130mod tests_physical {
131 use super::*;
132 use crate::PhysicalFS;
133 test_vfs!({
134 let temp_dir = std::env::temp_dir();
135 let dir = temp_dir.join(uuid::Uuid::new_v4().to_string());
136 std::fs::create_dir_all(&dir).unwrap();
137
138 let physical_root: VfsPath = PhysicalFS::new(dir).into();
139 let altroot_path = physical_root.join("altroot").unwrap();
140 altroot_path.create_dir().unwrap();
141 AltrootFS::new(altroot_path)
142 });
143
144 test_vfs_readonly!({
145 let physical_root: VfsPath = PhysicalFS::new("test").into();
146 let altroot_path = physical_root.join("test_directory").unwrap();
147 AltrootFS::new(altroot_path)
148 });
149}