virtual_filesystem/
file.rs1use std::fs;
2use std::io::{Read, Seek, Write};
3use std::path::PathBuf;
4
5#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7pub enum FileType {
8 Directory,
10 File,
12 Unknown,
14}
15
16impl From<fs::FileType> for FileType {
17 fn from(value: fs::FileType) -> Self {
18 if value.is_dir() {
19 Self::Directory
20 } else if value.is_file() {
21 Self::File
22 } else {
23 Self::Unknown
24 }
25 }
26}
27
28#[derive(Debug, Clone)]
30pub struct DirEntry {
31 pub path: PathBuf,
33 pub metadata: Metadata,
35}
36
37impl DirEntry {
38 pub fn is_directory(&self) -> bool {
40 self.metadata.is_directory()
41 }
42
43 pub fn is_file(&self) -> bool {
45 self.metadata.is_directory()
46 }
47
48 #[allow(clippy::len_without_is_empty)]
50 pub fn len(&self) -> u64 {
51 self.metadata.len()
52 }
53}
54
55#[derive(Debug, Clone, Eq, PartialEq)]
57pub struct Metadata {
58 pub file_type: FileType,
60 pub len: u64,
62}
63
64impl Metadata {
65 pub fn directory() -> Self {
67 Self {
68 file_type: FileType::Directory,
69 len: 0,
70 }
71 }
72
73 pub fn file(len: u64) -> Self {
75 Self {
76 file_type: FileType::File,
77 len,
78 }
79 }
80
81 pub fn is_directory(&self) -> bool {
83 self.file_type == FileType::Directory
84 }
85
86 pub fn is_file(&self) -> bool {
88 self.file_type == FileType::File
89 }
90
91 #[allow(clippy::len_without_is_empty)]
93 pub fn len(&self) -> u64 {
94 self.len
95 }
96}
97
98impl From<fs::Metadata> for Metadata {
99 fn from(value: fs::Metadata) -> Self {
100 let file_type = value.file_type().into();
101 Self {
102 len: if file_type == FileType::Directory { 0 } else { value.len() },
103 file_type,
104 }
105 }
106}
107
108#[derive(Debug)]
110pub struct OpenOptions {
111 pub append: bool,
113 pub create: bool,
115 pub read: bool,
117 pub truncate: bool,
119 pub write: bool,
121}
122
123impl From<&OpenOptions> for fs::OpenOptions {
124 fn from(value: &OpenOptions) -> Self {
125 Self::new()
126 .create(value.create)
127 .append(value.append)
128 .truncate(value.truncate)
129 .read(value.read)
130 .clone()
131 }
132}
133
134impl OpenOptions {
135 pub fn append(mut self, append: bool) -> Self {
140 if append {
141 self.write = true;
142 }
143 self.append = append;
144 self.truncate = !append;
145 self
146 }
147
148 pub fn create(mut self, create: bool) -> Self {
152 if create {
153 self.write = true;
154 }
155 self.create = true;
156 self
157 }
158
159 pub fn read(mut self, read: bool) -> Self {
162 self.read = read;
163 self
164 }
165
166 pub fn truncate(mut self, truncate: bool) -> Self {
171 if truncate {
172 self.write = true;
173 }
174 self.append = !truncate;
175 self.truncate = truncate;
176 self
177 }
178
179 pub fn write(mut self, write: bool) -> Self {
183 self.write = write;
184 self
185 }
186}
187
188impl Default for OpenOptions {
189 fn default() -> Self {
190 Self {
191 append: false,
192 create: false,
193 read: true,
194 truncate: false,
195 write: false,
196 }
197 }
198}
199
200pub trait File: Read + Write + Seek {
202 fn metadata(&self) -> crate::Result<Metadata>;
204
205 fn read_into_vec(&mut self) -> crate::Result<Vec<u8>> {
207 let mut vec = Vec::with_capacity(self.metadata()?.len() as usize);
208 self.read_to_end(&mut vec)?;
209 Ok(vec)
210 }
211
212 fn read_into_string(&mut self) -> crate::Result<String> {
214 let mut str = String::with_capacity(self.metadata()?.len() as usize);
215 self.read_to_string(&mut str)?;
216 Ok(str)
217 }
218}