From abc142f4b58a9c4602ec5815e17bdd34a8681206 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 25 Apr 2018 12:54:00 +0200 Subject: [PATCH] Rewrite library libimagcontact stores all contact information in the entry header now. --- lib/domain/libimagcontact/Cargo.toml | 10 ++-- lib/domain/libimagcontact/src/contact.rs | 44 +++++++---------- lib/domain/libimagcontact/src/deser.rs | 8 +-- lib/domain/libimagcontact/src/error.rs | 11 ++++- lib/domain/libimagcontact/src/lib.rs | 15 ++---- lib/domain/libimagcontact/src/store.rs | 63 +++++++++++++++++++----- lib/domain/libimagcontact/src/util.rs | 8 --- 7 files changed, 88 insertions(+), 71 deletions(-) diff --git a/lib/domain/libimagcontact/Cargo.toml b/lib/domain/libimagcontact/Cargo.toml index 4c4c4d2f..d295248a 100644 --- a/lib/domain/libimagcontact/Cargo.toml +++ b/lib/domain/libimagcontact/Cargo.toml @@ -25,15 +25,11 @@ log = "0.3" toml = "0.4" toml-query = "0.6" vobject = "0.4" -uuid = { version = "0.6", features = ["v4"] } -serde = { version = "1", optional = true } -serde_derive = { version = "1", optional = true } +uuid = "0.6" +serde = "1" +serde_derive = "1" libimagstore = { version = "0.8.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.8.0", path = "../../../lib/core/libimagerror" } libimagentryutil = { version = "0.8.0", path = "../../../lib/entry/libimagentryutil/" } -[features] -default = [] -deser = ["serde", "serde_derive"] - diff --git a/lib/domain/libimagcontact/src/contact.rs b/lib/domain/libimagcontact/src/contact.rs index b35ee5b8..fb586458 100644 --- a/lib/domain/libimagcontact/src/contact.rs +++ b/lib/domain/libimagcontact/src/contact.rs @@ -17,16 +17,18 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use std::ops::Deref; - -use vobject::Component; +use toml::to_string as toml_to_string; +use toml::from_str as toml_from_str; +use toml_query::read::TomlValueReadExt; use libimagstore::store::Entry; use libimagentryutil::isa::Is; use libimagentryutil::isa::IsKindHeaderPathProvider; +use deser::DeserVcard; use error::Result; -use util; +use error::ContactError as CE; +use error::ContactErrorKind as CEK; /// Trait to be implemented on ::libimagstore::store::Entry pub trait Contact { @@ -35,7 +37,7 @@ pub trait Contact { // getting data - fn get_contact_data(&self) -> Result; + fn deser(&self) -> Result; // More convenience functionality may follow @@ -49,28 +51,18 @@ impl Contact for Entry { self.is::().map_err(From::from) } - fn get_contact_data(&self) -> Result { - unimplemented!() + fn deser(&self) -> Result { + let data = self + .get_header() + .read("contact.data")? + .ok_or_else(|| CE::from_kind(CEK::HeaderDataMissing("contact.data")))?; + + // ugly hack + let data_str = toml_to_string(&data)?; + let deser : DeserVcard = toml_from_str(&data_str)?; + + Ok(deser) } } -pub struct ContactData(Component); - -impl ContactData { - - pub fn into_inner(self) -> Component { - self.0 - } - -} - -impl Deref for ContactData { - type Target = Component; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - - diff --git a/lib/domain/libimagcontact/src/deser.rs b/lib/domain/libimagcontact/src/deser.rs index 84855cd9..ec5e234d 100644 --- a/lib/domain/libimagcontact/src/deser.rs +++ b/lib/domain/libimagcontact/src/deser.rs @@ -20,13 +20,7 @@ use vobject::vcard::Vcard; /// A type which can be build from a Vcard and be serialized. -/// -/// # Details -/// -/// Deserializing is not supported by libimagcontact yet -/// Elements which are "empty" (as in empty list) or optional and not present are not serialized. -/// -#[derive(Serialize, Debug)] +#[derive(Serialize, Deserialize, Debug)] pub struct DeserVcard { #[serde(skip_serializing_if = "Vec::is_empty")] diff --git a/lib/domain/libimagcontact/src/error.rs b/lib/domain/libimagcontact/src/error.rs index eb44b3b2..8eb757b5 100644 --- a/lib/domain/libimagcontact/src/error.rs +++ b/lib/domain/libimagcontact/src/error.rs @@ -32,6 +32,8 @@ error_chain! { foreign_links { Io(::std::io::Error); + TomlDe(::toml::de::Error); + TomlSer(::toml::ser::Error); TomlQueryError(::toml_query::error::Error); UuidError(::uuid::ParseError); } @@ -43,14 +45,19 @@ error_chain! { display("Type error in header, expected {} at '{}', found other type", ty, loc) } + HeaderDataMissing(datapath: &'static str) { + description("Data missing in header") + display("Data missing in header at '{}'", datapath) + } + EntryNotFound(sid: StoreId) { description("Entry not found with StoreId") display("Entry {:?} not found", sid) } - UidMissing(path: String) { + UidMissing(buf: String) { description("Vcard object has no UID") - display("Vcard at {:?} has no UID", path) + display("Vcard has no UID : {}", buf) } } diff --git a/lib/domain/libimagcontact/src/lib.rs b/lib/domain/libimagcontact/src/lib.rs index f16d07e8..87b244e2 100644 --- a/lib/domain/libimagcontact/src/lib.rs +++ b/lib/domain/libimagcontact/src/lib.rs @@ -33,12 +33,16 @@ while_true, )] +#![recursion_limit="128"] + #[macro_use] extern crate log; #[macro_use] extern crate error_chain; extern crate vobject; extern crate toml; extern crate toml_query; extern crate uuid; +extern crate serde; +#[macro_use] extern crate serde_derive; #[macro_use] extern crate libimagstore; extern crate libimagerror; @@ -50,15 +54,6 @@ pub mod contact; pub mod error; pub mod iter; pub mod store; +pub mod deser; mod util; - -#[cfg(feature = "serde")] -extern crate serde; - -#[cfg(feature = "serde")] -#[macro_use] extern crate serde_derive; - -#[cfg(feature = "deser")] -pub mod deser; - diff --git a/lib/domain/libimagcontact/src/store.rs b/lib/domain/libimagcontact/src/store.rs index 8529eb0d..88856b70 100644 --- a/lib/domain/libimagcontact/src/store.rs +++ b/lib/domain/libimagcontact/src/store.rs @@ -17,18 +17,24 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use std::path::Path; use std::path::PathBuf; -use std::result::Result as RResult; -use vobject::parse_component; +use toml::Value; +use toml::to_string as toml_to_string; +use toml::from_str as toml_from_str; +use toml_query::insert::TomlValueInsertExt; +use vobject::vcard::Vcard; +use libimagstore::storeid::IntoStoreId; +use libimagstore::storeid::StoreId; use libimagstore::store::Store; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreIdIterator; use libimagentryutil::isa::Is; use contact::IsContact; +use deser::DeserVcard; +use module_path::ModuleEntryPath; use error::ContactError as CE; use error::ContactErrorKind as CEK; use error::Result; @@ -38,10 +44,11 @@ pub trait ContactStore<'a> { // creating - fn create_from_path(&'a self, p: &PathBuf) -> Result>; + fn create_from_path(&'a self, p: &PathBuf) -> Result>; + fn retrieve_from_path(&'a self, p: &PathBuf) -> Result>; - /// Create contact ref from buffer - fn create_from_buf(&'a self, buf: &String) -> Result>; + fn create_from_buf(&'a self, buf: &str) -> Result>; + fn retrieve_from_buf(&'a self, buf: &str) -> Result>; // getting @@ -55,12 +62,19 @@ impl<'a> ContactStore<'a> for Store { util::read_to_string(p).and_then(|buf| self.create_from_buf(&buf)) } - /// Create contact ref from buffer - fn create_from_buf(&'a self, buf: &String) -> Result> { - let component = parse_component(&buf)?; - debug!("Parsed: {:?}", component); + fn retrieve_from_path(&'a self, p: &PathBuf) -> Result> { + util::read_to_string(p).and_then(|buf| self.retrieve_from_buf(&buf)) + } - unimplemented!() + /// Create contact ref from buffer + fn create_from_buf(&'a self, buf: &str) -> Result> { + let (sid, value) = prepare_fetching_from_store(buf)?; + postprocess_fetched_entry(self.create(sid)?, value) + } + + fn retrieve_from_buf(&'a self, buf: &str) -> Result> { + let (sid, value) = prepare_fetching_from_store(buf)?; + postprocess_fetched_entry(self.retrieve(sid)?, value) } fn all_contacts(&'a self) -> Result { @@ -74,3 +88,30 @@ impl<'a> ContactStore<'a> for Store { } +/// Prepare the fetching from the store. +/// +/// That means calculating the StoreId and the Value from the vcard data +fn prepare_fetching_from_store(buf: &str) -> Result<(StoreId, Value)> { + let vcard = Vcard::build(&buf)?; + debug!("Parsed: {:?}", vcard); + + let uid = vcard.uid().ok_or_else(|| CE::from_kind(CEK::UidMissing(buf.to_string())))?; + + let value = { // dirty ugly hack + let serialized = DeserVcard::from(vcard); + let serialized = toml_to_string(&serialized)?; + toml_from_str::(&serialized)? + }; + + let sid = ModuleEntryPath::new(uid.raw()).into_storeid()?; + + Ok((sid, value)) +} + +/// Postprocess the entry just fetched from the store +fn postprocess_fetched_entry<'a>(mut entry: FileLockEntry<'a>, value: Value) -> Result> { + entry.set_isflag::()?; + entry.get_header_mut().insert("contact.data", value)?; + Ok(entry) +} + diff --git a/lib/domain/libimagcontact/src/util.rs b/lib/domain/libimagcontact/src/util.rs index 8a72b872..53e820c4 100644 --- a/lib/domain/libimagcontact/src/util.rs +++ b/lib/domain/libimagcontact/src/util.rs @@ -24,8 +24,6 @@ use std::io::Read; use error::Result; -use vobject::Component; - pub fn read_to_string + Debug>(pb: A) -> Result { let mut cont = String::new(); @@ -37,9 +35,3 @@ pub fn read_to_string + Debug>(pb: A) -> Result { Ok(cont) } -/// Helper for chaining results nicely -pub fn parse(buf: String) -> Result { - use vobject::parse_component; - parse_component(&buf).map_err(From::from) -} -