//! A module that enables file management for vaults //! //! #![feature(non_modrs_mods)] extern crate lockchain_core as lcc; use lcc::traits::{Body, Vault}; use lcc::{MetaDomain, Payload, Record}; use std::collections::HashMap; mod fs; use fs::{FileType, Filesystem}; /// Represents a vault on disk pub struct DataVault { records: HashMap>, metadata: HashMap, fs: Filesystem, } impl DataVault { /// Small utility function to setup file structure fn initialize(self) -> Self { self.fs.scaffold(); self } } impl Vault for DataVault { fn new(name: &str, location: &str) -> DataVault { Self { records: HashMap::new(), metadata: HashMap::new(), fs: Filesystem::create(location, name), }.initialize() } /// Caches all files from disk to memory fn fetch(&mut self) { self.records.clear(); self.metadata.clear(); self.fs .fetch::>(FileType::Record) .unwrap() .into_iter() .map(|rec| (rec.header.name.clone(), rec)) .for_each(|x| { self.records.insert(x.0, x.1); }); self.fs .fetch::(FileType::Metadata) .unwrap() .into_iter() .map(|rec| (rec.name().into(), rec)) .for_each(|x| { self.metadata.insert(x.0, x.1); }); } /// Make sure a single record is loaded fn pull(&mut self, name: &str) { self.records.remove(name); self.records.insert( name.to_owned(), self.fs.pull::>(FileType::Record, name).unwrap(), ); } fn sync(&mut self) { self.fs .sync::>(&self.records, FileType::Record) .unwrap(); self.fs .sync::(&self.metadata, FileType::Metadata) .unwrap(); } fn get_record(&self, name: &str) -> Option<&Record> { self.records.get(name) } fn contains(&self, name: &str) -> bool { self.records.contains_key(name) } fn add_record(&mut self, key: &str, category: &str, tags: Vec<&str>) { self.records .insert(key.to_owned(), Record::new(key, category, tags)); } fn delete_record(&mut self, record: &str) -> Option> { self.records.remove(record) } fn add_data(&mut self, record: &str, key: &str, data: Payload) -> Option<()> { self.records.get_mut(record)?.add_data(key, data) } fn get_data(&self, record: &str, key: &str) -> Option<&Payload> { self.records.get(record)?.get_data(key) } fn meta_add_domain(&mut self, domain: &str) -> Option<()> { if self.metadata.contains_key(domain) { None } else { self.metadata.insert(domain.into(), MetaDomain::new(domain)); Some(()) } } fn meta_pull_domain(&mut self, domain: &str) -> Option<&MetaDomain> { self.metadata.get(domain) } fn meta_set(&mut self, domain: &str, name: &str, data: Payload) -> Option<()> { self.metadata.get_mut(domain)?.set_field(name, data) } fn meta_get(&mut self, domain: &str, name: &str) -> Option { Some(self.metadata.get(domain)?.get_field(name)?.clone()) } }