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:
parent
1047a06a64
commit
2ef57a69ed
4 changed files with 32 additions and 35 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<()> {
|
||||||
|
|
Loading…
Reference in a new issue