use std::{io, path::Path, sync::Arc, time::SystemTime};
use crate::BoxFuture;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DirentKind {
File,
Dir,
}
#[derive(Clone, Debug)]
pub struct Stat {
pub kind: DirentKind,
pub size: u64,
pub mtime: Option<SystemTime>,
pub atime: Option<SystemTime>,
pub ctime: Option<SystemTime>,
pub created: Option<SystemTime>,
pub etag: Option<String>,
pub version: Option<String>,
}
impl Stat {
pub fn new(kind: DirentKind, size: u64) -> Self {
Self {
kind,
size,
mtime: None,
atime: None,
ctime: None,
created: None,
etag: None,
version: None,
}
}
}
#[derive(Clone, Debug)]
pub struct Dirent {
pub name: String,
pub kind: DirentKind,
stat: Option<Stat>,
}
impl Dirent {
pub fn new(name: impl Into<String>, kind: DirentKind) -> Self {
Dirent {
name: name.into(),
kind,
stat: None,
}
}
pub fn with_stat(name: impl Into<String>, stat: Stat) -> Self {
Dirent {
name: name.into(),
kind: stat.kind,
stat: Some(stat),
}
}
pub fn stat(&self) -> Option<&Stat> {
self.stat.as_ref()
}
}
pub trait FileSystem: Send + Sync {
fn stat<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<Stat>>;
fn list<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<Vec<Dirent>>>;
fn read_at<'a>(
&'a self,
path: &'a Path,
buf: &'a mut [u8],
offset: u64,
) -> BoxFuture<'a, io::Result<usize>>;
fn create<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<Stat>> {
let _ = path;
Box::pin(async { Err(io::ErrorKind::ReadOnlyFilesystem.into()) })
}
fn mkdir<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<Stat>> {
let _ = path;
Box::pin(async { Err(io::ErrorKind::ReadOnlyFilesystem.into()) })
}
fn unlink<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<()>> {
let _ = path;
Box::pin(async { Err(io::ErrorKind::ReadOnlyFilesystem.into()) })
}
fn rmdir<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<()>> {
let _ = path;
Box::pin(async { Err(io::ErrorKind::ReadOnlyFilesystem.into()) })
}
fn write_at<'a>(
&'a self,
path: &'a Path,
buf: &'a [u8],
offset: u64,
) -> BoxFuture<'a, io::Result<usize>> {
let _ = (path, buf, offset);
Box::pin(async { Err(io::ErrorKind::ReadOnlyFilesystem.into()) })
}
fn truncate<'a>(&'a self, path: &'a Path, size: u64) -> BoxFuture<'a, io::Result<()>> {
let _ = (path, size);
Box::pin(async { Err(io::ErrorKind::ReadOnlyFilesystem.into()) })
}
fn rename<'a>(&'a self, from: &'a Path, to: &'a Path) -> BoxFuture<'a, io::Result<()>> {
let _ = (from, to);
Box::pin(async { Err(io::ErrorKind::ReadOnlyFilesystem.into()) })
}
fn flush<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<()>> {
let _ = path;
Box::pin(async { Ok(()) })
}
fn forget<'a>(&'a self) -> BoxFuture<'a, ()> {
Box::pin(async {})
}
}
impl<T: FileSystem + ?Sized> FileSystem for Arc<T> {
fn stat<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<Stat>> {
(**self).stat(path)
}
fn forget<'a>(&'a self) -> BoxFuture<'a, ()> {
(**self).forget()
}
fn list<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<Vec<Dirent>>> {
(**self).list(path)
}
fn read_at<'a>(
&'a self,
path: &'a Path,
buf: &'a mut [u8],
offset: u64,
) -> BoxFuture<'a, io::Result<usize>> {
(**self).read_at(path, buf, offset)
}
fn create<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<Stat>> {
(**self).create(path)
}
fn mkdir<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<Stat>> {
(**self).mkdir(path)
}
fn unlink<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<()>> {
(**self).unlink(path)
}
fn rmdir<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<()>> {
(**self).rmdir(path)
}
fn write_at<'a>(
&'a self,
path: &'a Path,
buf: &'a [u8],
offset: u64,
) -> BoxFuture<'a, io::Result<usize>> {
(**self).write_at(path, buf, offset)
}
fn truncate<'a>(&'a self, path: &'a Path, size: u64) -> BoxFuture<'a, io::Result<()>> {
(**self).truncate(path, size)
}
fn rename<'a>(&'a self, from: &'a Path, to: &'a Path) -> BoxFuture<'a, io::Result<()>> {
(**self).rename(from, to)
}
fn flush<'a>(&'a self, path: &'a Path) -> BoxFuture<'a, io::Result<()>> {
(**self).flush(path)
}
}