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 Self {
101 file_type: value.file_type().into(),
102 len: value.len(),
103 }
104 }
105}
106
107#[derive(Debug)]
109pub struct OpenOptions {
110 pub append: bool,
112 pub create: bool,
114 pub read: bool,
116 pub truncate: bool,
118 pub write: bool,
120}
121
122impl From<&OpenOptions> for fs::OpenOptions {
123 fn from(value: &OpenOptions) -> Self {
124 Self::new()
125 .create(value.create)
126 .append(value.append)
127 .truncate(value.truncate)
128 .read(value.read)
129 .clone()
130 }
131}
132
133impl OpenOptions {
134 pub fn append(mut self, append: bool) -> Self {
139 if append {
140 self.write = true;
141 }
142 self.append = append;
143 self.truncate = !append;
144 self
145 }
146
147 pub fn create(mut self, create: bool) -> Self {
151 if create {
152 self.write = true;
153 }
154 self.create = true;
155 self
156 }
157
158 pub fn read(mut self, read: bool) -> Self {
161 self.read = read;
162 self
163 }
164
165 pub fn truncate(mut self, truncate: bool) -> Self {
170 if truncate {
171 self.write = true;
172 }
173 self.append = !truncate;
174 self.truncate = truncate;
175 self
176 }
177
178 pub fn write(mut self, write: bool) -> Self {
182 self.write = write;
183 self
184 }
185}
186
187impl Default for OpenOptions {
188 fn default() -> Self {
189 Self {
190 append: false,
191 create: false,
192 read: true,
193 truncate: false,
194 write: false,
195 }
196 }
197}
198
199pub trait File: Read + Write + Seek {
201 fn metadata(&self) -> crate::Result<Metadata>;
203
204 fn read_into_vec(&mut self) -> crate::Result<Vec<u8>> {
206 let mut vec = Vec::with_capacity(self.metadata()?.len() as usize);
207 self.read_to_end(&mut vec)?;
208 Ok(vec)
209 }
210
211 fn read_into_string(&mut self) -> crate::Result<String> {
213 let mut str = String::with_capacity(self.metadata()?.len() as usize);
214 self.read_to_string(&mut str)?;
215 Ok(str)
216 }
217}