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)]
89enum Node {
90 File(FileNode),
91 OffloadedFile(OffloadedFileNode),
92 ReadOnlyFile(ReadOnlyFileNode),
93 ArcFile(ArcFileNode),
94 CustomFile(CustomFileNode),
95 Directory(DirectoryNode),
96 ArcDirectory(ArcDirectoryNode),
97}
98
99impl Node {
100 fn inode(&self) -> Inode {
101 *match self {
102 Self::File(FileNode { inode, .. }) => inode,
103 Self::OffloadedFile(OffloadedFileNode { inode, .. }) => inode,
104 Self::ReadOnlyFile(ReadOnlyFileNode { inode, .. }) => inode,
105 Self::ArcFile(ArcFileNode { inode, .. }) => inode,
106 Self::CustomFile(CustomFileNode { inode, .. }) => inode,
107 Self::Directory(DirectoryNode { inode, .. }) => inode,
108 Self::ArcDirectory(ArcDirectoryNode { inode, .. }) => inode,
109 }
110 }
111
112 fn name(&self) -> &OsStr {
113 match self {
114 Self::File(FileNode { name, .. }) => name.as_os_str(),
115 Self::OffloadedFile(OffloadedFileNode { name, .. }) => name.as_os_str(),
116 Self::ReadOnlyFile(ReadOnlyFileNode { name, .. }) => name.as_os_str(),
117 Self::ArcFile(ArcFileNode { name, .. }) => name.as_os_str(),
118 Self::CustomFile(CustomFileNode { name, .. }) => name.as_os_str(),
119 Self::Directory(DirectoryNode { name, .. }) => name.as_os_str(),
120 Self::ArcDirectory(ArcDirectoryNode { name, .. }) => name.as_os_str(),
121 }
122 }
123
124 fn metadata(&self) -> &Metadata {
125 match self {
126 Self::File(FileNode { metadata, .. }) => metadata,
127 Self::OffloadedFile(OffloadedFileNode { metadata, .. }) => metadata,
128 Self::ReadOnlyFile(ReadOnlyFileNode { metadata, .. }) => metadata,
129 Self::ArcFile(ArcFileNode { metadata, .. }) => metadata,
130 Self::CustomFile(CustomFileNode { metadata, .. }) => metadata,
131 Self::Directory(DirectoryNode { metadata, .. }) => metadata,
132 Self::ArcDirectory(ArcDirectoryNode { metadata, .. }) => metadata,
133 }
134 }
135
136 fn metadata_mut(&mut self) -> &mut Metadata {
137 match self {
138 Self::File(FileNode { metadata, .. }) => metadata,
139 Self::OffloadedFile(OffloadedFileNode { metadata, .. }) => metadata,
140 Self::ReadOnlyFile(ReadOnlyFileNode { metadata, .. }) => metadata,
141 Self::ArcFile(ArcFileNode { metadata, .. }) => metadata,
142 Self::CustomFile(CustomFileNode { metadata, .. }) => metadata,
143 Self::Directory(DirectoryNode { metadata, .. }) => metadata,
144 Self::ArcDirectory(ArcDirectoryNode { metadata, .. }) => metadata,
145 }
146 }
147
148 fn set_name(&mut self, new_name: OsString) {
149 match self {
150 Self::File(FileNode { name, .. }) => *name = new_name,
151 Self::OffloadedFile(OffloadedFileNode { name, .. }) => *name = new_name,
152 Self::ReadOnlyFile(ReadOnlyFileNode { name, .. }) => *name = new_name,
153 Self::ArcFile(ArcFileNode { name, .. }) => *name = new_name,
154 Self::CustomFile(CustomFileNode { name, .. }) => *name = new_name,
155 Self::Directory(DirectoryNode { name, .. }) => *name = new_name,
156 Self::ArcDirectory(ArcDirectoryNode { name, .. }) => *name = new_name,
157 }
158 }
159}
160
161fn time() -> u64 {
162 SystemTime::now()
165 .duration_since(UNIX_EPOCH)
166 .unwrap()
167 .as_nanos() as u64
168}