use crate::traits::{FileMetadata, FileType, VortexFs, VortexFsError, VortexFsResult};
pub struct RealFs;
impl RealFs {
pub fn new() -> Self {
Self
}
}
impl Default for RealFs {
fn default() -> Self {
Self::new()
}
}
impl VortexFs for RealFs {
fn read_file(&self, path: &str) -> VortexFsResult<Vec<u8>> {
std::fs::read(path).map_err(|e| map_io_error(path, e))
}
fn write_file(&mut self, path: &str, data: &[u8]) -> VortexFsResult<()> {
if let Some(parent) = std::path::Path::new(path).parent()
&& !parent.as_os_str().is_empty()
{
std::fs::create_dir_all(parent).map_err(|e| map_io_error(path, e))?;
}
std::fs::write(path, data).map_err(|e| map_io_error(path, e))
}
fn append_file(&mut self, path: &str, data: &[u8]) -> VortexFsResult<()> {
use std::io::Write;
let mut file = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(path)
.map_err(|e| map_io_error(path, e))?;
file.write_all(data).map_err(|e| map_io_error(path, e))
}
fn remove_file(&mut self, path: &str) -> VortexFsResult<()> {
std::fs::remove_file(path).map_err(|e| map_io_error(path, e))
}
fn rename(&mut self, from: &str, to: &str) -> VortexFsResult<()> {
std::fs::rename(from, to).map_err(|e| map_io_error(from, e))
}
fn create_dir_all(&mut self, path: &str) -> VortexFsResult<()> {
std::fs::create_dir_all(path).map_err(|e| map_io_error(path, e))
}
fn remove_dir(&mut self, path: &str) -> VortexFsResult<()> {
std::fs::remove_dir(path).map_err(|e| map_io_error(path, e))
}
fn read_dir(&self, path: &str) -> VortexFsResult<Vec<String>> {
let entries = std::fs::read_dir(path).map_err(|e| map_io_error(path, e))?;
let mut names = Vec::new();
for entry in entries {
let entry = entry.map_err(|e| map_io_error(path, e))?;
if let Some(name) = entry.file_name().to_str() {
names.push(name.to_string());
}
}
names.sort(); Ok(names)
}
fn metadata(&self, path: &str) -> VortexFsResult<FileMetadata> {
let meta = std::fs::metadata(path).map_err(|e| map_io_error(path, e))?;
Ok(FileMetadata {
file_type: if meta.is_dir() {
FileType::Directory
} else {
FileType::File
},
size: meta.len(),
})
}
fn exists(&self, path: &str) -> bool {
std::path::Path::new(path).exists()
}
fn fsync(&mut self, path: &str) -> VortexFsResult<()> {
let file = std::fs::File::open(path).map_err(|e| map_io_error(path, e))?;
file.sync_all().map_err(|e| map_io_error(path, e))
}
}
fn map_io_error(path: &str, err: std::io::Error) -> VortexFsError {
match err.kind() {
std::io::ErrorKind::NotFound => VortexFsError::NotFound(path.into()),
std::io::ErrorKind::PermissionDenied => VortexFsError::PermissionDenied(path.into()),
std::io::ErrorKind::AlreadyExists => VortexFsError::AlreadyExists(path.into()),
_ => VortexFsError::IoError(format!("{path}: {err}")),
}
}