1use std::{fmt, fs, io, path::Path};
2
3#[derive(Debug)]
4pub enum FileSystemErrors {
5 CreateDirectory(io::Error),
6 CreateFile(io::Error),
7 Rename(io::Error),
8 Remove(io::Error),
9}
10
11impl fmt::Display for FileSystemErrors {
12 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
13 let message = match self {
14 FileSystemErrors::CreateDirectory(error) => format!("Can't create directory. {}", error),
15 FileSystemErrors::CreateFile(error) => format!("Can't create file. {}", error),
16 FileSystemErrors::Rename(error) => format!("Can't rename file, {}", error),
17 FileSystemErrors::Remove(error) => format!("Can't remove file. {}", error),
18 };
19
20 write!(f, "{}", message)
21 }
22}
23
24#[derive(Debug, PartialEq)]
25pub enum FilePermissions {
26 Read,
27 Write,
28 WriteTruncate,
29 Append,
30}
31
32pub struct FileSystem<'a, 'b> {
33 directory: &'a Path,
34 file_name: &'b str,
35 permissions: Vec<FilePermissions>,
36}
37
38impl<'a, 'b> FileSystem<'a, 'b> {
39 pub fn new(directory: &'a Path, file_name: &'b str, permissions: Vec<FilePermissions>) -> Self {
40 Self {
41 directory,
42 file_name,
43 permissions,
44 }
45 }
46
47 pub fn open(&self) -> Result<fs::File, FileSystemErrors> {
48 let file_path = format!("{}/{}", self.directory.display(), self.file_name);
49 let mut file = fs::OpenOptions::new();
50
51 for permission in &self.permissions {
52 if *permission == FilePermissions::Read {
53 file.read(true);
54 }
55
56 if *permission == FilePermissions::Write {
57 file.write(true);
58 }
59
60 if *permission == FilePermissions::WriteTruncate {
61 file.write(true);
62 file.truncate(true);
63 }
64
65 if *permission == FilePermissions::Append {
66 file.append(true);
67 }
68 }
69
70 if let Ok(file) = file.open(&file_path) {
71 return Ok(file);
72 }
73
74 let directory = fs::create_dir_all(self.directory);
75 if let Err(err) = directory {
76 return Err(FileSystemErrors::CreateDirectory(err));
77 }
78
79 fs::OpenOptions::new()
81 .create(true)
82 .read(true)
83 .write(true)
84 .open(&file_path)
85 .map_err(|error| FileSystemErrors::CreateFile(error))
86 }
87
88 #[allow(dead_code)]
89 pub fn rename(&mut self, new_name: &'static str) -> Result<(), FileSystemErrors> {
90 let old_path = format!("{}/{}", self.directory.display(), self.file_name);
91 let new_path = format!("{}/{}", self.directory.display(), new_name);
92
93 return match fs::rename(old_path, new_path) {
94 Ok(_) => {
95 self.file_name = new_name;
96 Ok(())
97 }
98 Err(error) => Err(FileSystemErrors::Rename(error)),
99 };
100 }
101
102 #[allow(dead_code)]
103 pub fn remove(self) -> Result<(), FileSystemErrors> {
104 let path = format!("{}/{}", self.directory.display(), self.file_name);
105
106 fs::remove_file(path).map_err(|error| FileSystemErrors::Remove(error))
107 }
108}