Merge branch 'add-store' into rewrite
This commit is contained in:
commit
52787f5108
7 changed files with 182 additions and 113 deletions
|
@ -2,12 +2,14 @@ use std::convert::{From, Into};
|
|||
use std::error::Error;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug)]
|
||||
#[derive(PartialEq)]
|
||||
#[derive(Eq)]
|
||||
#[derive(Hash)]
|
||||
pub struct FileHash {
|
||||
hash: String,
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::convert::{From, Into};
|
|||
use std::error::Error;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::path::PathBuf;
|
||||
use std::result::Result;
|
||||
use std::str::FromStr;
|
||||
|
@ -12,6 +13,9 @@ use storage::file::id_type::FileIDType;
|
|||
use storage::file::hash::FileHash;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Hash)]
|
||||
#[derive(Eq)]
|
||||
#[derive(PartialEq)]
|
||||
pub struct FileID {
|
||||
id: FileHash,
|
||||
id_type: FileIDType,
|
||||
|
@ -101,7 +105,7 @@ impl Into<String> for FileID {
|
|||
fn into(self) -> String {
|
||||
let typestr : String = self.id_type.into();
|
||||
let idstr : String = self.id.into();
|
||||
typestr + &idstr[..]
|
||||
typestr + "-" + &idstr[..]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
use std::convert::{From, Into};
|
||||
use std::error::Error;
|
||||
use std::str::FromStr;
|
||||
use std::hash::Hash;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone)]
|
||||
#[derive(PartialEq)]
|
||||
#[derive(Eq)]
|
||||
// #[derive(Display)]
|
||||
#[derive(Hash)]
|
||||
pub enum FileIDType {
|
||||
UUID,
|
||||
}
|
||||
|
|
|
@ -23,130 +23,42 @@ use self::header::data::*;
|
|||
* Internal abstract view on a file. Does not exist on the FS and is just kept
|
||||
* internally until it is written to disk.
|
||||
*/
|
||||
pub struct File<'a> {
|
||||
owning_module : &'a Module<'a>,
|
||||
header : FileHeaderData,
|
||||
data : String,
|
||||
id : FileID,
|
||||
pub struct File {
|
||||
pub owning_module_name : &'static str,
|
||||
pub header : FileHeaderData,
|
||||
pub data : String,
|
||||
pub id : FileID,
|
||||
}
|
||||
|
||||
impl<'a> File<'a> {
|
||||
impl File {
|
||||
|
||||
pub fn new(module: &'a Module<'a>) -> File<'a> {
|
||||
let f = File {
|
||||
owning_module: module,
|
||||
header: FileHeaderData::Null,
|
||||
data: String::from(""),
|
||||
id: File::get_new_file_id(),
|
||||
};
|
||||
debug!("Create new File object: {:?}", f);
|
||||
f
|
||||
pub fn owner_name(&self) -> &'static str {
|
||||
self.owning_module_name
|
||||
}
|
||||
|
||||
pub fn from_parser_result(module: &'a Module<'a>, id: FileID, header: FileHeaderData, data: String) -> File<'a> {
|
||||
let f = File {
|
||||
owning_module: module,
|
||||
header: header,
|
||||
data: data,
|
||||
id: id,
|
||||
};
|
||||
debug!("Create new File object from parser result: {:?}", f);
|
||||
f
|
||||
pub fn header(&self) -> &FileHeaderData {
|
||||
&self.header
|
||||
}
|
||||
|
||||
pub fn new_with_header(module: &'a Module<'a>, h: FileHeaderData) -> File<'a> {
|
||||
let f = File {
|
||||
owning_module: module,
|
||||
header: h,
|
||||
data: String::from(""),
|
||||
id: File::get_new_file_id(),
|
||||
};
|
||||
debug!("Create new File object with header: {:?}", f);
|
||||
f
|
||||
pub fn data(&self) -> &String {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn new_with_data(module: &'a Module<'a>, d: String) -> File<'a> {
|
||||
let f = File {
|
||||
owning_module: module,
|
||||
header: FileHeaderData::Null,
|
||||
data: d,
|
||||
id: File::get_new_file_id(),
|
||||
};
|
||||
debug!("Create new File object with data: {:?}", f);
|
||||
f
|
||||
}
|
||||
|
||||
pub fn new_with_content(module: &'a Module<'a>, h: FileHeaderData, d: String) -> File<'a> {
|
||||
let f = File {
|
||||
owning_module: module,
|
||||
header: h,
|
||||
data: d,
|
||||
id: File::get_new_file_id(),
|
||||
};
|
||||
debug!("Create new File object with content: {:?}", f);
|
||||
f
|
||||
}
|
||||
|
||||
/**
|
||||
* Call editor on the file
|
||||
*
|
||||
* Return true if exit code from editor was good (and content was changed), false otherwise.
|
||||
*/
|
||||
pub fn edit(rt: &Runtime) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/**
|
||||
* Call editor on the file contents, but don't include the header inside the editor call.
|
||||
*
|
||||
* Return true if exit code from editor was good (and content was changed), false otherwise.
|
||||
*/
|
||||
pub fn edit_contents(rt: &Runtime) -> bool {
|
||||
}
|
||||
|
||||
/**
|
||||
* Make file persistent.
|
||||
*
|
||||
* Retreive store path from the runtime, file id is already available in self.
|
||||
*
|
||||
* Return true if action succeeded, false otherwise.
|
||||
*/
|
||||
pub fn persist(rt: &Runtime) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn header(&self) -> FileHeaderData {
|
||||
self.header.clone()
|
||||
}
|
||||
|
||||
pub fn data(&self) -> String {
|
||||
self.data.clone()
|
||||
}
|
||||
|
||||
pub fn contents(&self) -> (FileHeaderData, String) {
|
||||
pub fn contents(&self) -> (&FileHeaderData, &String) {
|
||||
(self.header(), self.data())
|
||||
}
|
||||
|
||||
pub fn id(&self) -> FileID {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
pub fn owner(&self) -> &'a Module<'a> {
|
||||
self.owning_module
|
||||
pub fn id(&self) -> &FileID {
|
||||
&self.id
|
||||
}
|
||||
|
||||
pub fn matches_with(&self, r: &Regex) -> bool {
|
||||
r.is_match(&self.data[..]) || self.header.matches_with(r)
|
||||
}
|
||||
|
||||
fn get_new_file_id() -> FileID {
|
||||
use uuid::Uuid;
|
||||
let hash = FileHash::from(Uuid::new_v4().to_hyphenated_string());
|
||||
FileID::new(FileIDType::UUID, hash)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Display for File<'a> {
|
||||
impl Display for File {
|
||||
|
||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
write!(fmt,
|
||||
|
@ -154,7 +66,7 @@ impl<'a> Display for File<'a> {
|
|||
FileID: '{:?}'
|
||||
Header: '{:?}'
|
||||
Data : '{:?}'",
|
||||
self.owning_module,
|
||||
self.owning_module_name,
|
||||
self.header,
|
||||
self.data,
|
||||
self.id);
|
||||
|
@ -163,7 +75,7 @@ impl<'a> Display for File<'a> {
|
|||
|
||||
}
|
||||
|
||||
impl<'a> Debug for File<'a> {
|
||||
impl Debug for File {
|
||||
|
||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
write!(fmt,
|
||||
|
@ -171,7 +83,7 @@ impl<'a> Debug for File<'a> {
|
|||
FileID: '{:?}'
|
||||
Header: '{:?}'
|
||||
Data : '{:?}'",
|
||||
self.owning_module,
|
||||
self.owning_module_name,
|
||||
self.header,
|
||||
self.data,
|
||||
self.id);
|
||||
|
|
|
@ -1,4 +1,153 @@
|
|||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File as FSFile;
|
||||
use std::ops::Deref;
|
||||
use std::io::Write;
|
||||
|
||||
pub mod path;
|
||||
pub mod file;
|
||||
pub mod parser;
|
||||
pub mod json;
|
||||
|
||||
use module::Module;
|
||||
use runtime::Runtime;
|
||||
use storage::file::File;
|
||||
use storage::file::id::FileID;
|
||||
use storage::file::id_type::FileIDType;
|
||||
use storage::file::hash::FileHash;
|
||||
use storage::parser::{FileHeaderParser, Parser, ParserError};
|
||||
use storage::file::header::data::FileHeaderData;
|
||||
|
||||
type Cache = HashMap<FileID, Rc<RefCell<File>>>;
|
||||
|
||||
pub struct Store {
|
||||
cache : RefCell<Cache>,
|
||||
}
|
||||
|
||||
impl Store {
|
||||
|
||||
pub fn new() -> Store {
|
||||
Store {
|
||||
cache: RefCell::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn put_in_cache(&self, f: File) -> FileID {
|
||||
let res = f.id().clone();
|
||||
self.cache.borrow_mut().insert(f.id().clone(), Rc::new(RefCell::new(f)));
|
||||
res
|
||||
}
|
||||
|
||||
pub fn new_file(&self, module: &Module)
|
||||
-> FileID
|
||||
{
|
||||
let f = File {
|
||||
owning_module_name: module.name(),
|
||||
header: FileHeaderData::Null,
|
||||
data: String::from(""),
|
||||
id: self.get_new_file_id(),
|
||||
};
|
||||
|
||||
debug!("Create new File object: {:?}", &f);
|
||||
self.put_in_cache(f)
|
||||
}
|
||||
|
||||
pub fn new_file_from_parser_result(&self,
|
||||
module: &Module,
|
||||
id: FileID,
|
||||
header: FileHeaderData,
|
||||
data: String)
|
||||
-> FileID
|
||||
{
|
||||
let f = File {
|
||||
owning_module_name: module.name(),
|
||||
header: header,
|
||||
data: data,
|
||||
id: id,
|
||||
};
|
||||
debug!("Create new File object from parser result: {:?}", f);
|
||||
self.put_in_cache(f)
|
||||
}
|
||||
|
||||
pub fn new_file_with_header(&self,
|
||||
module: &Module,
|
||||
h: FileHeaderData)
|
||||
-> FileID
|
||||
{
|
||||
let f = File {
|
||||
owning_module_name: module.name(),
|
||||
header: h,
|
||||
data: String::from(""),
|
||||
id: self.get_new_file_id(),
|
||||
};
|
||||
debug!("Create new File object with header: {:?}", f);
|
||||
self.put_in_cache(f)
|
||||
}
|
||||
|
||||
pub fn new_file_with_data(&self, module: &Module, d: String)
|
||||
-> FileID
|
||||
{
|
||||
let f = File {
|
||||
owning_module_name: module.name(),
|
||||
header: FileHeaderData::Null,
|
||||
data: d,
|
||||
id: self.get_new_file_id(),
|
||||
};
|
||||
debug!("Create new File object with data: {:?}", f);
|
||||
self.put_in_cache(f)
|
||||
}
|
||||
|
||||
pub fn new_file_with_content(&self,
|
||||
module: &Module,
|
||||
h: FileHeaderData,
|
||||
d: String)
|
||||
-> FileID
|
||||
{
|
||||
let f = File {
|
||||
owning_module_name: module.name(),
|
||||
header: h,
|
||||
data: d,
|
||||
id: self.get_new_file_id(),
|
||||
};
|
||||
debug!("Create new File object with content: {:?}", f);
|
||||
self.put_in_cache(f)
|
||||
}
|
||||
|
||||
pub fn persist<HP>(&self,
|
||||
storepath: String,
|
||||
p: &Parser<HP>,
|
||||
f: Rc<RefCell<File>>) -> bool
|
||||
where HP: FileHeaderParser
|
||||
{
|
||||
let file = f.deref().borrow();
|
||||
let text = p.write(file.contents());
|
||||
if text.is_err() {
|
||||
error!("Error: {}", text.err().unwrap());
|
||||
return false;
|
||||
}
|
||||
|
||||
let path = {
|
||||
let ids : String = file.id().clone().into();
|
||||
format!("{}/{}-{}.imag", storepath, file.owning_module_name, ids)
|
||||
};
|
||||
|
||||
FSFile::create(&path).map(|mut fsfile| {
|
||||
fsfile.write_all(&text.unwrap().clone().into_bytes()[..])
|
||||
}).map_err(|writeerr| {
|
||||
debug!("Could not create file at '{}'", path);
|
||||
}).and(Ok(true)).unwrap()
|
||||
}
|
||||
|
||||
pub fn load(&self, id: &FileID) -> Option<Rc<RefCell<File>>> {
|
||||
debug!("Loading '{:?}'", id);
|
||||
self.cache.borrow().get(id).cloned()
|
||||
}
|
||||
|
||||
fn get_new_file_id(&self) -> FileID {
|
||||
use uuid::Uuid;
|
||||
let hash = FileHash::from(Uuid::new_v4().to_hyphenated_string());
|
||||
FileID::new(FileIDType::UUID, hash)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ impl<HP: FileHeaderParser> Parser<HP> {
|
|||
Ok((h_parseres, data.unwrap_or(String::new())))
|
||||
}
|
||||
|
||||
pub fn write(&self, tpl : (FileHeaderData, String)) -> Result<String, ParserError> {
|
||||
pub fn write(&self, tpl : (&FileHeaderData, &String)) -> Result<String, ParserError> {
|
||||
debug!("Parsing internal datastructure to String");
|
||||
let (header, data) = tpl;
|
||||
let h_text = try!(self.headerp.write(&header));
|
||||
|
|
|
@ -14,7 +14,7 @@ pub trait FilePrinter {
|
|||
/*
|
||||
* Print a list of files
|
||||
*/
|
||||
fn print_files<'a, I: Iterator<Item = File<'a>>>(&self, files: I) {
|
||||
fn print_files<I: Iterator<Item = File>>(&self, files: I) {
|
||||
for file in files {
|
||||
self.print_file(&file);
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ impl FilePrinter for TablePrinter {
|
|||
self.sp.print_file(f);
|
||||
}
|
||||
|
||||
fn print_files<'a, I: Iterator<Item = File<'a>>>(&self, files: I) {
|
||||
fn print_files<I: Iterator<Item = File>>(&self, files: I) {
|
||||
use prettytable::Table;
|
||||
use prettytable::row::Row;
|
||||
use prettytable::cell::Cell;
|
||||
|
@ -103,9 +103,9 @@ impl FilePrinter for TablePrinter {
|
|||
debug!("Printing file: {:?}", file);
|
||||
i += 1;
|
||||
let cell_i = Cell::new(&format!("{}", i)[..]);
|
||||
let cell_o = Cell::new(&format!("{}", file.owner().name())[..]);
|
||||
let cell_o = Cell::new(&format!("{}", file.owner_name())[..]);
|
||||
|
||||
let id : String = file.id().into();
|
||||
let id : String = file.id().clone().into();
|
||||
let cell_id = Cell::new(&id[..]);
|
||||
let row = Row::new(vec![cell_i, cell_o, cell_id]);
|
||||
tab.add_row(row);
|
||||
|
|
Loading…
Reference in a new issue