1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use crate::{FileSystem, SeekAndRead, VfsError, VfsMetadata, VfsPath, VfsResult};
use std::io::Write;
#[derive(Debug, Clone)]
pub struct AltrootFS {
root: VfsPath,
}
impl AltrootFS {
pub fn new(root: VfsPath) -> Self {
AltrootFS { root }
}
}
impl AltrootFS {
fn path(&self, path: &str) -> VfsResult<VfsPath> {
if path.is_empty() {
return Ok(self.root.clone());
}
if path.starts_with('/') {
return self.root.join(&path[1..]);
}
self.root.join(&path)
}
}
impl FileSystem for AltrootFS {
fn read_dir(&self, path: &str) -> VfsResult<Box<dyn Iterator<Item = String>>> {
self.path(path)?
.read_dir()
.map(|result| result.map(|path| path.filename()))
.map(|entries| Box::new(entries) as Box<dyn Iterator<Item = String>>)
}
fn create_dir(&self, path: &str) -> VfsResult<()> {
self.path(path)?.create_dir()
}
fn open_file(&self, path: &str) -> VfsResult<Box<dyn SeekAndRead>> {
self.path(path)?.open_file()
}
fn create_file(&self, path: &str) -> VfsResult<Box<dyn Write>> {
self.path(path)?.create_file()
}
fn append_file(&self, path: &str) -> VfsResult<Box<dyn Write>> {
self.path(path)?.append_file()
}
fn metadata(&self, path: &str) -> VfsResult<VfsMetadata> {
self.path(path)?.metadata()
}
fn exists(&self, path: &str) -> bool {
self.path(path).map(|path| path.exists()).unwrap_or(false)
}
fn remove_file(&self, path: &str) -> VfsResult<()> {
self.path(path)?.remove_file()
}
fn remove_dir(&self, path: &str) -> VfsResult<()> {
self.path(path)?.remove_dir()
}
fn copy_file(&self, src: &str, dest: &str) -> VfsResult<()> {
if dest.is_empty() {
return Err(VfsError::NotSupported);
}
self.path(src)?.copy_file(&self.path(dest)?)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MemoryFS;
test_vfs!({
let memory_root: VfsPath = MemoryFS::new().into();
let altroot_path = memory_root.join("altroot").unwrap();
altroot_path.create_dir().unwrap();
AltrootFS::new(altroot_path)
});
#[test]
fn parent() {
let memory_root: VfsPath = MemoryFS::new().into();
let altroot_path = memory_root.join("altroot").unwrap();
altroot_path.create_dir().unwrap();
let altroot: VfsPath = AltrootFS::new(altroot_path.clone()).into();
assert_eq!(altroot.parent(), None);
assert_eq!(altroot_path.parent(), Some(memory_root));
}
}
#[cfg(test)]
mod tests_physical {
use super::*;
use crate::PhysicalFS;
test_vfs!({
let temp_dir = std::env::temp_dir();
let dir = temp_dir.join(uuid::Uuid::new_v4().to_string());
std::fs::create_dir_all(&dir).unwrap();
let physical_root: VfsPath = PhysicalFS::new(dir).into();
let altroot_path = physical_root.join("altroot").unwrap();
altroot_path.create_dir().unwrap();
AltrootFS::new(altroot_path)
});
}