summaryrefslogtreecommitdiffstats
path: root/src/task.rs
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2016-07-16 15:01:38 +0200
committerMalte Brandy <malte.brandy@maralorn.de>2018-04-18 00:36:24 +0200
commit0dc43d01c167e020656774849c40a7349e7e5b0f (patch)
treefff6d0d168b57a5837b4755bc534a2e6d200c85a /src/task.rs
parent1dab9869b189506f66331a994faa7149abc3e3a3 (diff)
Add basic UDA support
Diffstat (limited to 'src/task.rs')
-rw-r--r--src/task.rs321
1 files changed, 288 insertions, 33 deletions
diff --git a/src/task.rs b/src/task.rs
index cb2b806..f481c64 100644
--- a/src/task.rs
+++ b/src/task.rs
@@ -6,6 +6,15 @@
//! Module containing `Task` type as well as trait implementations
+use std::result::Result as RResult;
+use std::collections::BTreeMap;
+
+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;
@@ -14,6 +23,7 @@ use project::Project;
use tag::Tag;
use date::Date;
use annotation::Annotation;
+use uda::{UDAName, UDAValue};
/// Task type
///
@@ -29,60 +39,29 @@ 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, Deserialize, Serialize)]
+#[derive(Debug, Clone)]
pub struct Task {
status : TaskStatus,
uuid : Uuid,
entry : Date,
description : String,
-
- #[serde(skip_serializing_if = "Option::is_none")]
annotations : Option<Vec<Annotation>>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
depends : Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
due : Option<Date>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
end : Option<Date>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
imask : Option<i64>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
mask : Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
modified : Option<Date>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
parent : Option<Uuid>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
priority : Option<TaskPriority>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
project : Option<Project>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
recur : Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
scheduled : Option<Date>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
start : Option<Date>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
tags : Option<Vec<Tag>>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
until : Option<Date>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
wait : Option<Date>,
+ uda : BTreeMap<UDAName, UDAValue>,
}
/*
@@ -114,6 +93,7 @@ impl Task {
tags : Option<Vec<Tag>>,
until : Option<Date>,
wait : Option<Date>,
+ uda : BTreeMap<UDAName, UDAValue>,
) -> Task
{
Task {
@@ -138,6 +118,7 @@ impl Task {
tags : tags,
until : until,
wait : wait,
+ uda : uda,
}
}
@@ -345,9 +326,283 @@ impl Task {
pub fn wait_mut(&mut self) -> Option<&mut Date> {
self.wait.as_mut()
}
+ /// Get the BTreeMap that contains the UDA
+ pub fn uda(&self) -> &BTreeMap<UDAName, UDAValue> {
+ &self.uda
+
+ /// Get the BTreeMap that contains the UDA mutable
+ pub fn uda(&mut self) -> &mut BTreeMap<UDAName, UDAValue> {
+ &self.uda
+}
+
+impl Serialize for Task {
+
+ fn serialize<S>(&self, serializer: &mut S) -> RResult<(), S::Error>
+ where S: Serializer
+ {
+ let mut state = try!(serializer.serialize_struct("Task", 19));
+ try!(serializer.serialize_struct_elt(&mut state, "status", &self.status));
+ try!(serializer.serialize_struct_elt(&mut state, "uuid", &self.uuid));
+ try!(serializer.serialize_struct_elt(&mut state, "entry", &self.entry));
+ try!(serializer.serialize_struct_elt(&mut state, "description", &self.description));
+ try!(serializer.serialize_struct_elt(&mut state, "annotations", &self.annotations));
+ try!(serializer.serialize_struct_elt(&mut state, "tags", &self.tags));
+
+ match self.recur {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "recur", v)),
+ None => { },
+ }
+ match self.depends {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "depends", v)),
+ None => { },
+ }
+ match self.due {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "due", v)),
+ None => { },
+ }
+ match self.end {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "end", v)),
+ None => { },
+ }
+ match self.imask {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "imask", v)),
+ None => { },
+ }
+ match self.mask {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "mask", v)),
+ None => { },
+ }
+ match self.modified {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "modified", v)),
+ None => { },
+ }
+ match self.parent {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "parent", v)),
+ None => { },
+ }
+ match self.priority {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "priority", v)),
+ None => { },
+ }
+ match self.project {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "project", v)),
+ None => { },
+ }
+ match self.scheduled {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "scheduled", v)),
+ None => { },
+ }
+ match self.start {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "start", v)),
+ None => { },
+ }
+ match self.until {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "until", v)),
+ None => { },
+ }
+ match self.wait {
+ Some(ref v) => try!(serializer.serialize_struct_elt(&mut state, "wait", v)),
+ None => { },
+ }
+
+ serializer.serialize_struct_end(state)
+ }
}
+impl Deserialize for Task {
+
+ fn deserialize<D>(deserializer: &mut D) -> RResult<Task, D::Error>
+ 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 visit_map<V>(&mut self, mut visitor: V) -> RResult<Task, V::Error>
+ where V: DeserializeMapVisitor
+ {
+ 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<String> = 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 => try!(visitor.missing_field("status")),
+ };
+
+ let uuid = match uuid {
+ Some(uuid) => uuid,
+ None => try!(visitor.missing_field("uuid")),
+ };
+
+ let entry = match entry {
+ Some(entry) => entry,
+ None => try!(visitor.missing_field("entry")),
+ };
+
+ let description = match description {
+ Some(description) => description,
+ None => try!(visitor.missing_field("description")),
+ };
+
+ try!(visitor.end());
+
+ 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;