1mod file;
2mod file_opener;
3mod filesystem;
4mod offloaded_file;
5mod stdio;
6
7use file::{File, FileHandle, ReadOnlyFile};
8pub use filesystem::FileSystem;
9pub use offloaded_file::OffloadBackingStore;
10#[cfg(not(feature = "js"))]
11use std::time::{SystemTime, UNIX_EPOCH};
12pub use stdio::{Stderr, Stdin, Stdout};
13#[cfg(feature = "js")]
14pub use web_time::{SystemTime, UNIX_EPOCH};
15
16use crate::Metadata;
17use std::{
18 ffi::{OsStr, OsString},
19 path::PathBuf,
20 sync::{Arc, Mutex},
21};
22
23use self::offloaded_file::OffloadedFile;
24
25type Inode = usize;
26const ROOT_INODE: Inode = 0;
27
28#[derive(Debug)]
29struct FileNode {
30 inode: Inode,
31 name: OsString,
32 file: File,
33 metadata: Metadata,
34}
35
36#[derive(Debug)]
37struct ReadOnlyFileNode {
38 inode: Inode,
39 name: OsString,
40 file: ReadOnlyFile,
41 metadata: Metadata,
42}
43
44#[derive(Debug)]
45struct OffloadedFileNode {
46 inode: Inode,
47 name: OsString,
48 file: OffloadedFile,
49 metadata: Metadata,
50}
51
52#[derive(Debug)]
53struct ArcFileNode {
54 inode: Inode,
55 name: OsString,
56 fs: Arc<dyn crate::FileSystem + Send + Sync>,
57 path: PathBuf,
58 metadata: Metadata,
59}
60
61#[derive(Debug)]
64struct CustomFileNode {
65 inode: Inode,
66 name: OsString,
67 file: Mutex<Box<dyn crate::VirtualFile + Send + Sync>>,
68 metadata: Metadata,
69}
70
71#[derive(Debug)]
72struct DirectoryNode {
73 inode: Inode,
74 name: OsString,
75 children: Vec<Inode>,
76 metadata: Metadata,
77}
78
79#[derive(Debug)]
80struct ArcDirectoryNode {
81 inode: Inode,
82 name: OsString,
83 fs: Arc<dyn crate::FileSystem + Send + Sync>,
84 path: PathBuf,
85 metadata: Metadata,
86}
87
88#[derive(Debug)]
89struct SymlinkNode {
90 inode: Inode,
91 name: OsString,
92 target: PathBuf,
93 metadata: Metadata,
94}
95
96#[derive(Debug)]
97enum Node {
98 File(FileNode),
99 OffloadedFile(OffloadedFileNode),
100 ReadOnlyFile(ReadOnlyFileNode),
101 ArcFile(ArcFileNode),
102 CustomFile(CustomFileNode),
103 Symlink(SymlinkNode),
104 Directory(DirectoryNode),
105 ArcDirectory(ArcDirectoryNode),
106}
107
108impl Node {
109 fn inode(&self) -> Inode {
110 *match self {
111 Self::File(FileNode { inode, .. }) => inode,
112 Self::OffloadedFile(OffloadedFileNode { inode, .. }) => inode,
113 Self::ReadOnlyFile(ReadOnlyFileNode { inode, .. }) => inode,
114 Self::ArcFile(ArcFileNode { inode, .. }) => inode,
115 Self::CustomFile(CustomFileNode { inode, .. }) => inode,
116 Self::Symlink(SymlinkNode { inode, .. }) => inode,
117 Self::Directory(DirectoryNode { inode, .. }) => inode,
118 Self::ArcDirectory(ArcDirectoryNode { inode, .. }) => inode,
119 }
120 }
121
122 fn name(&self) -> &OsStr {
123 match self {
124 Self::File(FileNode { name, .. }) => name.as_os_str(),
125 Self::OffloadedFile(OffloadedFileNode { name, .. }) => name.as_os_str(),
126 Self::ReadOnlyFile(ReadOnlyFileNode { name, .. }) => name.as_os_str(),
127 Self::ArcFile(ArcFileNode { name, .. }) => name.as_os_str(),
128 Self::CustomFile(CustomFileNode { name, .. }) => name.as_os_str(),
129 Self::Symlink(SymlinkNode { name, .. }) => name.as_os_str(),
130 Self::Directory(DirectoryNode { name, .. }) => name.as_os_str(),
131 Self::ArcDirectory(ArcDirectoryNode { name, .. }) => name.as_os_str(),
132 }
133 }
134
135 fn metadata(&self) -> &Metadata {
136 match self {
137 Self::File(FileNode { metadata, .. }) => metadata,
138 Self::OffloadedFile(OffloadedFileNode { metadata, .. }) => metadata,
139 Self::ReadOnlyFile(ReadOnlyFileNode { metadata, .. }) => metadata,
140 Self::ArcFile(ArcFileNode { metadata, .. }) => metadata,
141 Self::CustomFile(CustomFileNode { metadata, .. }) => metadata,
142 Self::Symlink(SymlinkNode { metadata, .. }) => metadata,
143 Self::Directory(DirectoryNode { metadata, .. }) => metadata,
144 Self::ArcDirectory(ArcDirectoryNode { metadata, .. }) => metadata,
145 }
146 }
147
148 fn metadata_mut(&mut self) -> &mut Metadata {
149 match self {
150 Self::File(FileNode { metadata, .. }) => metadata,
151 Self::OffloadedFile(OffloadedFileNode { metadata, .. }) => metadata,
152 Self::ReadOnlyFile(ReadOnlyFileNode { metadata, .. }) => metadata,
153 Self::ArcFile(ArcFileNode { metadata, .. }) => metadata,
154 Self::CustomFile(CustomFileNode { metadata, .. }) => metadata,
155 Self::Symlink(SymlinkNode { metadata, .. }) => metadata,
156 Self::Directory(DirectoryNode { metadata, .. }) => metadata,
157 Self::ArcDirectory(ArcDirectoryNode { metadata, .. }) => metadata,
158 }
159 }
160
161 fn set_name(&mut self, new_name: OsString) {
162 match self {
163 Self::File(FileNode { name, .. }) => *name = new_name,
164 Self::OffloadedFile(OffloadedFileNode { name, .. }) => *name = new_name,
165 Self::ReadOnlyFile(ReadOnlyFileNode { name, .. }) => *name = new_name,
166 Self::ArcFile(ArcFileNode { name, .. }) => *name = new_name,
167 Self::CustomFile(CustomFileNode { name, .. }) => *name = new_name,
168 Self::Symlink(SymlinkNode { name, .. }) => *name = new_name,
169 Self::Directory(DirectoryNode { name, .. }) => *name = new_name,
170 Self::ArcDirectory(ArcDirectoryNode { name, .. }) => *name = new_name,
171 }
172 }
173}
174
175fn time() -> u64 {
176 SystemTime::now()
179 .duration_since(UNIX_EPOCH)
180 .unwrap()
181 .as_nanos() as u64
182}