Merge branch 'add-store' into rewrite

This commit is contained in:
Matthias Beyer 2015-12-28 00:31:45 +01:00
commit 52787f5108
7 changed files with 182 additions and 113 deletions

View file

@ -2,12 +2,14 @@ use std::convert::{From, Into};
use std::error::Error; use std::error::Error;
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use std::fmt; use std::fmt;
use std::hash::Hash;
use uuid::Uuid; use uuid::Uuid;
#[derive(Clone)] #[derive(Clone)]
#[derive(Debug)] #[derive(Debug)]
#[derive(PartialEq)] #[derive(PartialEq)]
#[derive(Eq)] #[derive(Eq)]
#[derive(Hash)]
pub struct FileHash { pub struct FileHash {
hash: String, hash: String,
} }

View file

@ -2,6 +2,7 @@ use std::convert::{From, Into};
use std::error::Error; use std::error::Error;
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use std::fmt; use std::fmt;
use std::hash::Hash;
use std::path::PathBuf; use std::path::PathBuf;
use std::result::Result; use std::result::Result;
use std::str::FromStr; use std::str::FromStr;
@ -12,6 +13,9 @@ use storage::file::id_type::FileIDType;
use storage::file::hash::FileHash; use storage::file::hash::FileHash;
#[derive(Clone)] #[derive(Clone)]
#[derive(Hash)]
#[derive(Eq)]
#[derive(PartialEq)]
pub struct FileID { pub struct FileID {
id: FileHash, id: FileHash,
id_type: FileIDType, id_type: FileIDType,
@ -101,7 +105,7 @@ impl Into<String> for FileID {
fn into(self) -> String { fn into(self) -> String {
let typestr : String = self.id_type.into(); let typestr : String = self.id_type.into();
let idstr : String = self.id.into(); let idstr : String = self.id.into();
typestr + &idstr[..] typestr + "-" + &idstr[..]
} }
} }

View file

@ -1,12 +1,14 @@
use std::convert::{From, Into}; use std::convert::{From, Into};
use std::error::Error; use std::error::Error;
use std::str::FromStr; use std::str::FromStr;
use std::hash::Hash;
#[derive(Debug)] #[derive(Debug)]
#[derive(Clone)] #[derive(Clone)]
#[derive(PartialEq)] #[derive(PartialEq)]
#[derive(Eq)] #[derive(Eq)]
// #[derive(Display)] // #[derive(Display)]
#[derive(Hash)]
pub enum FileIDType { pub enum FileIDType {
UUID, UUID,
} }

View file

@ -23,130 +23,42 @@ use self::header::data::*;
* Internal abstract view on a file. Does not exist on the FS and is just kept * Internal abstract view on a file. Does not exist on the FS and is just kept
* internally until it is written to disk. * internally until it is written to disk.
*/ */
pub struct File<'a> { pub struct File {
owning_module : &'a Module<'a>, pub owning_module_name : &'static str,
header : FileHeaderData, pub header : FileHeaderData,
data : String, pub data : String,
id : FileID, pub id : FileID,
} }
impl<'a> File<'a> { impl File {
pub fn new(module: &'a Module<'a>) -> File<'a> { pub fn owner_name(&self) -> &'static str {
let f = File { self.owning_module_name
owning_module: module,
header: FileHeaderData::Null,
data: String::from(""),
id: File::get_new_file_id(),
};
debug!("Create new File object: {:?}", f);
f
} }
pub fn from_parser_result(module: &'a Module<'a>, id: FileID, header: FileHeaderData, data: String) -> File<'a> { pub fn header(&self) -> &FileHeaderData {
let f = File { &self.header
owning_module: module,
header: header,
data: data,
id: id,
};
debug!("Create new File object from parser result: {:?}", f);
f
} }
pub fn new_with_header(module: &'a Module<'a>, h: FileHeaderData) -> File<'a> { pub fn data(&self) -> &String {
let f = File { &self.data
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 new_with_data(module: &'a Module<'a>, d: String) -> File<'a> { pub fn contents(&self) -> (&FileHeaderData, &String) {
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) {
(self.header(), self.data()) (self.header(), self.data())
} }
pub fn id(&self) -> FileID { pub fn id(&self) -> &FileID {
self.id.clone() &self.id
}
pub fn owner(&self) -> &'a Module<'a> {
self.owning_module
} }
pub fn matches_with(&self, r: &Regex) -> bool { pub fn matches_with(&self, r: &Regex) -> bool {
r.is_match(&self.data[..]) || self.header.matches_with(r) 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 { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, write!(fmt,
@ -154,7 +66,7 @@ impl<'a> Display for File<'a> {
FileID: '{:?}' FileID: '{:?}'
Header: '{:?}' Header: '{:?}'
Data : '{:?}'", Data : '{:?}'",
self.owning_module, self.owning_module_name,
self.header, self.header,
self.data, self.data,
self.id); 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 { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, write!(fmt,
@ -171,7 +83,7 @@ impl<'a> Debug for File<'a> {
FileID: '{:?}' FileID: '{:?}'
Header: '{:?}' Header: '{:?}'
Data : '{:?}'", Data : '{:?}'",
self.owning_module, self.owning_module_name,
self.header, self.header,
self.data, self.data,
self.id); self.id);

View file

@ -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 path;
pub mod file; pub mod file;
pub mod parser; pub mod parser;
pub mod json; 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)
}
}

View file

@ -122,7 +122,7 @@ impl<HP: FileHeaderParser> Parser<HP> {
Ok((h_parseres, data.unwrap_or(String::new()))) 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"); debug!("Parsing internal datastructure to String");
let (header, data) = tpl; let (header, data) = tpl;
let h_text = try!(self.headerp.write(&header)); let h_text = try!(self.headerp.write(&header));

View file

@ -14,7 +14,7 @@ pub trait FilePrinter {
/* /*
* Print a list of files * 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 { for file in files {
self.print_file(&file); self.print_file(&file);
} }
@ -88,7 +88,7 @@ impl FilePrinter for TablePrinter {
self.sp.print_file(f); 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::Table;
use prettytable::row::Row; use prettytable::row::Row;
use prettytable::cell::Cell; use prettytable::cell::Cell;
@ -103,9 +103,9 @@ impl FilePrinter for TablePrinter {
debug!("Printing file: {:?}", file); debug!("Printing file: {:?}", file);
i += 1; i += 1;
let cell_i = Cell::new(&format!("{}", i)[..]); 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 cell_id = Cell::new(&id[..]);
let row = Row::new(vec![cell_i, cell_o, cell_id]); let row = Row::new(vec![cell_i, cell_o, cell_id]);
tab.add_row(row); tab.add_row(row);