1use std::{
4 collections::{HashMap, HashSet},
5 fs, io,
6 path::PathBuf,
7};
8
9use log::debug;
10
11use crate::io::FsIo;
12
13pub fn handle(input: FsIo) -> io::Result<FsIo> {
18 match input {
19 FsIo::CreateDir(input) => create_dir(input),
20 FsIo::CreateDirs(input) => create_dirs(input),
21 FsIo::CreateFile(input) => create_file(input),
22 FsIo::CreateFiles(input) => create_files(input),
23 FsIo::ReadDir(input) => read_dir(input),
24 FsIo::ReadFile(input) => read_file(input),
25 FsIo::ReadFiles(input) => read_files(input),
26 FsIo::RemoveDir(input) => remove_dir(input),
27 FsIo::RemoveDirs(input) => remove_dirs(input),
28 FsIo::RemoveFile(input) => remove_file(input),
29 FsIo::RemoveFiles(input) => remove_files(input),
30 FsIo::Rename(input) => rename(input),
31 }
32}
33
34pub fn create_dir(input: Result<(), PathBuf>) -> io::Result<FsIo> {
35 let Err(path) = input else {
36 let kind = io::ErrorKind::InvalidInput;
37 return Err(io::Error::new(kind, "missing directory path"));
38 };
39
40 fs::create_dir(path)?;
41
42 Ok(FsIo::CreateDir(Ok(())))
43}
44
45pub fn create_dirs(input: Result<(), HashSet<PathBuf>>) -> io::Result<FsIo> {
46 let Err(paths) = input else {
47 let kind = io::ErrorKind::InvalidInput;
48 return Err(io::Error::new(kind, "missing directory paths"));
49 };
50
51 for path in paths {
52 fs::create_dir(path)?;
53 }
54
55 Ok(FsIo::CreateDirs(Ok(())))
56}
57
58pub fn create_file(input: Result<(), (PathBuf, Vec<u8>)>) -> io::Result<FsIo> {
59 let Err((path, contents)) = input else {
60 let kind = io::ErrorKind::InvalidInput;
61 return Err(io::Error::new(kind, "missing file contents"));
62 };
63
64 fs::write(path, contents)?;
65
66 Ok(FsIo::CreateFile(Ok(())))
67}
68
69pub fn create_files(input: Result<(), HashMap<PathBuf, Vec<u8>>>) -> io::Result<FsIo> {
70 let Err(contents) = input else {
71 let kind = io::ErrorKind::InvalidInput;
72 return Err(io::Error::new(kind, "missing file contents"));
73 };
74
75 for (path, contents) in contents {
76 fs::write(path, contents)?;
77 }
78
79 Ok(FsIo::CreateFiles(Ok(())))
80}
81
82pub fn read_dir(input: Result<HashSet<PathBuf>, PathBuf>) -> io::Result<FsIo> {
83 let Err(path) = input else {
84 let kind = io::ErrorKind::InvalidInput;
85 return Err(io::Error::new(kind, "missing directory path"));
86 };
87
88 let mut paths = HashSet::new();
89 let dir = fs::read_dir(path)?;
90
91 for entry in dir {
92 match entry {
93 Ok(entry) => {
94 paths.insert(entry.path());
95 }
96 Err(err) => {
97 debug!("ignore invalid directory entry: {err}");
98 continue;
99 }
100 };
101 }
102
103 Ok(FsIo::ReadDir(Ok(paths)))
104}
105
106pub fn read_file(input: Result<Vec<u8>, PathBuf>) -> io::Result<FsIo> {
107 let Err(path) = input else {
108 let kind = io::ErrorKind::InvalidInput;
109 return Err(io::Error::new(kind, "missing file path"));
110 };
111
112 let contents = fs::read(path)?;
113
114 Ok(FsIo::ReadFile(Ok(contents)))
115}
116
117pub fn read_files(input: Result<HashMap<PathBuf, Vec<u8>>, HashSet<PathBuf>>) -> io::Result<FsIo> {
118 let Err(paths) = input else {
119 let kind = io::ErrorKind::InvalidInput;
120 return Err(io::Error::new(kind, "missing file paths"));
121 };
122
123 let mut contents = HashMap::new();
124
125 for path in paths {
126 let content = fs::read(&path)?;
127 contents.insert(path, content);
128 }
129
130 Ok(FsIo::ReadFiles(Ok(contents)))
131}
132
133pub fn remove_dir(input: Result<(), PathBuf>) -> io::Result<FsIo> {
134 let Err(path) = input else {
135 let kind = io::ErrorKind::InvalidInput;
136 return Err(io::Error::new(kind, "missing directory path"));
137 };
138
139 fs::remove_dir_all(path)?;
140
141 Ok(FsIo::RemoveDir(Ok(())))
142}
143
144pub fn remove_dirs(input: Result<(), HashSet<PathBuf>>) -> io::Result<FsIo> {
145 let Err(paths) = input else {
146 let kind = io::ErrorKind::InvalidInput;
147 return Err(io::Error::new(kind, "missing directory paths"));
148 };
149
150 for path in paths {
151 fs::remove_dir_all(path)?;
152 }
153
154 Ok(FsIo::RemoveDirs(Ok(())))
155}
156
157pub fn remove_file(input: Result<(), PathBuf>) -> io::Result<FsIo> {
158 let Err(path) = input else {
159 let kind = io::ErrorKind::InvalidInput;
160 return Err(io::Error::new(kind, "missing file path"));
161 };
162
163 fs::remove_file(path)?;
164
165 Ok(FsIo::RemoveFile(Ok(())))
166}
167
168pub fn remove_files(input: Result<(), HashSet<PathBuf>>) -> io::Result<FsIo> {
169 let Err(paths) = input else {
170 let kind = io::ErrorKind::InvalidInput;
171 return Err(io::Error::new(kind, "missing file paths"));
172 };
173
174 for path in paths {
175 fs::remove_file(path)?;
176 }
177
178 Ok(FsIo::RemoveFiles(Ok(())))
179}
180
181pub fn rename(input: Result<(), Vec<(PathBuf, PathBuf)>>) -> io::Result<FsIo> {
182 let Err(paths) = input else {
183 let kind = io::ErrorKind::InvalidInput;
184 return Err(io::Error::new(kind, "missing file paths"));
185 };
186
187 for (from, to) in paths {
188 fs::rename(from, to)?;
189 }
190
191 Ok(FsIo::Rename(Ok(())))
192}