~matthiasbeyer/imag

2ef57a69eda86d805261b77713de1b7545c04494 — Matthias Beyer 2 years ago 1047a06
Simplify implementation using toml-query Partial

This patch rewrites the get_tags() function to use toml_query::read::Partial.

The helper functions is_tag_str and is_tag are rewritten for
compatiblity.

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
M lib/entry/libimagentrytag/Cargo.toml => lib/entry/libimagentrytag/Cargo.toml +7 -1
@@ 26,12 26,18 @@ toml = "0.5"
itertools = "0.7"
is-match = "0.1"
filters = "0.3"
toml-query = "0.9"
failure    = "0.1"
serde        = "1"
serde_derive = "1"

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

[dependencies.toml-query]
version = "0.9"
default-features = false
features = [ "typed" ]

[dependencies.clap]
version = "^2.29"
default-features = false

M lib/entry/libimagentrytag/src/lib.rs => lib/entry/libimagentrytag/src/lib.rs +2 -0
@@ 43,6 43,8 @@ extern crate itertools;
extern crate regex;
extern crate toml;
extern crate toml_query;
extern crate serde;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate is_match;
extern crate filters;
#[macro_use] extern crate failure;

M lib/entry/libimagentrytag/src/tag.rs => lib/entry/libimagentrytag/src/tag.rs +4 -3
@@ 20,16 20,17 @@
use std::result::Result;

use regex::Regex;
use failure::Error;

pub type Tag = String;
pub type TagSlice<'a> = &'a str;

/// validator which can be used by clap to validate that a string is a valid tag
pub fn is_tag(s: String) -> Result<(), String> {
    is_tag_str(&s)
    is_tag_str(&s).map_err(|_| format!("The string '{}' is not a valid tag", s))
}

pub fn is_tag_str(s: &String) -> Result<(), String> {
pub fn is_tag_str(s: &String) -> Result<(), Error> {
    use filters::filter::Filter;
    trace!("Checking whether '{}' is a valid tag", s);



@@ 41,7 42,7 @@ pub fn is_tag_str(s: &String) -> Result<(), String> {
    if is_lower.and(no_whitespace).and(is_alphanum).and(matches_regex).filter(s) {
        Ok(())
    } else {
        Err(format!("The string '{}' is not a valid tag", s))
        Err(format_err!("The string '{}' is not a valid tag", s))
    }
}


M lib/entry/libimagentrytag/src/tagable.rs => lib/entry/libimagentrytag/src/tagable.rs +20 -32
@@ 23,6 23,7 @@ use libimagstore::store::Entry;
use libimagerror::errors::ErrorMsg as EM;

use toml_query::read::TomlValueReadExt;
use toml_query::read::Partial;
use toml_query::insert::TomlValueInsertExt;

use failure::Error;


@@ 47,42 48,29 @@ pub trait Tagable {

}

#[derive(Serialize, Deserialize, Debug)]
struct TagHeader {
    values: Vec<String>,
}

impl<'a> Partial<'a> for TagHeader {
    const LOCATION: &'static str = "tags";
    type Output                  = Self;
}

impl Tagable for Value {

    fn get_tags(&self) -> Result<Vec<Tag>> {
        self.read("tag.values")
            .context(format_err!("Failed to read header at 'tag.values'"))
            .map_err(Error::from)
            .context(EM::EntryHeaderReadError)?
            .map(|val| {
                debug!("Got Value of tags...");
                val.as_array()
                    .map(|tags| {
                        debug!("Got Array<T> of tags...");
                        if !tags.iter().all(|t| is_match!(*t, Value::String(_))) {
                            return Err(format_err!("Tag type error: Got Array<T> where T is not a String: {:?}", tags));
                        }
                        debug!("Got Array<String> of tags...");
                        if tags.iter().any(|t| match *t {
                            Value::String(ref s) => !is_tag_str(s).is_ok(),
                            _ => unreachable!()})
                        {
                            return Err(format_err!("At least one tag is not a valid tag string"));
                        }

                        Ok(tags.iter()
                            .cloned()
                            .map(|t| {
                                match t {
                                   Value::String(s) => s,
                                   _ => unreachable!(),
                                }
                            })
                            .collect())
                    })
                    .unwrap_or(Ok(vec![]))
        self.read_partial::<TagHeader>()?
            .map(|header| {
                let _ = header.values
                    .iter()
                    .map(is_tag_str)
                    .collect::<Result<_>>()?;

                Ok(header.values)
            })
            .unwrap_or(Ok(vec![]))
            .unwrap_or_else(|| Ok(vec![]))
    }

    fn set_tags(&mut self, ts: &[Tag]) -> Result<()> {