use std::{
io,
path::{Path, PathBuf},
};
use crate::{FileMetadata, FileSystem};
#[derive(Default)]
pub struct MemoryFS {
fs: vfs::MemoryFS,
}
impl MemoryFS {
#[allow(dead_code)]
pub fn new(data: &[(&'static str, &'static str)]) -> Self {
let mut fs = Self {
fs: vfs::MemoryFS::default(),
};
for (path, content) in data {
fs.add_file(Path::new(path), content);
}
fs
}
#[allow(dead_code)]
pub fn add_file(&mut self, path: &Path, content: &str) {
use vfs::FileSystem;
let fs = &mut self.fs;
for path in path.ancestors().collect::<Vec<_>>().iter().rev() {
let path = path.to_string_lossy();
if !fs.exists(path.as_ref()).unwrap() {
fs.create_dir(path.as_ref()).unwrap();
}
}
let mut file = fs.create_file(path.to_string_lossy().as_ref()).unwrap();
file.write_all(content.as_bytes()).unwrap();
}
}
#[async_trait::async_trait]
impl FileSystem for MemoryFS {
async fn read_to_string(&self, path: &Path) -> io::Result<String> {
use vfs::FileSystem;
let mut file = self
.fs
.open_file(path.to_string_lossy().as_ref())
.map_err(|err| io::Error::new(io::ErrorKind::NotFound, err))?;
let mut buffer = String::new();
file.read_to_string(&mut buffer).unwrap();
Ok(buffer)
}
async fn read(&self, path: &Path) -> io::Result<Vec<u8>> {
let buf = self.read_to_string(path).await?;
Ok(buf.into_bytes())
}
async fn metadata(&self, path: &Path) -> io::Result<FileMetadata> {
use vfs::FileSystem;
let metadata = self
.fs
.metadata(path.to_string_lossy().as_ref())
.map_err(|err| io::Error::new(io::ErrorKind::NotFound, err))?;
let is_file = metadata.file_type == vfs::VfsFileType::File;
let is_dir = metadata.file_type == vfs::VfsFileType::Directory;
Ok(FileMetadata::new(is_file, is_dir, false))
}
async fn symlink_metadata(&self, path: &Path) -> io::Result<FileMetadata> {
self.metadata(path).await
}
async fn canonicalize(&self, _path: &Path) -> io::Result<PathBuf> {
Err(io::Error::new(io::ErrorKind::NotFound, "not a symlink"))
}
}