Refactor everything into one trait

This commit is contained in:
Matthias Beyer 2016-02-15 14:03:56 +01:00
parent 1ca9597ad6
commit 5c92624989
6 changed files with 176 additions and 114 deletions

View file

@ -7,37 +7,4 @@ use tag::Tag;
use error::{TagError, TagErrorKind}; use error::{TagError, TagErrorKind};
pub fn add_tag(e: &mut Entry, t: &Tag) -> Result<()> { pub fn add_tag(e: &mut Entry, t: &Tag) -> Result<()> {
let tags = e.get_header().read("imag.tags");
if tags.is_err() {
let kind = TagErrorKind::HeaderReadError;
return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
}
let tags = tags.unwrap();
if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
if tags.is_none() {
return Ok(());
}
let tags = tags.unwrap();
if !match tags { Value::Array(_) => true, _ => false } {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
match tags {
Value::Array(tag_array) => {
let mut new_tags = tag_array.clone();
new_tags.push(Value::String(t.clone()));
e.get_header_mut()
.set("imag.tags", Value::Array(new_tags))
.map_err(|e| TagError::new(TagErrorKind::TagTypeError, Some(Box::new(e))))
.map(|_| ())
},
_ => unreachable!(),
}
} }

View file

@ -7,45 +7,8 @@ use tag::Tag;
use error::{TagError, TagErrorKind}; use error::{TagError, TagErrorKind};
pub fn has_tag(e: &Entry, t: &Tag) -> Result<bool> { pub fn has_tag(e: &Entry, t: &Tag) -> Result<bool> {
header_has_tag(e.get_header(), t)
} }
pub fn has_tags(e: &Entry, tags: &Vec<Tag>) -> Result<bool> { pub fn has_tags(e: &Entry, tags: &Vec<Tag>) -> Result<bool> {
let hdr = e.get_header();
let mut result = true;
for tag in tags {
let check = header_has_tag(hdr, tag);
if check.is_err() {
return Err(check.err().unwrap());
}
let check = check.unwrap();
result = result && check;
}
Ok(result)
}
fn header_has_tag(head: &EntryHeader, t: &Tag) -> Result<bool> {
let tags = head.read("imag.tags");
if tags.is_err() {
let kind = TagErrorKind::HeaderReadError;
return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
}
let tags = tags.unwrap();
if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
Ok(tags
.iter()
.any(|tag| {
match tag {
&Value::String(ref s) => { s == t },
_ => unreachable!()
}
}))
} }

View file

@ -8,12 +8,14 @@ use std::fmt;
pub enum TagErrorKind { pub enum TagErrorKind {
TagTypeError, TagTypeError,
HeaderReadError, HeaderReadError,
HeaderWriteError,
} }
fn tag_error_type_as_str(e: &TagErrorKind) -> &'static str { fn tag_error_type_as_str(e: &TagErrorKind) -> &'static str {
match e { match e {
&TagErrorKind::TagTypeError => "Entry Header Tag Type wrong", &TagErrorKind::TagTypeError => "Entry Header Tag Type wrong",
&TagErrorKind::HeaderReadError => "Error while reading entry header", &TagErrorKind::HeaderReadError => "Error while reading entry header",
&TagErrorKind::HeaderWriteError=> "Error while writing entry header",
} }
} }

View file

@ -3,10 +3,8 @@ extern crate toml;
extern crate libimagstore; extern crate libimagstore;
pub mod add;
pub mod check;
pub mod error; pub mod error;
pub mod remove;
pub mod result; pub mod result;
pub mod tag; pub mod tag;
pub mod tagable;
pub mod util; pub mod util;

View file

@ -7,45 +7,4 @@ use tag::Tag;
use error::{TagError, TagErrorKind}; use error::{TagError, TagErrorKind};
pub fn remove_tag(e: &mut Entry, t: &Tag) -> Result<()> { pub fn remove_tag(e: &mut Entry, t: &Tag) -> Result<()> {
let tags = e.get_header().read("imag.tags");
if tags.is_err() {
let kind = TagErrorKind::HeaderReadError;
return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
}
let tags = tags.unwrap();
if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
if tags.is_none() {
return Ok(());
}
let tags = tags.unwrap();
if !match tags { Value::Array(_) => true, _ => false } {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
match tags {
Value::Array(tag_array) => {
let new_tags = tag_array.iter()
.map(|tag| {
match tag {
&Value::String(ref s) => s,
_ => unreachable!(),
}
})
.filter(|tag| tag.clone() != t)
.map(|tag| Value::String(t.clone()))
.collect();
e.get_header_mut()
.set("imag.tags", Value::Array(new_tags))
.map_err(|e| TagError::new(TagErrorKind::TagTypeError, Some(Box::new(e))))
.map(|_| ())
},
_ => unreachable!(),
}
} }

173
libimagtag/src/tagable.rs Normal file
View file

@ -0,0 +1,173 @@
use libimagstore::store::{Entry, EntryHeader};
use error::{TagError, TagErrorKind};
use result::Result;
use tag::Tag;
use toml::Value;
pub trait Tagable {
fn get_tags(&self) -> Result<Vec<Tag>>;
fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()>;
fn add_tag(&mut self, t: Tag) -> Result<()>;
fn remove_tag(&mut self, t: Tag) -> Result<()>;
fn has_tag(&self, t: &Tag) -> Result<bool>;
fn has_tags(&self, ts: &Vec<Tag>) -> Result<bool>;
}
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;
return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
}
let tags = tags.unwrap();
match tags {
Some(Value::Array(tags)) => {
if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
Ok(tags.iter()
.cloned()
.map(|t| {
match t {
Value::String(s) => s,
_ => unreachable!(),
}
})
.collect())
},
None => Ok(vec![]),
_ => Err(TagError::new(TagErrorKind::TagTypeError, None)),
}
}
fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()> {
let a = ts.iter().map(|t| Value::String(t.clone())).collect();
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<()> {
let tags = self.read("imag.tags");
if tags.is_err() {
let kind = TagErrorKind::HeaderReadError;
return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
}
let tags = tags.unwrap();
if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
if tags.is_none() {
return Ok(());
}
let tags = tags.unwrap();
if !match tags { Value::Array(_) => true, _ => false } {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
match tags {
Value::Array(tag_array) => {
let mut new_tags = tag_array.clone();
new_tags.push(Value::String(t.clone()));
self.set("imag.tags", Value::Array(new_tags))
.map_err(|e| TagError::new(TagErrorKind::TagTypeError, Some(Box::new(e))))
.map(|_| ())
},
_ => unreachable!(),
}
}
fn remove_tag(&mut self, t: Tag) -> Result<()> {
let tags = self.read("imag.tags");
if tags.is_err() {
let kind = TagErrorKind::HeaderReadError;
return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
}
let tags = tags.unwrap();
if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
if tags.is_none() {
return Ok(());
}
let tags = tags.unwrap();
if !match tags { Value::Array(_) => true, _ => false } {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
match tags {
Value::Array(tag_array) => {
let mut tag_array = tag_array.clone();
tag_array.retain(|tag| {
match tag {
&Value::String(ref s) => s.clone() != t,
_ => unreachable!(),
}
});
self.set("imag.tags", Value::Array(tag_array))
.map_err(|e| TagError::new(TagErrorKind::TagTypeError, Some(Box::new(e))))
.map(|_| ())
},
_ => unreachable!(),
}
}
fn has_tag(&self, t: &Tag) -> Result<bool> {
let tags = self.read("imag.tags");
if tags.is_err() {
let kind = TagErrorKind::HeaderReadError;
return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
}
let tags = tags.unwrap();
if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
return Err(TagError::new(TagErrorKind::TagTypeError, None));
}
Ok(tags
.iter()
.any(|tag| {
match tag {
&Value::String(ref s) => { s == t },
_ => unreachable!()
}
}))
}
fn has_tags(&self, tags: &Vec<Tag>) -> Result<bool> {
let mut result = true;
for tag in tags {
let check = self.has_tag(tag);
if check.is_err() {
return Err(check.err().unwrap());
}
let check = check.unwrap();
result = result && check;
}
Ok(result)
}
}