use crate::errors::CoreError;
use std::fs::{self, DirEntry, Metadata};
use std::io;
use std::path::{Path, PathBuf};
use std::time::SystemTime;
pub trait FileSystem: Send + Sync {
fn now(&self) -> SystemTime;
fn exists(&self, path: &Path) -> bool;
fn metadata(&self, path: &Path) -> crate::Result<Metadata>;
fn symlink_metadata(&self, path: &Path) -> crate::Result<Metadata>;
fn create_dir_all(&self, path: &Path) -> crate::Result<()>;
fn create_dir(&self, path: &Path) -> crate::Result<()>;
fn write(&self, path: &Path, data: &[u8]) -> crate::Result<()>;
fn write_to_string(&self, path: &Path, content: &str) -> crate::Result<()>;
fn read_to_string(&self, path: &Path) -> crate::Result<String>;
fn remove_file(&self, path: &Path) -> crate::Result<()>;
fn rename(&self, from: &Path, to: &Path) -> crate::Result<()>;
fn list_dir(&self, path: &Path) -> crate::Result<Vec<PathBuf>>;
fn remove_dir(&self, path: &Path) -> crate::Result<()>;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct RealFileSystem;
impl FileSystem for RealFileSystem {
fn now(&self) -> SystemTime {
SystemTime::now()
}
fn exists(&self, path: &Path) -> bool {
path.exists()
}
fn metadata(&self, path: &Path) -> crate::Result<Metadata> {
fs::metadata(path).map_err(|err| CoreError::io(path, err))
}
fn symlink_metadata(&self, path: &Path) -> crate::Result<Metadata> {
fs::symlink_metadata(path).map_err(|err| CoreError::io(path, err))
}
fn create_dir_all(&self, path: &Path) -> crate::Result<()> {
fs::create_dir_all(path).map_err(|err| CoreError::io(path, err))
}
fn create_dir(&self, path: &Path) -> crate::Result<()> {
fs::create_dir(path).map_err(|err| CoreError::io(path, err))
}
fn write(&self, path: &Path, data: &[u8]) -> crate::Result<()> {
fs::write(path, data).map_err(|err| CoreError::io(path, err))
}
fn write_to_string(&self, path: &Path, content: &str) -> crate::Result<()> {
fs::write(path, content).map_err(|err| CoreError::io(path, err))
}
fn read_to_string(&self, path: &Path) -> crate::Result<String> {
fs::read_to_string(path).map_err(|err| CoreError::io(path, err))
}
fn remove_file(&self, path: &Path) -> crate::Result<()> {
fs::remove_file(path).map_err(|err| CoreError::io(path, err))
}
fn rename(&self, from: &Path, to: &Path) -> crate::Result<()> {
fs::rename(from, to).map_err(|err| CoreError::io(from, err))
}
fn list_dir(&self, path: &Path) -> crate::Result<Vec<PathBuf>> {
fs::read_dir(path)
.map_err(|err| CoreError::io(path, err))?
.map(|entry| entry.map(|v| v.path()))
.collect::<Result<Vec<PathBuf>, io::Error>>()
.map_err(|err| CoreError::io(path, err))
}
fn remove_dir(&self, path: &Path) -> crate::Result<()> {
fs::remove_dir(path).map_err(|err| CoreError::io(path, err))
}
}
pub fn first_entry_file_name(entries: &[DirEntry]) -> Option<String> {
entries.first().and_then(|entry| {
entry
.file_name()
.to_str()
.map(|name| name.to_ascii_lowercase())
})
}