2016-02-15 15:56:36 +00:00
|
|
|
use std::ops::Deref;
|
|
|
|
use std::ops::DerefMut;
|
|
|
|
|
2016-03-25 14:34:47 +00:00
|
|
|
use itertools::Itertools;
|
|
|
|
|
2016-02-15 15:56:36 +00:00
|
|
|
use libimagstore::store::{Entry, EntryHeader, FileLockEntry};
|
2016-02-15 13:03:56 +00:00
|
|
|
|
|
|
|
use error::{TagError, TagErrorKind};
|
|
|
|
use result::Result;
|
2016-05-03 21:10:32 +00:00
|
|
|
use tag::{Tag, TagSlice};
|
2016-02-21 18:18:38 +00:00
|
|
|
use util::is_tag;
|
2016-02-15 13:03:56 +00:00
|
|
|
|
|
|
|
use toml::Value;
|
|
|
|
|
|
|
|
pub trait Tagable {
|
|
|
|
|
|
|
|
fn get_tags(&self) -> Result<Vec<Tag>>;
|
2016-05-03 21:10:32 +00:00
|
|
|
fn set_tags(&mut self, ts: &[Tag]) -> Result<()>;
|
2016-02-15 13:03:56 +00:00
|
|
|
|
|
|
|
fn add_tag(&mut self, t: Tag) -> Result<()>;
|
|
|
|
fn remove_tag(&mut self, t: Tag) -> Result<()>;
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn has_tag(&self, t: TagSlice) -> Result<bool>;
|
|
|
|
fn has_tags(&self, ts: &[Tag]) -> Result<bool>;
|
2016-02-15 13:03:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Tagable for EntryHeader {
|
|
|
|
|
|
|
|
fn get_tags(&self) -> Result<Vec<Tag>> {
|
|
|
|
let tags = self.read("imag.tags");
|
|
|
|
if tags.is_err() {
|
|
|
|
let kind = TagErrorKind::HeaderReadError;
|
2016-04-17 19:08:27 +00:00
|
|
|
return Err(TagError::new(kind, Some(Box::new(tags.unwrap_err()))));
|
2016-02-15 13:03:56 +00:00
|
|
|
}
|
|
|
|
let tags = tags.unwrap();
|
|
|
|
|
|
|
|
match tags {
|
|
|
|
Some(Value::Array(tags)) => {
|
2016-05-23 19:42:49 +00:00
|
|
|
if !tags.iter().all(|t| is_match!(*t, Value::String(_))) {
|
2016-02-15 13:03:56 +00:00
|
|
|
return Err(TagError::new(TagErrorKind::TagTypeError, None));
|
|
|
|
}
|
2016-05-03 21:10:32 +00:00
|
|
|
if tags.iter().any(|t| match *t {
|
|
|
|
Value::String(ref s) => !is_tag(s),
|
2016-02-21 18:18:38 +00:00
|
|
|
_ => unreachable!()})
|
|
|
|
{
|
|
|
|
return Err(TagError::new(TagErrorKind::NotATag, None));
|
|
|
|
}
|
2016-02-15 13:03:56 +00:00
|
|
|
|
|
|
|
Ok(tags.iter()
|
|
|
|
.cloned()
|
|
|
|
.map(|t| {
|
|
|
|
match t {
|
|
|
|
Value::String(s) => s,
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect())
|
|
|
|
},
|
|
|
|
None => Ok(vec![]),
|
|
|
|
_ => Err(TagError::new(TagErrorKind::TagTypeError, None)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn set_tags(&mut self, ts: &[Tag]) -> Result<()> {
|
2016-02-21 18:18:38 +00:00
|
|
|
if ts.iter().any(|tag| !is_tag(tag)) {
|
|
|
|
debug!("Not a tag: '{}'", ts.iter().filter(|t| !is_tag(t)).next().unwrap());
|
|
|
|
return Err(TagError::new(TagErrorKind::NotATag, None));
|
|
|
|
}
|
|
|
|
|
2016-03-25 14:34:47 +00:00
|
|
|
let a = ts.iter().unique().map(|t| Value::String(t.clone())).collect();
|
2016-02-15 13:03:56 +00:00
|
|
|
self.set("imag.tags", Value::Array(a))
|
|
|
|
.map(|_| ())
|
|
|
|
.map_err(|e| TagError::new(TagErrorKind::HeaderWriteError, Some(Box::new(e))))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_tag(&mut self, t: Tag) -> Result<()> {
|
2016-02-21 18:18:38 +00:00
|
|
|
if !is_tag(&t) {
|
|
|
|
debug!("Not a tag: '{}'", t);
|
|
|
|
return Err(TagError::new(TagErrorKind::NotATag, None));
|
|
|
|
}
|
|
|
|
|
2016-02-15 13:06:08 +00:00
|
|
|
self.get_tags()
|
|
|
|
.map(|mut tags| {
|
|
|
|
tags.push(t);
|
2016-05-03 21:10:32 +00:00
|
|
|
self.set_tags(&tags.into_iter().unique().collect::<Vec<_>>()[..])
|
2016-02-15 13:06:08 +00:00
|
|
|
})
|
|
|
|
.map(|_| ())
|
2016-02-15 13:03:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn remove_tag(&mut self, t: Tag) -> Result<()> {
|
2016-02-21 18:18:38 +00:00
|
|
|
if !is_tag(&t) {
|
|
|
|
debug!("Not a tag: '{}'", t);
|
|
|
|
return Err(TagError::new(TagErrorKind::NotATag, None));
|
|
|
|
}
|
|
|
|
|
2016-02-15 13:07:10 +00:00
|
|
|
self.get_tags()
|
|
|
|
.map(|mut tags| {
|
|
|
|
tags.retain(|tag| tag.clone() != t);
|
2016-05-03 21:10:32 +00:00
|
|
|
self.set_tags(&tags[..])
|
2016-02-15 13:07:10 +00:00
|
|
|
})
|
|
|
|
.map(|_| ())
|
2016-02-15 13:03:56 +00:00
|
|
|
}
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn has_tag(&self, t: TagSlice) -> Result<bool> {
|
2016-02-15 13:03:56 +00:00
|
|
|
let tags = self.read("imag.tags");
|
|
|
|
if tags.is_err() {
|
|
|
|
let kind = TagErrorKind::HeaderReadError;
|
2016-04-17 19:08:27 +00:00
|
|
|
return Err(TagError::new(kind, Some(Box::new(tags.unwrap_err()))));
|
2016-02-15 13:03:56 +00:00
|
|
|
}
|
|
|
|
let tags = tags.unwrap();
|
|
|
|
|
2016-05-23 19:42:49 +00:00
|
|
|
if !tags.iter().all(|t| is_match!(*t, Value::String(_))) {
|
2016-02-15 13:03:56 +00:00
|
|
|
return Err(TagError::new(TagErrorKind::TagTypeError, None));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(tags
|
|
|
|
.iter()
|
|
|
|
.any(|tag| {
|
2016-05-03 21:10:32 +00:00
|
|
|
match *tag {
|
|
|
|
Value::String(ref s) => { s == t },
|
2016-02-15 13:03:56 +00:00
|
|
|
_ => unreachable!()
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn has_tags(&self, tags: &[Tag]) -> Result<bool> {
|
2016-02-15 13:03:56 +00:00
|
|
|
let mut result = true;
|
|
|
|
for tag in tags {
|
|
|
|
let check = self.has_tag(tag);
|
|
|
|
if check.is_err() {
|
2016-04-17 19:08:27 +00:00
|
|
|
return Err(check.unwrap_err());
|
2016-02-15 13:03:56 +00:00
|
|
|
}
|
|
|
|
let check = check.unwrap();
|
|
|
|
|
|
|
|
result = result && check;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-02-15 13:09:11 +00:00
|
|
|
impl Tagable for Entry {
|
|
|
|
|
|
|
|
fn get_tags(&self) -> Result<Vec<Tag>> {
|
|
|
|
self.get_header().get_tags()
|
|
|
|
}
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn set_tags(&mut self, ts: &[Tag]) -> Result<()> {
|
2016-02-15 13:09:11 +00:00
|
|
|
self.get_header_mut().set_tags(ts)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_tag(&mut self, t: Tag) -> Result<()> {
|
|
|
|
self.get_header_mut().add_tag(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn remove_tag(&mut self, t: Tag) -> Result<()> {
|
|
|
|
self.get_header_mut().remove_tag(t)
|
|
|
|
}
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn has_tag(&self, t: TagSlice) -> Result<bool> {
|
2016-02-15 13:09:11 +00:00
|
|
|
self.get_header().has_tag(t)
|
|
|
|
}
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn has_tags(&self, ts: &[Tag]) -> Result<bool> {
|
2016-02-15 13:09:11 +00:00
|
|
|
self.get_header().has_tags(ts)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2016-02-15 15:56:36 +00:00
|
|
|
|
|
|
|
impl<'a> Tagable for FileLockEntry<'a> {
|
|
|
|
|
|
|
|
fn get_tags(&self) -> Result<Vec<Tag>> {
|
|
|
|
self.deref().get_tags()
|
|
|
|
}
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn set_tags(&mut self, ts: &[Tag]) -> Result<()> {
|
2016-02-15 15:56:36 +00:00
|
|
|
self.deref_mut().set_tags(ts)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_tag(&mut self, t: Tag) -> Result<()> {
|
|
|
|
self.deref_mut().add_tag(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn remove_tag(&mut self, t: Tag) -> Result<()> {
|
|
|
|
self.deref_mut().remove_tag(t)
|
|
|
|
}
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn has_tag(&self, t: TagSlice) -> Result<bool> {
|
2016-02-15 15:56:36 +00:00
|
|
|
self.deref().has_tag(t)
|
|
|
|
}
|
|
|
|
|
2016-05-03 21:10:32 +00:00
|
|
|
fn has_tags(&self, ts: &[Tag]) -> Result<bool> {
|
2016-02-15 15:56:36 +00:00
|
|
|
self.deref().has_tags(ts)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|