From 4cf63eb00d9e43056f40b122642b2e40a7ee120e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 3 Feb 2017 08:31:48 +0100 Subject: Try out whether deriving works --- src/annotation.rs | 99 +------------------ src/lib.rs | 2 +- src/priority.rs | 59 +---------- src/status.rs | 62 +----------- src/task.rs | 286 +----------------------------------------------------- 5 files changed, 6 insertions(+), 502 deletions(-) diff --git a/src/annotation.rs b/src/annotation.rs index a56c41b..5f43e2d 100644 --- a/src/annotation.rs +++ b/src/annotation.rs @@ -6,23 +6,12 @@ //! Module containing types and functions for annotations of tasks -use std::result::Result as RResult; -use std::fmt::Formatter; -use std::fmt::Result as FmtResult; - -use serde::Serialize; -use serde::Serializer; -use serde::Deserialize; -use serde::Deserializer; -use serde::de::Visitor; -use serde::de::MapVisitor as DeserializeMapVisitor; - use date::Date; /// Annotation type for task annotations. /// Each annotation in taskwarrior consists of a date and a description, /// the date is named "entry", the description "description" in the JSON export. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Annotation { entry: Date, description: String @@ -50,92 +39,6 @@ impl Annotation { } -impl Serialize for Annotation { - - fn serialize(&self, serializer: S) -> RResult - where S: Serializer - { - use serde::ser::SerializeStruct; - - let mut state = try!(serializer.serialize_struct("Annotation", 2)); - try!(state.serialize_field("entry", &self.entry)); - try!(state.serialize_field("description", &self.description)); - state.end() - } - -} - -impl Deserialize for Annotation { - - fn deserialize(deserializer: D) -> RResult - where D: Deserializer - { - static FIELDS: &'static [&'static str] = &[ - "entry", - "description" - ]; - - deserializer.deserialize_struct("Annotation", FIELDS, AnnotationDeserializeVisitor) - } - -} - -/// Helper type for the `Deserialize` implementation -struct AnnotationDeserializeVisitor; - -impl Visitor for AnnotationDeserializeVisitor { - type Value = Annotation; - - fn expecting(&self, fmt: &mut Formatter) -> FmtResult { - write!(fmt, "a taskwarrior annotation object") - } - - fn visit_map(self, mut visitor: V) -> RResult - where V: DeserializeMapVisitor - { - use serde::de::Error; - - let mut entry = None; - let mut description = None; - - loop { - let key : Option = try!(visitor.visit_key()); - if key.is_none() { - break; - } - let key = key.unwrap(); - - match &key[..] { - "entry" => { - entry = Some(try!(visitor.visit_value())); - }, - "description" => { - description = Some(try!(visitor.visit_value())); - }, - - field => { - use serde::de::impls::IgnoredAny; - - debug!("field '{}' ignored", field); - let _: IgnoredAny = try!(visitor.visit_value()); - } - } - } - - let entry = match entry { - Some(entry) => entry, - None => return Err(V::Error::missing_field("entry")), - }; - - let description = match description { - Some(description) => description, - None => return Err(V::Error::missing_field("description")), - }; - - Ok(Annotation::new(entry, description)) - } -} - #[cfg(test)] mod test { } diff --git a/src/lib.rs b/src/lib.rs index dc6ee48..2ed6b3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ )] extern crate chrono; -#[macro_use] extern crate log; +extern crate log; extern crate serde; #[macro_use] extern crate serde_derive; extern crate serde_json; diff --git a/src/priority.rs b/src/priority.rs index d9a2554..20fd673 100644 --- a/src/priority.rs +++ b/src/priority.rs @@ -6,18 +6,8 @@ //! Module containing TaskPriority types and trait impls -use serde::Serialize; -use serde::ser::Serializer; -use serde::de::Deserialize; -use serde::de::Deserializer; -use serde::de::Error as DeError; -use serde::de::Visitor; - -use std::fmt::Formatter; -use std::fmt::Result as FmtResult; - /// Enum for the priorities taskwarrior supports. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum TaskPriority { /// Low prio for a Task Low, @@ -29,50 +19,3 @@ pub enum TaskPriority { High, } - -impl Serialize for TaskPriority { - - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - serializer.serialize_str( - match self { - &TaskPriority::Low => "L", - &TaskPriority::Medium => "M", - &TaskPriority::High => "H", - } - ) - } - -} - -impl Deserialize for TaskPriority { - - fn deserialize(deserializer: D) -> Result - where D: Deserializer - { - struct TaskPriorityVisitor; - - impl Visitor for TaskPriorityVisitor { - type Value = TaskPriority; - - fn expecting(&self, fmt: &mut Formatter) -> FmtResult { - write!(fmt, "one of 'L', 'M', 'H'") - } - - fn visit_str(self, value: &str) -> Result - where E: DeError - { - match value { - "L" => Ok(TaskPriority::Low), - "M" => Ok(TaskPriority::Medium), - "H" => Ok(TaskPriority::High), - _ => Err(DeError::custom("expected one of 'L', 'M', 'H'")), - } - } - } - - deserializer.deserialize(TaskPriorityVisitor) - } -} - diff --git a/src/status.rs b/src/status.rs index 8cdf420..5a0004c 100644 --- a/src/status.rs +++ b/src/status.rs @@ -6,19 +6,10 @@ //! Module containing `TaskStatus` type and trait impls -use std::fmt::{Display, Formatter}; -use std::fmt::Error as FmtError; -use std::fmt::Result as FmtResult; - -use serde::Serialize; -use serde::Serializer; -use serde::Deserialize; -use serde::Deserializer; -use serde::de::Error; -use serde::de::Visitor; +use std::fmt::{Display, Formatter, Error as FmtError}; /// Enum for status taskwarrior supports. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub enum TaskStatus { /// Pening status type Pending, @@ -49,52 +40,3 @@ impl Display for TaskStatus { } } -impl Serialize for TaskStatus { - - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - serializer.serialize_str( - match self { - &TaskStatus::Pending => "pending", - &TaskStatus::Deleted => "deleted", - &TaskStatus::Completed => "completed", - &TaskStatus::Waiting => "waiting", - &TaskStatus::Recurring => "recurring", - } - ) - } - -} - -impl Deserialize for TaskStatus { - fn deserialize(deserializer: D) -> Result - where D: Deserializer - { - struct TaskStatusVisitor; - - impl Visitor for TaskStatusVisitor { - type Value = TaskStatus; - - fn expecting(&self, fmt: &mut Formatter) -> FmtResult { - write!(fmt, "a taskwarrior status ('pending', 'deleted', ...)") - } - - fn visit_str(self, value: &str) -> Result - where E: Error - { - match value { - "pending" => Ok(TaskStatus::Pending), - "deleted" => Ok(TaskStatus::Deleted), - "completed" => Ok(TaskStatus::Completed), - "waiting" => Ok(TaskStatus::Waiting), - "recurring" => Ok(TaskStatus::Recurring), - _ => Err(Error::custom("expected one of pending, deleted, completed, waiting, recurring")), - } - } - } - - deserializer.deserialize(TaskStatusVisitor) - } -} - diff --git a/src/task.rs b/src/task.rs index c28d8ea..bb0c19f 100644 --- a/src/task.rs +++ b/src/task.rs @@ -6,16 +6,6 @@ //! Module containing `Task` type as well as trait implementations -use std::result::Result as RResult; -use std::fmt::Formatter; -use std::fmt::Result as FmtResult; - -use serde::Serialize; -use serde::Serializer; -use serde::Deserialize; -use serde::Deserializer; -use serde::de::Visitor; -use serde::de::MapVisitor as DeserializeMapVisitor; use uuid::Uuid; use priority::TaskPriority; @@ -39,7 +29,7 @@ use annotation::Annotation; /// /// It is deserializeable and serializeable via serde_json, so importing and exporting taskwarrior /// tasks is simply serializing and deserializing objects of this type. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct Task { status : TaskStatus, uuid : Uuid, @@ -238,280 +228,6 @@ impl Task { } -impl Serialize for Task { - - fn serialize(&self, serializer: S) -> RResult - where S: Serializer - { - use serde::ser::SerializeStruct; - - let mut state = try!(serializer.serialize_struct("Task", 19)); - try!(state.serialize_field("status", &self.status)); - try!(state.serialize_field("uuid", &self.uuid)); - try!(state.serialize_field("entry", &self.entry)); - try!(state.serialize_field("description", &self.description)); - try!(state.serialize_field("annotations", &self.annotations)); - try!(state.serialize_field("tags", &self.tags)); - - match self.recur { - Some(ref v) => try!(state.serialize_field("recur", v)), - None => { }, - } - match self.depends { - Some(ref v) => try!(state.serialize_field("depends", v)), - None => { }, - } - match self.due { - Some(ref v) => try!(state.serialize_field("due", v)), - None => { }, - } - match self.end { - Some(ref v) => try!(state.serialize_field("end", v)), - None => { }, - } - match self.imask { - Some(ref v) => try!(state.serialize_field("imask", v)), - None => { }, - } - match self.mask { - Some(ref v) => try!(state.serialize_field("mask", v)), - None => { }, - } - match self.modified { - Some(ref v) => try!(state.serialize_field("modified", v)), - None => { }, - } - match self.parent { - Some(ref v) => try!(state.serialize_field("parent", v)), - None => { }, - } - match self.priority { - Some(ref v) => try!(state.serialize_field("priority", v)), - None => { }, - } - match self.project { - Some(ref v) => try!(state.serialize_field("project", v)), - None => { }, - } - match self.scheduled { - Some(ref v) => try!(state.serialize_field("scheduled", v)), - None => { }, - } - match self.start { - Some(ref v) => try!(state.serialize_field("start", v)), - None => { }, - } - match self.until { - Some(ref v) => try!(state.serialize_field("until", v)), - None => { }, - } - match self.wait { - Some(ref v) => try!(state.serialize_field("wait", v)), - None => { }, - } - - state.end() - } - -} - -impl Deserialize for Task { - - fn deserialize(deserializer: D) -> RResult - where D: Deserializer - { - static FIELDS: &'static [&'static str] = &[ - "status", - "uuid", - "entry", - "description", - - "annotations", - "depends", - "due", - "end", - "imask", - "mask", - "modified", - "parent", - "priority", - "project", - "recur", - "scheduled", - "start", - "tags", - "until", - "wait" - ]; - deserializer.deserialize_struct("Task", FIELDS, TaskDeserializeVisitor) - } - -} - -/// Helper type for task deserialization -struct TaskDeserializeVisitor; - -impl Visitor for TaskDeserializeVisitor { - type Value = Task; - - fn expecting(&self, fmt: &mut Formatter) -> FmtResult { - write!(fmt, "a taskwarrior exported JSON object") - } - - fn visit_map(self, mut visitor: V) -> RResult - where V: DeserializeMapVisitor - { - use serde::de::Error; - - let mut status = None; - let mut uuid = None; - let mut entry = None; - let mut description = None; - - let mut annotations = None; - let mut depends = None; - let mut due = None; - let mut end = None; - let mut imask = None; - let mut mask = None; - let mut modified = None; - let mut parent = None; - let mut priority = None; - let mut project = None; - let mut recur = None; - let mut scheduled = None; - let mut start = None; - let mut tags = None; - let mut until = None; - let mut wait = None; - - loop { - let key : Option = try!(visitor.visit_key()); - if key.is_none() { - break; - } - let key = key.unwrap(); - - match &key[..] { - "status" => { - status = Some(try!(visitor.visit_value())); - }, - "uuid" => { - uuid = Some(try!(visitor.visit_value())); - }, - "entry" => { - entry = Some(try!(visitor.visit_value())); - }, - "description" => { - description = Some(try!(visitor.visit_value())); - }, - - "annotations" => { - annotations = Some(try!(visitor.visit_value())); - }, - "depends" => { - depends = Some(try!(visitor.visit_value())); - }, - "due" => { - due = Some(try!(visitor.visit_value())); - }, - "end" => { - end = Some(try!(visitor.visit_value())); - }, - "imask" => { - imask = Some(try!(visitor.visit_value())); - }, - "mask" => { - mask = Some(try!(visitor.visit_value())); - }, - "modified" => { - modified = Some(try!(visitor.visit_value())); - }, - "parent" => { - parent = Some(try!(visitor.visit_value())); - }, - "priority" => { - priority = Some(try!(visitor.visit_value())); - }, - "project" => { - project = Some(try!(visitor.visit_value())); - }, - "recur" => { - recur = Some(try!(visitor.visit_value())); - }, - "scheduled" => { - scheduled = Some(try!(visitor.visit_value())); - }, - "start" => { - start = Some(try!(visitor.visit_value())); - }, - "tags" => { - tags = Some(try!(visitor.visit_value())); - }, - "until" => { - until = Some(try!(visitor.visit_value())); - }, - "wait" => { - wait = Some(try!(visitor.visit_value())); - }, - - field => { - use serde::de::impls::IgnoredAny; - - debug!("field '{}' ignored", field); - let _: IgnoredAny = try!(visitor.visit_value()); - } - } - } - - let status = match status { - Some(status) => status, - None => return Err(V::Error::missing_field("status")), - }; - - let uuid = match uuid { - Some(uuid) => uuid, - None => return Err(V::Error::missing_field("uuid")), - }; - - let entry = match entry { - Some(entry) => entry, - None => return Err(V::Error::missing_field("entry")), - }; - - let description = match description { - Some(description) => description, - None => return Err(V::Error::missing_field("description")), - }; - - let task = Task::new( - status, - uuid, - entry, - description, - - annotations, - depends, - due, - end, - imask, - mask, - modified, - parent, - priority, - project, - recur, - scheduled, - start, - tags, - until, - wait - ); - - Ok(task) - } -} - #[cfg(test)] mod test { use date::Date; -- cgit v1.2.3