podcasts/
file_system.rs

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        // If the file doesn't exist, it will always be in write mode and not append
80        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}