grace_cli/core/file/
file.rs1use std::fs;
2use std::path::Path;
3use std::vec::Vec;
4use thiserror::Error;
5
6#[derive(Error, Debug, PartialEq)]
8pub enum FileErr {
9 #[error("Provided path is not a directory")]
10 NotADirectory,
11 #[error("Provided path is not a file")]
12 NotAFile,
13 #[error("File already exists")]
14 FileAlreadyExist,
15 #[error("File does not exist")]
16 FileDoesNotExist,
17 #[error("Directory does not exist")]
18 DirectoryDoesNotExist,
19 #[error("Failed to read directory: {0}")]
20 ReadDirError(String),
21 #[error("Failed to rename file: {0}")]
22 RenameError(String),
23 #[error("Failed to create file: {0}")]
24 CreateFileError(String),
25 #[error("I/O error: {0}")]
26 IoError(String),
27}
28
29pub struct File<'a> {
32 path: &'a Path,
33}
34
35impl File<'_> {
36 pub fn new(path_str: &str) -> File<'_> {
38 File {
39 path: Path::new(path_str),
40 }
41 }
42
43 pub fn extension(&self) -> Option<String> {
45 self.path.extension().map(|os_str| {
46 os_str
47 .to_str()
48 .map(|str| str.to_string())
49 .unwrap_or("".to_string())
50 })
51 }
52
53 pub fn file_name(&self) -> Option<String> {
55 self.path.file_name().map(|os_str| {
56 os_str
57 .to_str()
58 .map(|str| str.to_string())
59 .unwrap_or("".to_string())
60 })
61 }
62
63 pub fn file_stem(&self) -> Option<String> {
65 self.path.file_stem().map(|os_str| {
66 os_str
67 .to_str()
68 .map(|str| str.to_string())
69 .unwrap_or("".to_string())
70 })
71 }
72
73 pub fn is_dir(&self) -> bool {
75 self.path.is_dir()
76 }
77
78 pub fn is_file(&self) -> bool {
80 self.path.is_file()
81 }
82
83 pub fn exist(&self) -> bool {
85 self.path.exists()
86 }
87
88 pub fn read_dir(&self) -> Result<Vec<String>, FileErr> {
91 if !self.is_dir() {
92 return Err(FileErr::NotADirectory);
93 }
94
95 let paths = fs::read_dir(self.path).map_err(|e| FileErr::ReadDirError(e.to_string()))?;
96
97 let files_in_dir: Result<Vec<String>, FileErr> = paths
98 .map(|entry| {
99 entry
100 .map_err(|e| FileErr::ReadDirError(e.to_string()))
101 .and_then(|e| {
102 e.file_name()
103 .into_string()
104 .map_err(|_| FileErr::IoError("Invalid UTF-8 in filename".to_string()))
105 })
106 })
107 .collect();
108
109 files_in_dir
110 }
111
112 pub fn create_file(&self) -> Result<(), FileErr> {
114 if self.exist() {
115 return Err(FileErr::FileAlreadyExist);
116 }
117
118 fs::File::create(self.path)
119 .map(|_| ())
120 .map_err(|e| FileErr::CreateFileError(e.to_string()))
121 }
122
123 pub fn rename(&self, new_name: &str) -> Result<(), FileErr> {
125 let new_path = self.path.with_file_name(new_name);
126 fs::rename(self.path, new_path).map_err(|e| FileErr::RenameError(e.to_string()))
127 }
128
129 pub fn path(&self) -> String {
130 self.path.to_str().unwrap().to_string()
131 }
132}