1use error::*;
2use path;
3use std::collections::HashMap;
4use std::fmt::Debug;
5use std::str::FromStr;
6use value::{Value, ValueKind};
7
8pub trait Source: Debug {
10 fn clone_into_box(&self) -> Box<dyn Source + Send + Sync>;
11
12 fn collect(&self) -> Result<HashMap<String, Value>>;
15
16 fn collect_to(&self, cache: &mut Value) -> Result<()> {
17 let props = match self.collect() {
18 Ok(props) => props,
19 Err(error) => {
20 return Err(error);
21 }
22 };
23
24 for (key, val) in &props {
25 match path::Expression::from_str(key) {
26 Ok(expr) => expr.set(cache, val.clone()),
28
29 _ => path::Expression::Identifier(key.clone()).set(cache, val.clone()),
31 }
32 }
33
34 Ok(())
35 }
36}
37
38impl Clone for Box<dyn Source + Send + Sync> {
39 fn clone(&self) -> Box<dyn Source + Send + Sync> {
40 self.clone_into_box()
41 }
42}
43
44impl Source for Vec<Box<dyn Source + Send + Sync>> {
45 fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
46 Box::new((*self).clone())
47 }
48
49 fn collect(&self) -> Result<HashMap<String, Value>> {
50 let mut cache: Value = HashMap::<String, Value>::new().into();
51
52 for source in self {
53 source.collect_to(&mut cache)?;
54 }
55
56 if let ValueKind::Table(table) = cache.kind {
57 Ok(table)
58 } else {
59 unreachable!();
60 }
61 }
62}
63
64impl<T> Source for Vec<T>
65where
66 T: Source + Sync + Send,
67 T: Clone,
68 T: 'static,
69{
70 fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
71 Box::new((*self).clone())
72 }
73
74 fn collect(&self) -> Result<HashMap<String, Value>> {
75 let mut cache: Value = HashMap::<String, Value>::new().into();
76
77 for source in self {
78 source.collect_to(&mut cache)?;
79 }
80
81 if let ValueKind::Table(table) = cache.kind {
82 Ok(table)
83 } else {
84 unreachable!();
85 }
86 }
87}