From 41bb6d6f53b7c0e9c1a2a6898c0218f434f1a152 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 13 Feb 2016 18:29:34 +0100 Subject: [PATCH] Add initial structure --- libimagnotes/src/error.rs | 88 +++++++++++++++++++++++++++++ libimagnotes/src/lib.rs | 8 ++- libimagnotes/src/note.rs | 113 +++++++++++++++++++++++++++++++++++++ libimagnotes/src/result.rs | 6 ++ 4 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 libimagnotes/src/error.rs create mode 100644 libimagnotes/src/note.rs create mode 100644 libimagnotes/src/result.rs diff --git a/libimagnotes/src/error.rs b/libimagnotes/src/error.rs new file mode 100644 index 00000000..e6b0617f --- /dev/null +++ b/libimagnotes/src/error.rs @@ -0,0 +1,88 @@ +use std::error::Error; +use std::fmt::Error as FmtError; +use std::clone::Clone; +use std::fmt::{Debug, Display, Formatter}; +use std::fmt; +use std::convert::From; + +/** + * Kind of error + */ +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum NoteErrorKind { + StoreWriteError, + StoreReadError, + HeaderTypeError, + NoteToEntryConversion, + // Nothing here yet +} + +fn note_error_type_as_str(e: &NoteErrorKind) -> &'static str { + match e { + &NoteErrorKind::StoreWriteError => "Error writing store", + &NoteErrorKind::StoreReadError => "Error reading store", + &NoteErrorKind::HeaderTypeError => "Header type error", + &NoteErrorKind::NoteToEntryConversion => "Error converting Note instance to Entry instance", + } +} + +impl Display for NoteErrorKind { + + fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> { + try!(write!(fmt, "{}", note_error_type_as_str(self))); + Ok(()) + } + +} + +/** + * Store error type + */ +#[derive(Debug)] +pub struct NoteError { + err_type: NoteErrorKind, + cause: Option>, +} + +impl NoteError { + + /** + * Build a new NoteError from an NoteErrorKind, optionally with cause + */ + pub fn new(errtype: NoteErrorKind, cause: Option>) -> NoteError { + NoteError { + err_type: errtype, + cause: cause, + } + } + + /** + * Get the error type of this NoteError + */ + pub fn err_type(&self) -> NoteErrorKind { + self.err_type.clone() + } + +} + +impl Display for NoteError { + + fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> { + try!(write!(fmt, "[{}]", note_error_type_as_str(&self.err_type.clone()))); + Ok(()) + } + +} + +impl Error for NoteError { + + fn description(&self) -> &str { + note_error_type_as_str(&self.err_type.clone()) + } + + fn cause(&self) -> Option<&Error> { + self.cause.as_ref().map(|e| &**e) + } + +} + diff --git a/libimagnotes/src/lib.rs b/libimagnotes/src/lib.rs index ee6a5a7a..f9319e8e 100644 --- a/libimagnotes/src/lib.rs +++ b/libimagnotes/src/lib.rs @@ -3,6 +3,12 @@ extern crate semver; extern crate toml; extern crate libimagrt; -extern crate libimagstore; +#[macro_use] extern crate libimagstore; extern crate libimagtag; +module_entry_path_mod!("notes", "0.1.0"); + +pub mod error; +pub mod note; +pub mod result; + diff --git a/libimagnotes/src/note.rs b/libimagnotes/src/note.rs new file mode 100644 index 00000000..b2a253cf --- /dev/null +++ b/libimagnotes/src/note.rs @@ -0,0 +1,113 @@ +use std::convert::Into; +use std::collections::BTreeMap; +use std::ops::{DerefMut, Deref}; + +use toml::Value; + +use libimagstore::storeid::IntoStoreId; +use libimagstore::store::FileLockEntry; +use libimagstore::store::Store; +use libimagtag::tag::Tag; +use libimagtag::tagable::Tagable; +use libimagtag::result::Result as TagResult; +use libimagtag::error::{TagError, TagErrorKind}; + +use module_path::ModuleEntryPath; +use result::Result; +use error::NoteError as NE; +use error::NoteErrorKind as NEK; + +pub struct Note<'a> { + entry: FileLockEntry<'a>, +} + +impl<'a> Note<'a> { + + pub fn new(store: &Store, name: String, text: String) -> Result { + use std::ops::DerefMut; + + debug!("Creating new Note: '{}'", name); + let fle = { + let mut lockentry = store.create(ModuleEntryPath::new(name.clone()).into_storeid()); + if lockentry.is_err() { + return Err(NE::new(NEK::StoreWriteError, Some(Box::new(lockentry.err().unwrap())))); + } + let mut lockentry = lockentry.unwrap(); + + { + let mut entry = lockentry.deref_mut(); + let mut header = entry.get_header_mut(); + let setres = header.set("note", Value::Table(BTreeMap::new())); + if setres.is_err() { + return Err(NE::new(NEK::StoreWriteError, Some(Box::new(setres.err().unwrap())))); + } + + let setres = header.set("note.name", Value::String(name)); + if setres.is_err() { + return Err(NE::new(NEK::StoreWriteError, Some(Box::new(setres.err().unwrap())))); + } + } + + lockentry + }; + + Ok(Note { entry: fle }) + } + + pub fn set_name(&mut self, n: String) -> Result<()> { + let mut header = self.entry.deref_mut().get_header_mut(); + header.set("note.name", Value::String(n)) + .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e)))) + .map(|_| ()) + } + + pub fn get_name(&self) -> Result { + let mut header = self.entry.deref().get_header(); + match header.read("note.name") { + Ok(Some(Value::String(s))) => Ok(String::from(s)), + Ok(_) => { + let e = NE::new(NEK::HeaderTypeError, None); + Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))) + }, + Err(e) => Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))) + } + } + + pub fn set_text(&mut self, n: String) { + *self.entry.deref_mut().get_content_mut() = n + } + + pub fn get_text(&self) -> &String { + self.entry.deref().get_content() + } + +} + +impl<'a> Tagable for Note<'a> { + + fn get_tags(&self) -> TagResult> { + self.entry.deref().get_tags() + } + + fn set_tags(&mut self, ts: Vec) -> TagResult<()> { + self.entry.deref_mut().set_tags(ts) + } + + fn add_tag(&mut self, t: Tag) -> TagResult<()> { + self.entry.deref_mut().add_tag(t) + } + + fn remove_tag(&mut self, t: Tag) -> TagResult<()> { + self.entry.deref_mut().remove_tag(t) + } + + fn has_tag(&self, t: &Tag) -> TagResult { + self.entry.deref().has_tag(t) + } + + fn has_tags(&self, ts: &Vec) -> TagResult { + self.entry.deref().has_tags(ts) + } + +} + diff --git a/libimagnotes/src/result.rs b/libimagnotes/src/result.rs new file mode 100644 index 00000000..df40d8c7 --- /dev/null +++ b/libimagnotes/src/result.rs @@ -0,0 +1,6 @@ +use std::result::Result as RResult; + +use error::NoteError; + +pub type Result = RResult; +