1use std::io::BufRead;
10use std::io::Read;
11
12use serde_json;
13
14use crate::error::Error;
15use crate::task::{Task, TaskWarriorVersion};
16
17pub fn import<T: TaskWarriorVersion, R: Read>(r: R) -> Result<Vec<Task<T>>, Error> {
20 serde_json::from_reader(r).map_err(Error::from)
21}
22
23pub fn import_task<T: TaskWarriorVersion>(s: &str) -> Result<Task<T>, Error> {
25 serde_json::from_str(s).map_err(Error::from)
26}
27
28pub fn import_tasks<T: TaskWarriorVersion, BR: BufRead>(r: BR) -> Vec<Result<Task<T>, Error>> {
30 let mut vt = Vec::new();
31 for line in r.lines() {
32 if let Err(err) = line {
33 vt.push(Err(Error::from(err)));
34 continue;
35 }
36 if line.as_ref().unwrap().is_empty() {
38 continue;
40 }
41 vt.push(import_task(line.unwrap().as_str()));
42 }
43 vt
44}
45
46#[cfg(test)]
47mod test {
48 use crate::import::{import, import_task, import_tasks};
49 use crate::task::{Task, TW25, TW26};
50
51 #[test]
52 fn test_one_tw25() {
53 let s = r#"
54[
55 {
56 "id": 1,
57 "description": "some description",
58 "entry": "20150619T165438Z",
59 "modified": "20160327T164007Z",
60 "project": "someproject",
61 "status": "waiting",
62 "tags": ["some", "tags", "are", "here"],
63 "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
64 "depends": "8ca953d5-18b5-4eb9-bd56-18f2e5b752f0",
65 "wait": "20160508T164007Z",
66 "urgency": 0.583562
67 }
68]
69"#;
70
71 let imported = import::<TW25, _>(s.as_bytes());
72 assert!(imported.is_ok());
73 let imported = imported.unwrap();
74 assert!(imported.len() == 1);
75 }
76
77 #[test]
78 fn test_one_tw26() {
79 let s = r#"
80[
81 {
82 "id": 1,
83 "description": "some description",
84 "entry": "20150619T165438Z",
85 "modified": "20160327T164007Z",
86 "project": "someproject",
87 "status": "waiting",
88 "tags": ["some", "tags", "are", "here"],
89 "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
90 "depends": ["8ca953d5-18b5-4eb9-bd56-18f2e5b752f0"],
91 "wait": "20160508T164007Z",
92 "urgency": 0.583562
93 }
94]
95"#;
96
97 let imported = import::<TW26, _>(s.as_bytes());
98 assert!(imported.is_ok());
99 let imported = imported.unwrap();
100 assert!(imported.len() == 1);
101 }
102
103 #[test]
104 fn test_two_tw25() {
105 let s = r#"
106[
107 {
108 "id" : 1,
109 "description" : "test",
110 "entry" : "20150619T165438Z",
111 "modified" : "20160327T164007Z",
112 "project" : "self.software",
113 "status" : "waiting",
114 "tags" : ["check", "this", "crate", "out"],
115 "uuid" : "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
116 "wait" : "20160508T164007Z",
117 "urgency" : 0.583562
118 },
119 {
120 "id" : 2,
121 "description" : "another test",
122 "entry" : "20150623T181011Z",
123 "modified" : "20160327T163718Z",
124 "priority" : "L",
125 "project" : "studying",
126 "status" : "waiting",
127 "tags" : ["I", "have", "awesome", "kittens"],
128 "uuid" : "54d49ffc-a06b-4dd8-b7d1-db5f50594312",
129 "wait" : "20160508T163718Z",
130 "annotations" : [
131 {
132 "entry" : "20150623T181018Z",
133 "description" : "fooooooobar"
134 }
135 ],
136 "urgency" : 3.16164
137 },
138 {
139 "id" : 3,
140 "description" : "I love kittens, really!",
141 "entry" : "20150919T222323Z",
142 "modified" : "20160327T163718Z",
143 "project" : "getkittens",
144 "status" : "waiting",
145 "tags" : ["kittens", "are", "so", "damn", "awesome"],
146 "uuid" : "08ee8dce-cb97-4c8c-9940-c9a440e90119",
147 "wait" : "20160508T163718Z",
148 "urgency" : 1.07397
149 }
150]
151
152"#;
153
154 assert!(import::<TW25, _>(s.as_bytes()).unwrap().len() == 3);
155 }
156
157 #[test]
158 fn test_one_single_tw25() {
159 use crate::date::Date;
160 use crate::date::TASKWARRIOR_DATETIME_TEMPLATE;
161 use crate::status::TaskStatus;
162 use chrono::NaiveDateTime;
163 use uuid::Uuid;
164 fn mkdate(s: &str) -> Date {
165 let n = NaiveDateTime::parse_from_str(s, TASKWARRIOR_DATETIME_TEMPLATE);
166 Date::from(n.unwrap())
167 }
168 let s = r#"
169{
170 "id": 1,
171 "description": "some description",
172 "entry": "20150619T165438Z",
173 "modified": "20160327T164007Z",
174 "project": "someproject",
175 "status": "waiting",
176 "tags": ["some", "tags", "are", "here"],
177 "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
178 "wait": "20160508T164007Z",
179 "urgency": 0.583562
180}
181"#;
182 let imported = import_task(s);
183 assert!(imported.is_ok());
184
185 let task: Task<TW25> = imported.unwrap();
187 assert_eq!(*task.status(), TaskStatus::Waiting);
188 assert_eq!(task.description(), "some description");
189 assert_eq!(*task.entry(), mkdate("20150619T165438Z"));
190 assert_eq!(
191 *task.uuid(),
192 Uuid::parse_str("8ca953d5-18b4-4eb9-bd56-18f2e5b752f0").unwrap()
193 );
194 assert_eq!(task.modified(), Some(&mkdate("20160327T164007Z")));
195 assert_eq!(task.project(), Some(&String::from("someproject")));
196 if let Some(tags) = task.tags() {
197 for tag in tags {
198 let any_tag = ["some", "tags", "are", "here"].iter().any(|t| tag == *t);
199 assert!(any_tag, "Tag {} missing", tag);
200 }
201 } else {
202 panic!("Tags completely missing");
203 }
204
205 assert_eq!(task.wait(), Some(&mkdate("20160508T164007Z")));
206 }
207
208 #[test]
209 fn test_two_single_tw25() {
210 use crate::status::TaskStatus;
211 use std::io::BufReader;
212 let s = r#"
213{"id":1,"description":"some description","entry":"20150619T165438Z","modified":"20160327T164007Z","project":"someproject","status":"waiting","tags":["some","tags","are","here"],"uuid":"8ca953d5-18b4-4eb9-bd56-18f2e5b752f0","wait":"20160508T164007Z","urgency":0.583562}
214{"id":1,"description":"some description","entry":"20150619T165438Z","modified":"20160327T164007Z","project":"someproject","status":"waiting","tags":["some","tags","are","here"],"uuid":"8ca953d5-18b4-4eb9-bd56-18f2e5b752f0","wait":"20160508T164007Z","urgency":0.583562}"#;
215 let imported = import_tasks(BufReader::new(s.as_bytes()));
216 assert_eq!(imported.len(), 2);
217 assert!(imported[0].is_ok());
218 assert!(imported[1].is_ok());
219 let import0: &Task<TW25> = imported[0].as_ref().unwrap();
220 let import1 = imported[1].as_ref().unwrap();
221 assert_eq!(*import0.status(), TaskStatus::Waiting);
222 assert_eq!(*import1.status(), TaskStatus::Waiting);
223 }
224}