1use std::collections::BTreeMap;
10use std::collections::btree_map::Iter;
11use std::iter::Peekable;
12
13use toml::Value;
14
15use item_def::ItemDef;
16use notify::Notify;
17
18enum State
21{
22 Normal,
25
26 Done,
29
30 UnknownInput,
33
34 MissingInput
37}
38
39pub enum Next<'a, 'b, 'c>
42{
43 NextItem(&'a String, &'a Value, &'b Box<ItemDef>, Option<&'c Box<Notify>>),
46
47 UnknownInput(&'a String, &'a Value),
50
51 MissingInput(&'b String, &'b Box<ItemDef>, Option<&'c Box<Notify>>),
54
55}
56
57pub struct TomlIter<'a, 'b, 'c>
61{
62 input_iter : Peekable<Iter<'a, String, Value>>,
65
66 define_iter : Peekable<Iter<'b, String, Box<ItemDef>>>,
69
70 notify_iter : Peekable<Iter<'c, String, Box<Notify>>>
73}
74
75impl<'a, 'b, 'c> TomlIter<'a, 'b, 'c>
76{
77 pub fn new(
80 input : &'a BTreeMap<String, Value>,
81 define : &'b BTreeMap<String, Box<ItemDef>>,
82 notify : &'c BTreeMap<String, Box<Notify>>
83 ) -> TomlIter<'a, 'b, 'c>
84 {
85 TomlIter {
86 input_iter : input.iter().peekable(),
87 define_iter : define.iter().peekable(),
88 notify_iter : notify.iter().peekable()
89 }
90 }
91
92 fn state(&mut self) -> State
95 {
96 let input = self.input_iter.peek();
97 let definition = self.define_iter.peek();
98
99 if input.is_some() && definition.is_some()
103 {
104 let &(input_name, _) = input.unwrap();
105 let &(def_name, _) = definition.unwrap();
106
107 if input_name < def_name
111 {
112 State::UnknownInput
113 }
114 else if def_name < input_name
118 {
119 State::MissingInput
120 }
121 else
124 {
125 State::Normal
126 }
127 }
128 else if input.is_some()
132 {
133 State::UnknownInput
134 }
135 else if definition.is_some()
138 {
139 State::MissingInput
140 }
141 else
144 {
145 State::Done
146 }
147 }
148
149 fn notification(
152 &mut self,
153 name : &String
154 ) -> Option<&'c Box<Notify>>
155 {
156 if let Some(&(notify_name, _)) = self.notify_iter.peek()
157 {
158 if name == notify_name
159 {
160 let (_, notify_value) = self.notify_iter.next().unwrap();
161
162 Some(notify_value)
163 }
164 else
165 {
166 None
167 }
168 }
169 else
170 {
171 None
172 }
173 }
174
175 fn unknown_item(&mut self) -> Next<'a, 'b, 'c>
178 {
179 let (name, value) = self.input_iter.next().unwrap();
180
181 Next::UnknownInput(name, value)
182 }
183
184 fn missing_item(&mut self) -> Next<'a, 'b, 'c>
188 {
189 let (name, value) = self.define_iter.next().unwrap();
190 let notify = self.notification(name);
191
192 Next::MissingInput(name, value, notify)
193 }
194
195 fn next_item(&mut self) -> Next<'a, 'b, 'c>
199 {
200 let (name, value) = self.input_iter.next().unwrap();
201 let (_, define) = self.define_iter.next().unwrap();
202 let notify = self.notification(name);
203
204 Next::NextItem(name, value, define, notify)
205 }
206
207 pub fn next(&mut self) -> Option<Next>
210 {
211 match self.state()
212 {
213 State::Normal => Some(self.next_item()),
214 State::Done => None,
215 State::UnknownInput => Some(self.unknown_item()),
216 State::MissingInput => Some(self.missing_item())
217 }
218 }
219}
220
221#[cfg(test)]
222mod tests
223{
224 use std::collections::BTreeMap;
225
226 use toml::Value;
227
228 use data::ItemUsize;
229 use item_def::ItemDef;
230 use notify::Notify;
231 use value::UsizeValue;
232
233 macro_rules! assert_item {
234 ($test:expr, $name:expr, $val:expr, $notify:expr) => {{
235 match $test.unwrap()
236 {
237 super::Next::NextItem(name, value, def, notify) => {
238 assert_eq!(name, $name);
239 assert_eq!(def.name(), name);
240 assert_eq!($val, value.as_integer().unwrap());
241
242 if $notify
243 {
244 assert!(notify.is_some());
245 }
246 else
247 {
248 assert!(notify.is_none());
249 }
250 },
251 _ => {
252 panic!("{} not found.", $name);
253 }
254 }
255 }}
256 }
257
258 macro_rules! assert_unknown {
259 ($test:expr, $name:expr, $val:expr) => {{
260 match $test.unwrap()
261 {
262 super::Next::UnknownInput(name, value) => {
263 assert_eq!(name, $name);
264 assert_eq!($val, value.as_integer().unwrap());
265 },
266 _ => {
267 panic!("{} is known.", $name);
268 }
269 }
270 }}
271 }
272
273 macro_rules! assert_missing {
274 ($test:expr, $name:expr, $notify:expr) => {{
275 match $test.unwrap()
276 {
277 super::Next::MissingInput(name, def, notify) => {
278 assert_eq!(name, $name);
279 assert_eq!(def.name(), name);
280
281 if $notify
282 {
283 assert!(notify.is_some());
284 }
285 else
286 {
287 assert!(notify.is_none());
288 }
289 },
290 _ => {
291 panic!("{} is not missing.", $name);
292 }
293 }
294 }}
295 }
296
297 fn generate(
300 mut data : Vec<(&str, i64)>
301 ) -> (BTreeMap<String, Value>, BTreeMap<String, Box<ItemDef>>, BTreeMap<String, Box<Notify>>)
302 {
303 let mut input : BTreeMap<String, Value> = BTreeMap::new();
304 let mut define : BTreeMap<String, Box<ItemDef>> = BTreeMap::new();
305 let mut notify : BTreeMap<String, Box<Notify>> = BTreeMap::new();
306
307 for (name, value) in data.drain(..)
308 {
309 input.insert(String::from(name), Value::Integer(value));
310 define.insert(String::from(name), Box::new(ItemUsize::with_name(name)));
311 notify.insert(String::from(name), Box::new(UsizeValue::new()));
312 }
313
314 (input, define, notify)
315 }
316
317 #[test]
320 fn normal()
321 {
322 let (input, define, notify) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
323 let mut test = super::TomlIter::new(&input, &define, ¬ify);
324
325 assert_item!(test.next(), "a", 1, true);
326 assert_item!(test.next(), "b", 2, true);
327 assert_item!(test.next(), "c", 3, true);
328 assert_item!(test.next(), "d", 4, true);
329 assert!(test.next().is_none());
330 }
331
332 #[test]
335 fn no_notify()
336 {
337 let (input, define, _) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
338 let notify = BTreeMap::new();
339 let mut test = super::TomlIter::new(&input, &define, ¬ify);
340
341 assert_item!(test.next(), "a", 1, false);
342 assert_item!(test.next(), "b", 2, false);
343 assert_item!(test.next(), "c", 3, false);
344 assert_item!(test.next(), "d", 4, false);
345 assert!(test.next().is_none());
346 }
347
348 #[test]
351 fn no_define()
352 {
353 let (input, _, _) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
354 let define = BTreeMap::new();
355 let notify = BTreeMap::new();
356 let mut test = super::TomlIter::new(&input, &define, ¬ify);
357
358 assert_unknown!(test.next(), "a", 1);
359 assert_unknown!(test.next(), "b", 2);
360 assert_unknown!(test.next(), "c", 3);
361 assert_unknown!(test.next(), "d", 4);
362 assert!(test.next().is_none());
363 }
364
365 #[test]
368 fn no_values()
369 {
370 let (_, define, notify) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
371 let input = BTreeMap::new();
372 let mut test = super::TomlIter::new(&input, &define, ¬ify);
373
374 assert_missing!(test.next(), "a", true);
375 assert_missing!(test.next(), "b", true);
376 assert_missing!(test.next(), "c", true);
377 assert_missing!(test.next(), "d", true);
378 assert!(test.next().is_none());
379 }
380
381 #[test]
384 fn missing_first()
385 {
386 let (mut input, define, notify) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
387
388 input.remove("a");
389
390 let mut test = super::TomlIter::new(&input, &define, ¬ify);
391
392 assert_missing!(test.next(), "a", true);
393 assert_item!(test.next(), "b", 2, true);
394 assert_item!(test.next(), "c", 3, true);
395 assert_item!(test.next(), "d", 4, true);
396 assert!(test.next().is_none());
397 }
398
399 #[test]
402 fn missing_middle()
403 {
404 let (mut input, define, notify) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
405
406 input.remove("b");
407
408 let mut test = super::TomlIter::new(&input, &define, ¬ify);
409
410 assert_item!(test.next(), "a", 1, true);
411 assert_missing!(test.next(), "b", true);
412 assert_item!(test.next(), "c", 3, true);
413 assert_item!(test.next(), "d", 4, true);
414 assert!(test.next().is_none());
415 }
416
417 #[test]
420 fn missing_last()
421 {
422 let (mut input, define, notify) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
423
424 input.remove("d");
425
426 let mut test = super::TomlIter::new(&input, &define, ¬ify);
427
428 assert_item!(test.next(), "a", 1, true);
429 assert_item!(test.next(), "b", 2, true);
430 assert_item!(test.next(), "c", 3, true);
431 assert_missing!(test.next(), "d", true);
432 assert!(test.next().is_none());
433 }
434
435 #[test]
438 fn undefined_first()
439 {
440 let (input, mut define, mut notify) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
441
442 define.remove("a");
443 notify.remove("a");
444
445 let mut test = super::TomlIter::new(&input, &define, ¬ify);
446
447 assert_unknown!(test.next(), "a", 1);
448 assert_item!(test.next(), "b", 2, true);
449 assert_item!(test.next(), "c", 3, true);
450 assert_item!(test.next(), "d", 4, true);
451 assert!(test.next().is_none());
452 }
453
454 #[test]
457 fn undefined_middle()
458 {
459 let (input, mut define, mut notify) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
460
461 define.remove("b");
462 notify.remove("b");
463
464 let mut test = super::TomlIter::new(&input, &define, ¬ify);
465
466 assert_item!(test.next(), "a", 1, true);
467 assert_unknown!(test.next(), "b", 2);
468 assert_item!(test.next(), "c", 3, true);
469 assert_item!(test.next(), "d", 4, true);
470 assert!(test.next().is_none());
471 }
472
473 #[test]
476 fn undefined_last()
477 {
478 let (input, mut define, mut notify) = generate(vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]);
479
480 define.remove("d");
481 notify.remove("d");
482
483 let mut test = super::TomlIter::new(&input, &define, ¬ify);
484
485 assert_item!(test.next(), "a", 1, true);
486 assert_item!(test.next(), "b", 2, true);
487 assert_item!(test.next(), "c", 3, true);
488 assert_unknown!(test.next(), "d", 4);
489 assert!(test.next().is_none());
490 }
491
492}