1use std::fs::File;
6use std::io::{BufRead, BufReader, BufWriter, Read, Write};
7use std::path::Path;
8
9use crate::error::CoreResult;
10
11#[allow(dead_code)]
25pub fn open_file<P: AsRef<Path>>(path: P) -> CoreResult<BufReader<File>> {
26 let file = File::open(path.as_ref())?;
27 Ok(BufReader::new(file))
28}
29
30#[allow(dead_code)]
44pub fn create_file<P: AsRef<Path>>(path: P) -> CoreResult<BufWriter<File>> {
45 let file = File::create(path.as_ref())?;
46 Ok(BufWriter::new(file))
47}
48
49#[allow(dead_code)]
63pub fn read_to_string<P: AsRef<Path>>(path: P) -> CoreResult<String> {
64 let mut file = open_file(path)?;
65 let mut contents = String::new();
66 file.read_to_string(&mut contents)?;
67 Ok(contents)
68}
69
70#[allow(dead_code)]
84pub fn read_to_bytes<P: AsRef<Path>>(path: P) -> CoreResult<Vec<u8>> {
85 let mut file = open_file(path)?;
86 let mut contents = Vec::new();
87 file.read_to_end(&mut contents)?;
88 Ok(contents)
89}
90
91#[allow(dead_code)]
103pub fn write_string<P: AsRef<Path>, S: AsRef<str>>(path: P, contents: S) -> CoreResult<()> {
104 let mut file = create_file(path)?;
105 file.write_all(contents.as_ref().as_bytes())?;
106 file.flush()?;
107 Ok(())
108}
109
110#[allow(dead_code)]
122pub fn write_bytes<P: AsRef<Path>, B: AsRef<[u8]>>(path: P, contents: B) -> CoreResult<()> {
123 let mut file = create_file(path)?;
124 file.write_all(contents.as_ref())?;
125 file.flush()?;
126 Ok(())
127}
128
129#[allow(dead_code)]
141pub fn read_lines<P, F>(path: P, mut callback: F) -> CoreResult<()>
142where
143 P: AsRef<Path>,
144 F: FnMut(String) -> CoreResult<()>,
145{
146 let file = open_file(path)?;
147 for line in file.lines() {
148 let line = line?;
149 callback(line)?;
150 }
151 Ok(())
152}
153
154#[must_use]
165#[allow(dead_code)]
166pub fn file_exists<P: AsRef<Path>>(path: P) -> bool {
167 path.as_ref().exists() && path.as_ref().is_file()
168}
169
170#[must_use]
181#[allow(dead_code)]
182pub fn directory_exists<P: AsRef<Path>>(path: P) -> bool {
183 path.as_ref().exists() && path.as_ref().is_dir()
184}
185
186#[allow(dead_code)]
197pub fn create_directory<P: AsRef<Path>>(path: P) -> CoreResult<()> {
198 if !directory_exists(&path) {
199 std::fs::create_dir_all(path.as_ref())?;
200 }
201 Ok(())
202}
203
204#[allow(dead_code)]
218pub fn filesize<P: AsRef<Path>>(path: P) -> CoreResult<u64> {
219 let metadata = std::fs::metadata(path.as_ref())?;
220 Ok(metadata.len())
221}
222
223#[must_use]
233#[allow(dead_code)]
234pub fn formatsize(size: u64) -> String {
235 const KB: u64 = 1024;
236 const MB: u64 = KB * 1024;
237 const GB: u64 = MB * 1024;
238 const TB: u64 = GB * 1024;
239
240 if size >= TB {
241 format!("{:.2} TB", size as f64 / TB as f64)
242 } else if size >= GB {
243 format!("{:.2} GB", size as f64 / GB as f64)
244 } else if size >= MB {
245 format!("{:.2} MB", size as f64 / MB as f64)
246 } else if size >= KB {
247 format!("{:.2} KB", size as f64 / KB as f64)
248 } else {
249 format!("{size} B")
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256 use std::io::Write;
257 use tempfile::tempdir;
258
259 #[test]
260 fn test_read_write_string() {
261 let dir = tempdir().unwrap();
262 let filepath = dir.path().join("test.txt");
263
264 let test_str = "Hello, world!";
265 write_string(&filepath, test_str).unwrap();
266
267 let contents = read_to_string(&filepath).unwrap();
268 assert_eq!(contents, test_str);
269 }
270
271 #[test]
272 fn test_read_write_bytes() {
273 let dir = tempdir().unwrap();
274 let filepath = dir.path().join("test.bin");
275
276 let test_bytes = vec![1, 2, 3, 4, 5];
277 write_bytes(&filepath, &test_bytes).unwrap();
278
279 let contents = read_to_bytes(&filepath).unwrap();
280 assert_eq!(contents, test_bytes);
281 }
282
283 #[test]
284 fn test_read_lines() {
285 let dir = tempdir().unwrap();
286 let filepath = dir.path().join("test_lines.txt");
287
288 {
289 let mut file = File::create(&filepath).unwrap();
290 writeln!(file, "Line 1").unwrap();
291 writeln!(file, "Line 2").unwrap();
292 writeln!(file, "Line 3").unwrap();
293 }
294
295 let mut lines = Vec::new();
296 read_lines(&filepath, |line| {
297 lines.push(line);
298 Ok(())
299 })
300 .unwrap();
301
302 assert_eq!(lines, vec!["Line 1", "Line 2", "Line 3"]);
303 }
304
305 #[test]
306 fn test_file_exists() {
307 let dir = tempdir().unwrap();
308 let filepath = dir.path().join("test_exists.txt");
309
310 assert!(!file_exists(&filepath));
311
312 File::create(&filepath).unwrap();
313
314 assert!(file_exists(&filepath));
315 }
316
317 #[test]
318 fn test_directory_exists() {
319 let dir = tempdir().unwrap();
320 let dirpath = dir.path().join("test_dir");
321
322 assert!(!directory_exists(&dirpath));
323
324 std::fs::create_dir(&dirpath).unwrap();
325
326 assert!(directory_exists(&dirpath));
327 }
328
329 #[test]
330 fn test_create_directory() {
331 let dir = tempdir().unwrap();
332 let dirpath = dir.path().join("test_create_dir");
333
334 assert!(!directory_exists(&dirpath));
335
336 create_directory(&dirpath).unwrap();
337
338 assert!(directory_exists(&dirpath));
339 }
340
341 #[test]
342 fn test_filesize() {
343 let dir = tempdir().unwrap();
344 let filepath = dir.path().join("testsize.txt");
345
346 let test_str = "Hello, world!";
347 write_string(&filepath, test_str).unwrap();
348
349 let size = filesize(&filepath).unwrap();
350 assert_eq!(size, test_str.len() as u64);
351 }
352
353 #[test]
354 fn test_formatsize() {
355 assert_eq!(formatsize(500), "500 B");
356 assert_eq!(formatsize(1024), "1.00 KB");
357 assert_eq!(formatsize(1500), "1.46 KB");
358 assert_eq!(formatsize(1024 * 1024), "1.00 MB");
359 assert_eq!(formatsize(1024 * 1024 * 1024), "1.00 GB");
360 assert_eq!(formatsize(1024 * 1024 * 1024 * 1024), "1.00 TB");
361 }
362}