diff options
Diffstat (limited to 'lockchain-files/src/fs.rs')
-rw-r--r-- | lockchain-files/src/fs.rs | 81 |
1 files changed, 36 insertions, 45 deletions
diff --git a/lockchain-files/src/fs.rs b/lockchain-files/src/fs.rs index be5ccba..1aa57bc 100644 --- a/lockchain-files/src/fs.rs +++ b/lockchain-files/src/fs.rs @@ -1,10 +1,10 @@ //! Filesystem abstraction for various data types -//! +//! //! All operations return io::Result<()> to indicate errors //! and functions that have multiple file endpoints will return //! a folded error list to indicate which ops were successful //! and which failed. -//! +//! //! There is also a `From<Vec<?>> for Result<?>` implementation //! which will return either `Ok(())` or the first error in the list //! of operations. @@ -13,20 +13,23 @@ use lcc::traits::AutoEncoder; use std::collections::HashMap; use std::error::Error; -use std::io::{self, Read, Write}; +use std::io::Write; use std::{ - fs::{self, File, OpenOptions as OO}, path::PathBuf, + fs::{self, File, OpenOptions as OO}, + path::PathBuf, }; +use utils::FileToString; + #[derive(Debug)] pub struct Filesystem { - name: String, - path: String, - root: PathBuf, + pub name: String, + pub path: String, + pub root: PathBuf, } /// A switching enum to determine what type of file to load - +#[allow(dead_code)] pub enum FileType { /// A data record file Record, @@ -34,6 +37,8 @@ pub enum FileType { Metadata, /// A simple checksum file Checksum, + #[doc(hidden)] + __NonExhaustive, } /// Construct a file ending for a specific match result @@ -42,18 +47,22 @@ macro_rules! file_ending { match $type { FileType::Record => "record", FileType::Metadata => "meta", + FileType::Checksum => "sum", _ => "dat", } }; } impl Filesystem { - pub fn create(path: &str, name: &str) -> Filesystem { + /// Create a new filesystem representation + /// + /// This function does _not_ touch the disk! + pub fn new(path: &str, name: &str) -> Self { let mut buffer = PathBuf::new(); buffer.push(path); buffer.push(format!("{}.vault", name)); - Filesystem { + Self { name: name.to_owned(), path: path.to_owned(), root: buffer, @@ -74,27 +83,29 @@ impl Filesystem { Ok(fs::read_dir(match types { FileType::Record => self.root.join("records"), FileType::Metadata => self.root.join("metadata"), - _ => self.root.join("."), + _ => self.root.clone(), })?.into_iter() - .filter_map(|r| r.ok()) - .filter(|f| match f.file_type() { - Ok(vf) => vf.is_file(), - _ => false, - }) - .map(|de| de.path()) - .filter_map(|p| p.into_os_string().into_string().ok()) - .filter_map(|s| File::open(s).ok()) - .filter_map(|mut f| f.get_string().ok()) - .filter_map(|s| T::decode(&s).ok()) - .collect()) + .filter_map(|r| r.ok()) + .filter(|f| match f.file_type() { + Ok(vf) => vf.is_file(), + _ => false, + }).map(|de| de.path()) + .filter_map(|p| p.into_os_string().into_string().ok()) + .filter_map(|s| File::open(s).ok()) + .filter_map(|mut f| f.get_string().ok()) + .filter_map(|s| T::decode(&s).ok()) + .collect()) } + /// Retrieve a single record from the cached vault pub fn pull<T: AutoEncoder>(&self, types: FileType, id: &str) -> Result<T, Box<Error>> { Ok(T::decode( - &File::open(self.root.join(&format!("{}.{}", id, file_ending!(types))))?.get_string()?, + &File::open(self.root.join(&format!("{}.{}", id, file_ending!(types))))? + .get_string()?, )?) } + /// Respond to a sync request pub fn sync<T>(&self, data: &HashMap<String, T>, types: FileType) -> Result<(), Box<Error>> where T: AutoEncoder, @@ -110,13 +121,11 @@ impl Filesystem { }.join(format!("{}.{}", k, file_ending!(types))), v, ) - }) - .filter(|(_, v)| v.is_some()) + }).filter(|(_, v)| v.is_some()) .map(|(k, v)| (k, v.unwrap())) .map(|(path, data): (PathBuf, String)| { (OO::new().create(true).write(true).open(path), data) - }) - .filter(|(path, _)| path.is_ok()) + }).filter(|(path, _)| path.is_ok()) .map(|(file, data)| (file.unwrap(), data)) .for_each(|(mut file, data)| { file.write_all(data.as_bytes()) @@ -126,21 +135,3 @@ impl Filesystem { Ok(()) } } - -/// A utility trait to read the conents from a file in -/// a single line. -pub trait FileToString { - /// Read the file contents into a string without any - /// error handling. - fn get_string(&mut self) -> Result<String, io::Error>; -} - -impl FileToString for File { - fn get_string(&mut self) -> Result<String, io::Error> { - let mut s = String::new(); - return match self.read_to_string(&mut s) { - Ok(_) => Ok(s), - Err(e) => Err(e), - }; - } -} |