use std::path::PathBuf;
use std::fmt::Debug;
use std::collections::HashMap;
use std::sync::Arc;
use failure::Fallible as Result;
use crate::store::Entry;
use crate::storeid::StoreIdWithBase;
pub mod fs;
pub mod inmemory;
pub mod iter;
use self::iter::PathIterator;
pub(crate) trait FileAbstraction : Debug {
fn remove_file(&self, path: &PathBuf) -> Result<()>;
fn copy(&self, from: &PathBuf, to: &PathBuf) -> Result<()>;
fn rename(&self, from: &PathBuf, to: &PathBuf) -> Result<()>;
fn create_dir_all(&self, _: &PathBuf) -> Result<()>;
fn exists(&self, _: &PathBuf) -> Result<bool>;
fn is_file(&self, _: &PathBuf) -> Result<bool>;
fn new_instance(&self, p: PathBuf) -> Box<dyn FileAbstractionInstance>;
fn drain(&self) -> Result<Drain>;
fn fill(&mut self, d: Drain) -> Result<()>;
fn pathes_recursively<'a>(&self, basepath: PathBuf, storepath: &'a PathBuf, backend: Arc<dyn FileAbstraction>) -> Result<PathIterator<'a>>;
}
pub(crate) trait FileAbstractionInstance : Debug {
fn get_file_content<'a>(&mut self, id: StoreIdWithBase<'a>) -> Result<Option<Entry>>;
fn write_file_content(&mut self, buf: &Entry) -> Result<()>;
}
pub struct Drain(HashMap<PathBuf, Entry>);
impl Drain {
pub fn new(hm: HashMap<PathBuf, Entry>) -> Drain {
Drain(hm)
}
pub fn empty() -> Drain {
Drain::new(HashMap::new())
}
pub fn iter(&mut self) -> DrainIter<'_> {
DrainIter(self.0.drain())
}
}
pub struct DrainIter<'a>(::std::collections::hash_map::Drain<'a, PathBuf, Entry>);
impl<'a> Iterator for DrainIter<'a> {
type Item = (PathBuf, Entry);
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
#[cfg(test)]
mod test {
use std::path::PathBuf;
use super::FileAbstractionInstance;
use super::inmemory::InMemoryFileAbstraction;
use super::inmemory::InMemoryFileAbstractionInstance;
use crate::storeid::StoreIdWithBase;
use crate::store::Entry;
#[test]
fn lazy_file() {
let store_path = PathBuf::from("/");
let fs = InMemoryFileAbstraction::default();
let mut path = PathBuf::from("tests");
path.set_file_name("test1");
let mut lf = InMemoryFileAbstractionInstance::new(fs.backend().clone(), path.clone());
let loca = StoreIdWithBase::new(&store_path, path);
let file = Entry::from_str(loca.clone(), &format!(r#"---
[imag]
version = "{}"
---
Hello World"#, env!("CARGO_PKG_VERSION"))).unwrap();
lf.write_file_content(&file).unwrap();
let bah = lf.get_file_content(loca).unwrap().unwrap();
assert_eq!(bah.get_content(), "Hello World");
}
#[test]
fn lazy_file_multiline() {
let store_path = PathBuf::from("/");
let fs = InMemoryFileAbstraction::default();
let mut path = PathBuf::from("tests");
path.set_file_name("test1");
let mut lf = InMemoryFileAbstractionInstance::new(fs.backend().clone(), path.clone());
let loca = StoreIdWithBase::new(&store_path, path);
let file = Entry::from_str(loca.clone(), &format!(r#"---
[imag]
version = "{}"
---
Hello World
baz"#, env!("CARGO_PKG_VERSION"))).unwrap();
lf.write_file_content(&file).unwrap();
let bah = lf.get_file_content(loca).unwrap().unwrap();
assert_eq!(bah.get_content(), "Hello World\nbaz");
}
#[test]
fn lazy_file_multiline_trailing_newlines() {
let store_path = PathBuf::from("/");
let fs = InMemoryFileAbstraction::default();
let mut path = PathBuf::from("tests");
path.set_file_name("test1");
let mut lf = InMemoryFileAbstractionInstance::new(fs.backend().clone(), path.clone());
let loca = StoreIdWithBase::new(&store_path, path);
let file = Entry::from_str(loca.clone(), &format!(r#"---
[imag]
version = "{}"
---
Hello World
baz
"#, env!("CARGO_PKG_VERSION"))).unwrap();
lf.write_file_content(&file).unwrap();
let bah = lf.get_file_content(loca).unwrap().unwrap();
assert_eq!(bah.get_content(), "Hello World\nbaz\n\n");
}
}