~matthiasbeyer/imag

1c851bbb797ec30b344fc3a86a5dd30d431ab9ed — Matthias Beyer 2 years ago 784cc85
Rewrite store interface abstraction

Because we pull in libimagentryref here to create actual references to
the files we parse here, we need to rewrite the interface to be able to
pass the required information to the libimagentryref API.

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
M lib/domain/libimagcontact/Cargo.toml => lib/domain/libimagcontact/Cargo.toml +2 -1
@@ 31,5 31,6 @@ serde_derive = "1"

libimagstore     = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagerror     = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
libimagentryutil  = { version = "0.10.0", path = "../../../lib/entry/libimagentryutil/" }
libimagentryutil = { version = "0.10.0", path = "../../../lib/entry/libimagentryutil/" }
libimagentryref  = { version = "0.10.0", path = "../../../lib/entry/libimagentryref/" }


M lib/domain/libimagcontact/src/lib.rs => lib/domain/libimagcontact/src/lib.rs +1 -0
@@ 48,6 48,7 @@ extern crate serde;

#[macro_use] extern crate libimagstore;
extern crate libimagerror;
extern crate libimagentryref;
#[macro_use] extern crate libimagentryutil;

module_entry_path_mod!("contact");

M lib/domain/libimagcontact/src/store.rs => lib/domain/libimagcontact/src/store.rs +82 -16
@@ 18,6 18,7 @@
//

use std::path::PathBuf;
use std::path::Path;

use toml::Value;
use toml::to_string as toml_to_string;


@@ 32,6 33,7 @@ use libimagstore::iter::Entries;
use libimagstore::store::Store;
use libimagstore::store::FileLockEntry;
use libimagentryutil::isa::Is;
use libimagentryref::reference::{MutRef, Config as RefConfig};

use contact::IsContact;
use deser::DeserVcard;


@@ 39,13 41,23 @@ use util;

pub trait ContactStore<'a> {

    // creating
    fn create_from_path<CN>(&'a self, p: &PathBuf, rc: &RefConfig, collection_name: CN)
        -> Result<FileLockEntry<'a>>
        where CN: AsRef<str>;

    fn create_from_path(&'a self, p: &PathBuf)   -> Result<FileLockEntry<'a>>;
    fn retrieve_from_path(&'a self, p: &PathBuf) -> Result<FileLockEntry<'a>>;
    fn retrieve_from_path<CN>(&'a self, p: &PathBuf, rc: &RefConfig, collection_name: CN)
        -> Result<FileLockEntry<'a>>
        where CN: AsRef<str>;

    fn create_from_buf(&'a self, buf: &str)      -> Result<FileLockEntry<'a>>;
    fn retrieve_from_buf(&'a self, buf: &str)    -> Result<FileLockEntry<'a>>;
    fn create_from_buf<CN, P>(&'a self, buf: &str, path: P, rc: &RefConfig, collection_name: CN)
        -> Result<FileLockEntry<'a>>
        where CN: AsRef<str>,
              P: AsRef<Path>;

    fn retrieve_from_buf<CN, P>(&'a self, buf: &str, path: P, rc: &RefConfig, collection_name: CN)
        -> Result<FileLockEntry<'a>>
        where CN: AsRef<str>,
              P: AsRef<Path>;

    // getting



@@ 55,23 67,58 @@ pub trait ContactStore<'a> {
/// The extension for the Store to work with contacts
impl<'a> ContactStore<'a> for Store {

    fn create_from_path(&'a self, p: &PathBuf) -> Result<FileLockEntry<'a>> {
        util::read_to_string(p).and_then(|buf| self.create_from_buf(&buf))
    /// Create a contact from a filepath
    ///
    /// Uses the collection with `collection_name` from RefConfig to store the reference to the
    /// file.
    fn create_from_path<CN>(&'a self, p: &PathBuf, rc: &RefConfig, collection_name: CN)
        -> Result<FileLockEntry<'a>>
        where CN: AsRef<str>
    {
        util::read_to_string(p).and_then(|buf| self.create_from_buf(&buf, p, rc, collection_name))
    }

    fn retrieve_from_path(&'a self, p: &PathBuf) -> Result<FileLockEntry<'a>> {
        util::read_to_string(p).and_then(|buf| self.retrieve_from_buf(&buf))
    /// Retrieve a contact from a filepath
    ///
    /// Uses the collection with `collection_name` from RefConfig to store the reference to the
    /// file.
    fn retrieve_from_path<CN>(&'a self, p: &PathBuf, rc: &RefConfig, collection_name: CN)
        -> Result<FileLockEntry<'a>>
        where CN: AsRef<str>
    {
        util::read_to_string(p).and_then(|buf| self.retrieve_from_buf(&buf, p, rc, collection_name))
    }

    /// Create contact ref from buffer
    fn create_from_buf(&'a self, buf: &str) -> Result<FileLockEntry<'a>> {
    /// Create a contact from a buffer
    ///
    /// Uses the collection with `collection_name` from RefConfig to store the reference to the
    /// file.
    ///
    /// Needs the `path` passed where the buffer was read from, because we want to create a
    /// reference to it.
    fn create_from_buf<CN, P>(&'a self, buf: &str, path: P, rc: &RefConfig, collection_name: CN)
        -> Result<FileLockEntry<'a>>
        where CN: AsRef<str>,
              P: AsRef<Path>
    {
        let (sid, value) = prepare_fetching_from_store(buf)?;
        postprocess_fetched_entry(self.create(sid)?, value)
        postprocess_fetched_entry(self.create(sid)?, value, path, rc, collection_name)
    }

    fn retrieve_from_buf(&'a self, buf: &str) -> Result<FileLockEntry<'a>> {
    /// Retrieve a contact from a buffer
    ///
    /// Uses the collection with `collection_name` from RefConfig to store the reference to the
    /// file.
    ///
    /// Needs the `path` passed where the buffer was read from, because we want to create a
    /// reference to it.
    fn retrieve_from_buf<CN, P>(&'a self, buf: &str, path: P, rc: &RefConfig, collection_name: CN)
        -> Result<FileLockEntry<'a>>
        where CN: AsRef<str>,
              P: AsRef<Path>
    {
        let (sid, value) = prepare_fetching_from_store(buf)?;
        postprocess_fetched_entry(self.retrieve(sid)?, value)
        postprocess_fetched_entry(self.retrieve(sid)?, value, path, rc, collection_name)
    }

    fn all_contacts(&'a self) -> Result<Entries<'a>> {


@@ 101,10 148,29 @@ fn prepare_fetching_from_store(buf: &str) -> Result<(StoreId, Value)> {
    Ok((sid, value))
}

/// Postprocess the entry just fetched from the store
fn postprocess_fetched_entry<'a>(mut entry: FileLockEntry<'a>, value: Value) -> Result<FileLockEntry<'a>> {
/// Postprocess the entry just fetched (created or retrieved) from the store
///
/// We need the path, the refconfig and the collection name passed here because we create a
/// reference here.
///
/// This is marked as inline because what it does is trivial, but repetitve in this module.
#[inline]
fn postprocess_fetched_entry<'a, CN, P>(mut entry: FileLockEntry<'a>,
                                        value: Value,
                                        path: P,
                                        rc: &RefConfig,
                                        collection_name: CN)
    -> Result<FileLockEntry<'a>>
    where CN: AsRef<str>,
           P: AsRef<Path>
{
    use libimagentryref::reference::RefFassade;
    use libimagentryref::hasher::sha1::Sha1Hasher;

    entry.set_isflag::<IsContact>()?;
    entry.get_header_mut().insert("contact.data", value)?;
    entry.as_ref_with_hasher_mut::<Sha1Hasher>().make_ref(path, collection_name, rc, false)?;

    Ok(entry)
}