From f3bb6d02d0a04e8897cf59253a2e7e7fb59401bc Mon Sep 17 00:00:00 2001 From: Mario Krehl Date: Sat, 2 Sep 2017 12:23:29 +0200 Subject: [PATCH] Change the Task(FileLockEntry) type to a trait --- lib/domain/libimagtodo/src/task.rs | 158 ++++++++--------------------- 1 file changed, 42 insertions(+), 116 deletions(-) diff --git a/lib/domain/libimagtodo/src/task.rs b/lib/domain/libimagtodo/src/task.rs index 3dbbd04c..260d1a3a 100644 --- a/lib/domain/libimagtodo/src/task.rs +++ b/lib/domain/libimagtodo/src/task.rs @@ -18,8 +18,8 @@ // use std::collections::BTreeMap; -use std::ops::{Deref, DerefMut}; use std::io::BufRead; +use std::marker::Sized; use std::result::Result as RResult; use toml::Value; @@ -29,31 +29,43 @@ use task_hookrs::task::Task as TTask; use task_hookrs::import::{import_task, import_tasks}; use libimagstore::store::{FileLockEntry, Store}; -use libimagstore::storeid::{IntoStoreId, StoreIdIterator, StoreId}; +use libimagstore::storeid::{IntoStoreId, StoreIdIterator}; use module_path::ModuleEntryPath; use error::{TodoErrorKind as TEK, MapErrInto}; use result::Result; /// Task struct containing a `FileLockEntry` -#[derive(Debug)] -pub struct Task<'a>(FileLockEntry<'a>); +pub trait Task<'a> { + fn import_task_from_reader(store: &'a Store, r: R) -> Result<(Self, String, Uuid)> + where Self: Sized; + fn get_task_from_import(store: &'a Store, r: R) -> Result> + where Self: Sized; + fn get_task_from_string(store: &'a Store, s: String) -> Result> + where Self: Sized; + fn get_task_from_uuid(store: &'a Store, uuid: Uuid) -> Result> + where Self: Sized; + fn retrieve_task_from_import(store: &'a Store, r: R) -> Result + where Self: Sized; + fn retrieve_task_from_string(store: &'a Store, s: String) -> Result + where Self: Sized; + fn delete_tasks_by_imports(store: &Store, r: R) -> Result<()>; + fn delete_task_by_uuid(store: &Store, uuid: Uuid) -> Result<()>; + fn all_tasks(store: &Store) -> Result; + fn new_from_twtask(store: &'a Store, task: TTask) -> Result + where Self: Sized; +} -impl<'a> Task<'a> { +impl<'a> Task<'a> for FileLockEntry<'a> { - /// Concstructs a new `Task` with a `FileLockEntry` - pub fn new(fle: FileLockEntry<'a>) -> Task<'a> { - Task(fle) - } - - pub fn import(store: &'a Store, mut r: R) -> Result<(Task<'a>, String, Uuid)> { + fn import_task_from_reader(store: &'a Store, mut r: R) -> Result<(FileLockEntry<'a>, String, Uuid)> { let mut line = String::new(); try!(r.read_line(&mut line).map_err_into(TEK::UTF8Error)); import_task(&line.as_str()) .map_err_into(TEK::ImportError) .and_then(|t| { let uuid = t.uuid().clone(); - t.into_task(store).map(|t| (t, line, uuid)) + Self::new_from_twtask(store, t).map(|t| (t, line, uuid)) }) } @@ -66,23 +78,21 @@ impl<'a> Task<'a> { /// * Ok(Err(String)) - where the String is the String read from the `r` parameter /// * Err(_) - where the error is an error that happened during evaluation /// - pub fn get_from_import(store: &'a Store, mut r: R) -> Result, String>> - where R: BufRead - { + fn get_task_from_import(store: &'a Store, mut r: R) -> Result, String>> { let mut line = String::new(); try!(r.read_line(&mut line).map_err_into(TEK::UTF8Error)); - Task::get_from_string(store, line) + Self::get_task_from_string(store, line) } /// Get a task from a String. The String is expected to contain the JSON-representation of the /// Task to get from the store (only the UUID really matters in this case) /// /// For an explanation on the return values see `Task::get_from_import()`. - pub fn get_from_string(store: &'a Store, s: String) -> Result, String>> { + fn get_task_from_string(store: &'a Store, s: String) -> Result, String>> { import_task(s.as_str()) .map_err_into(TEK::ImportError) .map(|t| t.uuid().clone()) - .and_then(|uuid| Task::get_from_uuid(store, uuid)) + .and_then(|uuid| Self::get_task_from_uuid(store, uuid)) .and_then(|o| match o { None => Ok(Err(s)), Some(t) => Ok(Ok(t)), @@ -92,35 +102,34 @@ impl<'a> Task<'a> { /// Get a task from an UUID. /// /// If there is no task with this UUID, this returns `Ok(None)`. - pub fn get_from_uuid(store: &'a Store, uuid: Uuid) -> Result>> { + fn get_task_from_uuid(store: &'a Store, uuid: Uuid) -> Result>> { ModuleEntryPath::new(format!("taskwarrior/{}", uuid)) .into_storeid() .and_then(|store_id| store.get(store_id)) - .map(|o| o.map(Task::new)) .map_err_into(TEK::StoreError) } /// Same as Task::get_from_import() but uses Store::retrieve() rather than Store::get(), to /// implicitely create the task if it does not exist. - pub fn retrieve_from_import(store: &'a Store, mut r: R) -> Result> { + fn retrieve_task_from_import(store: &'a Store, mut r: R) -> Result> { let mut line = String::new(); try!(r.read_line(&mut line).map_err_into(TEK::UTF8Error)); - Task::retrieve_from_string(store, line) + Self::retrieve_task_from_string(store, line) } /// Retrieve a task from a String. The String is expected to contain the JSON-representation of /// the Task to retrieve from the store (only the UUID really matters in this case) - pub fn retrieve_from_string(store: &'a Store, s: String) -> Result> { - Task::get_from_string(store, s) + fn retrieve_task_from_string(store: &'a Store, s: String) -> Result> { + Self::get_task_from_string(store, s) .and_then(|opt| match opt { Ok(task) => Ok(task), Err(string) => import_task(string.as_str()) .map_err_into(TEK::ImportError) - .and_then(|t| t.into_task(store)), + .and_then(|t| Self::new_from_twtask(store, t)), }) } - pub fn delete_by_imports(store: &Store, r: R) -> Result<()> { + fn delete_tasks_by_imports(store: &Store, r: R) -> Result<()> { use serde_json::ser::to_string as serde_to_string; use task_hookrs::status::TaskStatus; @@ -144,7 +153,7 @@ impl<'a> Task<'a> { // Here we check if the status of a task is deleted and if yes, we delete it // from the store. if *ttask.status() == TaskStatus::Deleted { - match Task::delete_by_uuid(store, *ttask.uuid()) { + match Self::delete_task_by_uuid(store, *ttask.uuid()) { Ok(_) => info!("Deleted task {}", *ttask.uuid()), Err(e) => return Err(e), } @@ -157,70 +166,23 @@ impl<'a> Task<'a> { Ok(()) } - pub fn delete_by_uuid(store: &Store, uuid: Uuid) -> Result<()> { + fn delete_task_by_uuid(store: &Store, uuid: Uuid) -> Result<()> { ModuleEntryPath::new(format!("taskwarrior/{}", uuid)) .into_storeid() .and_then(|id| store.delete(id)) .map_err_into(TEK::StoreError) } - pub fn all_as_ids(store: &Store) -> Result { + fn all_tasks(store: &Store) -> Result { store.retrieve_for_module("todo/taskwarrior") .map_err_into(TEK::StoreError) } - pub fn all(store: &Store) -> Result { - Task::all_as_ids(store) - .map(|iter| TaskIterator::new(store, iter)) - } - -} - -impl<'a> Deref for Task<'a> { - type Target = FileLockEntry<'a>; - - fn deref(&self) -> &FileLockEntry<'a> { - &self.0 - } - -} - -impl<'a> DerefMut for Task<'a> { - - fn deref_mut(&mut self) -> &mut FileLockEntry<'a> { - &mut self.0 - } - -} - -/// A trait to get a `libimagtodo::task::Task` out of the implementing object. -pub trait IntoTask<'a> { - - /// # Usage - /// ```ignore - /// use std::io::stdin; - /// - /// use task_hookrs::task::Task; - /// use task_hookrs::import::import; - /// use libimagstore::store::{Store, FileLockEntry}; - /// - /// if let Ok(task_hookrs_task) = import(stdin()) { - /// // Store is given at runtime - /// let task = task_hookrs_task.into_filelockentry(store); - /// println!("Task with uuid: {}", task.flentry.get_header().get("todo.uuid")); - /// } - /// ``` - fn into_task(self, store : &'a Store) -> Result>; - -} - -impl<'a> IntoTask<'a> for TTask { - - fn into_task(self, store : &'a Store) -> Result> { + fn new_from_twtask(store: &'a Store, task: TTask) -> Result> { use toml_query::read::TomlValueReadExt; use toml_query::set::TomlValueSetExt; - let uuid = self.uuid(); + let uuid = task.uuid(); ModuleEntryPath::new(format!("taskwarrior/{}", uuid)) .into_storeid() .map_err_into(TEK::StoreIdError) @@ -241,47 +203,11 @@ impl<'a> IntoTask<'a> for TTask { } // If none of the errors above have returned the function, everything is fine - Ok(Task::new(fle)) + Ok(fle) }) }) + } } -trait FromStoreId { - fn from_storeid<'a>(&'a Store, StoreId) -> Result>; -} - -impl<'a> FromStoreId for Task<'a> { - - fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result> { - store.retrieve(id) - .map_err_into(TEK::StoreError) - .map(Task::new) - } -} - -pub struct TaskIterator<'a> { - store: &'a Store, - iditer: StoreIdIterator, -} - -impl<'a> TaskIterator<'a> { - - pub fn new(store: &'a Store, iditer: StoreIdIterator) -> TaskIterator<'a> { - TaskIterator { - store: store, - iditer: iditer, - } - } - -} - -impl<'a> Iterator for TaskIterator<'a> { - type Item = Result>; - - fn next(&mut self) -> Option>> { - self.iditer.next().map(|id| Task::from_storeid(self.store, id)) - } -} -