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>
This commit is contained in:
Matthias Beyer 2019-06-26 20:08:42 +02:00
parent 1047a06a64
commit 2ef57a69ed
4 changed files with 32 additions and 35 deletions

View file

@ -26,12 +26,18 @@ toml = "0.5"
itertools = "0.7" itertools = "0.7"
is-match = "0.1" is-match = "0.1"
filters = "0.3" filters = "0.3"
toml-query = "0.9"
failure = "0.1" failure = "0.1"
serde = "1"
serde_derive = "1"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" } libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
[dependencies.toml-query]
version = "0.9"
default-features = false
features = [ "typed" ]
[dependencies.clap] [dependencies.clap]
version = "^2.29" version = "^2.29"
default-features = false default-features = false

View file

@ -43,6 +43,8 @@ extern crate itertools;
extern crate regex; extern crate regex;
extern crate toml; extern crate toml;
extern crate toml_query; extern crate toml_query;
extern crate serde;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate is_match; #[macro_use] extern crate is_match;
extern crate filters; extern crate filters;
#[macro_use] extern crate failure; #[macro_use] extern crate failure;

View file

@ -20,16 +20,17 @@
use std::result::Result; use std::result::Result;
use regex::Regex; use regex::Regex;
use failure::Error;
pub type Tag = String; pub type Tag = String;
pub type TagSlice<'a> = &'a str; pub type TagSlice<'a> = &'a str;
/// validator which can be used by clap to validate that a string is a valid tag /// validator which can be used by clap to validate that a string is a valid tag
pub fn is_tag(s: String) -> Result<(), String> { 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; use filters::filter::Filter;
trace!("Checking whether '{}' is a valid tag", s); 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) { if is_lower.and(no_whitespace).and(is_alphanum).and(matches_regex).filter(s) {
Ok(()) Ok(())
} else { } else {
Err(format!("The string '{}' is not a valid tag", s)) Err(format_err!("The string '{}' is not a valid tag", s))
} }
} }

View file

@ -23,6 +23,7 @@ use libimagstore::store::Entry;
use libimagerror::errors::ErrorMsg as EM; use libimagerror::errors::ErrorMsg as EM;
use toml_query::read::TomlValueReadExt; use toml_query::read::TomlValueReadExt;
use toml_query::read::Partial;
use toml_query::insert::TomlValueInsertExt; use toml_query::insert::TomlValueInsertExt;
use failure::Error; 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 { impl Tagable for Value {
fn get_tags(&self) -> Result<Vec<Tag>> { fn get_tags(&self) -> Result<Vec<Tag>> {
self.read("tag.values") self.read_partial::<TagHeader>()?
.context(format_err!("Failed to read header at 'tag.values'")) .map(|header| {
.map_err(Error::from) let _ = header.values
.context(EM::EntryHeaderReadError)? .iter()
.map(|val| { .map(is_tag_str)
debug!("Got Value of tags..."); .collect::<Result<_>>()?;
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() Ok(header.values)
.cloned()
.map(|t| {
match t {
Value::String(s) => s,
_ => unreachable!(),
}
}) })
.collect()) .unwrap_or_else(|| Ok(vec![]))
})
.unwrap_or(Ok(vec![]))
})
.unwrap_or(Ok(vec![]))
} }
fn set_tags(&mut self, ts: &[Tag]) -> Result<()> { fn set_tags(&mut self, ts: &[Tag]) -> Result<()> {