1use crate::traits::{FileMetadata, FileType, VortexFs, VortexFsError, VortexFsResult};
6
7pub struct RealFs;
9
10impl RealFs {
11 pub fn new() -> Self {
12 Self
13 }
14}
15
16impl Default for RealFs {
17 fn default() -> Self {
18 Self::new()
19 }
20}
21
22impl VortexFs for RealFs {
23 fn read_file(&self, path: &str) -> VortexFsResult<Vec<u8>> {
24 std::fs::read(path).map_err(|e| map_io_error(path, e))
25 }
26
27 fn write_file(&mut self, path: &str, data: &[u8]) -> VortexFsResult<()> {
28 if let Some(parent) = std::path::Path::new(path).parent()
30 && !parent.as_os_str().is_empty()
31 {
32 std::fs::create_dir_all(parent).map_err(|e| map_io_error(path, e))?;
33 }
34 std::fs::write(path, data).map_err(|e| map_io_error(path, e))
35 }
36
37 fn append_file(&mut self, path: &str, data: &[u8]) -> VortexFsResult<()> {
38 use std::io::Write;
39 let mut file = std::fs::OpenOptions::new()
40 .create(true)
41 .append(true)
42 .open(path)
43 .map_err(|e| map_io_error(path, e))?;
44 file.write_all(data).map_err(|e| map_io_error(path, e))
45 }
46
47 fn remove_file(&mut self, path: &str) -> VortexFsResult<()> {
48 std::fs::remove_file(path).map_err(|e| map_io_error(path, e))
49 }
50
51 fn rename(&mut self, from: &str, to: &str) -> VortexFsResult<()> {
52 std::fs::rename(from, to).map_err(|e| map_io_error(from, e))
53 }
54
55 fn create_dir_all(&mut self, path: &str) -> VortexFsResult<()> {
56 std::fs::create_dir_all(path).map_err(|e| map_io_error(path, e))
57 }
58
59 fn remove_dir(&mut self, path: &str) -> VortexFsResult<()> {
60 std::fs::remove_dir(path).map_err(|e| map_io_error(path, e))
61 }
62
63 fn read_dir(&self, path: &str) -> VortexFsResult<Vec<String>> {
64 let entries = std::fs::read_dir(path).map_err(|e| map_io_error(path, e))?;
65 let mut names = Vec::new();
66 for entry in entries {
67 let entry = entry.map_err(|e| map_io_error(path, e))?;
68 if let Some(name) = entry.file_name().to_str() {
69 names.push(name.to_string());
70 }
71 }
72 names.sort(); Ok(names)
74 }
75
76 fn metadata(&self, path: &str) -> VortexFsResult<FileMetadata> {
77 let meta = std::fs::metadata(path).map_err(|e| map_io_error(path, e))?;
78 Ok(FileMetadata {
79 file_type: if meta.is_dir() {
80 FileType::Directory
81 } else {
82 FileType::File
83 },
84 size: meta.len(),
85 })
86 }
87
88 fn exists(&self, path: &str) -> bool {
89 std::path::Path::new(path).exists()
90 }
91
92 fn fsync(&mut self, path: &str) -> VortexFsResult<()> {
93 let file = std::fs::File::open(path).map_err(|e| map_io_error(path, e))?;
94 file.sync_all().map_err(|e| map_io_error(path, e))
95 }
96}
97
98fn map_io_error(path: &str, err: std::io::Error) -> VortexFsError {
99 match err.kind() {
100 std::io::ErrorKind::NotFound => VortexFsError::NotFound(path.into()),
101 std::io::ErrorKind::PermissionDenied => VortexFsError::PermissionDenied(path.into()),
102 std::io::ErrorKind::AlreadyExists => VortexFsError::AlreadyExists(path.into()),
103 _ => VortexFsError::IoError(format!("{path}: {err}")),
104 }
105}