use std::borrow::Cow;
use std::collections::VecDeque;
use camino::Utf8Path;
use camino::Utf8PathBuf;
use lexiclean_cow::Lexiclean;
use sftp_protocol::common::Metadata;
use crate::Error;
use super::file::OpenFile;
pub type Result<T> = std::result::Result<T, Error>;
pub trait PathRef: AsRef<Utf8Path> + Send + Sync {}
impl<T> PathRef for T where T: AsRef<Utf8Path> + Send + Sync {}
#[async_trait]
pub trait Backend : Clone + Send + Sync {
async fn metadata(&self, path: impl PathRef + 'async_trait) -> Result<Metadata>;
async fn list(&self, path: impl PathRef + 'async_trait) -> Result<VecDeque<Metadata>>;
#[allow(clippy::too_many_arguments)]
async fn open(&self, path: impl PathRef + 'async_trait, read: bool, write: bool, append: bool, create: bool, truncate: bool, create_new: bool) -> Result<OpenFile>;
async fn set_metadata(&self, path: impl PathRef + 'async_trait, uid_and_gid: Option<(u32, u32)>, permissions: Option<u32>, atime_and_mtime: Option<(u32, u32)>) -> Result<()>;
async fn delete_file(&self, path: impl PathRef + 'async_trait) -> Result<()>;
async fn mkdir(&self, path: impl PathRef + 'async_trait) -> Result<()>;
async fn rmdir(&self, path: impl PathRef + 'async_trait) -> Result<()>;
async fn rename(&self, from: impl PathRef + 'async_trait, to: impl PathRef + 'async_trait) -> Result<()>;
async fn readlink(&self, path: impl PathRef + 'async_trait) -> Result<Option<Utf8PathBuf>>;
async fn mklink(&self, link_path: impl PathRef + 'async_trait, target_path: impl PathRef + 'async_trait, link_type: crate::LinkType) -> Result<()>;
fn normalize_path<'a, 'path>(&'a self, path: &'path Utf8Path) -> Result<Cow<'path, Utf8Path>> {
let path = path.lexiclean();
if let Some(first) = path.ancestors().next() {
if(first == "..") {
return Err(Error::InvalidPath);
}
}
Ok(path)
}
}