1use std::collections::HashMap;
2use std::error;
3use super::Collection;
4
5use crate::utils;
6use utils::{Serializable, Deserializable};
7use utils::errors::CalcifyError;
8use utils::io::{ToFile,FromFile};
9
10extern crate rmp;
11use rmp::encode::*;
12use rmp::decode::*;
13
14#[derive(Debug, PartialEq, Clone)]
16pub struct FeedTree<T: Serializable> {
17 metadata: HashMap<String,String>,
18 datafeeds: HashMap<String,Collection<T>>,
19}
20
21impl<T: Serializable> FeedTree<T> {
22 pub fn new(name: &str, subtype: &str) -> FeedTree<T> {
44 let mut md = HashMap::new();
45 md.insert(String::from("Name"),String::from(name));
46 md.insert(String::from("SubType"),String::from(subtype));
47 let df = HashMap::new();
48 FeedTree {
49 metadata: md,
50 datafeeds: df,
51 }
52 }
53
54 pub fn add_field(&mut self, key: &str, f: &str) -> Result<(),CalcifyError> {
55 if let Some(_) = self.metadata.insert(String::from(key),String::from(f)) {
56 return Err(CalcifyError::KeyError);
57 }
58 Ok(())
59 }
60
61 pub fn add_feed(&mut self, key: &str, f: Collection<T>) -> Result<(),CalcifyError> {
68 if let Some(_) = self.datafeeds.insert(String::from(key),f) {
69 return Err(CalcifyError::KeyError);
70 }
71 Ok(())
72 }
73
74 pub fn get_feed(&mut self, key: &str) -> Option<&Collection<T>> {
75 self.datafeeds.get(key)
76 }
77
78 pub fn write(&mut self, key: &str, data: T) -> Result<(),CalcifyError> {
79 if let Some(feed) = self.datafeeds.get_mut(key) {
80 feed.push(data);
81 Ok(())
82 } else {
83 Err(CalcifyError::KeyError)
84 }
85 }
86}
87
88impl<T: Serializable> Serializable for FeedTree<T> {
89 fn to_json(&self) -> String {
90 let mut out = String::from("{");
91 for (key, val) in &self.metadata {
92 out.push_str(format!("\"{}\":\"{}\",",key,val).as_str());
93 }
94 out.push_str("\"datafeeds\":{");
95 for (key, val) in &self.datafeeds {
96 out.push_str(format!("\"{}\":{},",key,val.to_json()).as_str());
97 }
98 out.pop();
99 out.push_str("}}");
100 out
101 }
102
103 fn to_msg(&self) -> Result<Vec<u8>, ValueWriteError> {
104 let mut buf = Vec::new();
105 write_map_len(&mut buf, (self.metadata.len()+1) as u32)?;
106 for (key, val) in &self.metadata {
107 write_str(&mut buf, key)?;
108 write_str(&mut buf, val)?;
109 }
110 write_str(&mut buf, "datafeeds")?;
111 write_map_len(&mut buf, (self.datafeeds.len()) as u32)?;
112 for (key, val) in &self.datafeeds {
113 write_str(&mut buf, key)?;
114 buf.append(&mut val.to_msg()?);
115 }
116 Ok(buf)
117 }
118}
119
120impl<T: Serializable + Deserializable> Deserializable for FeedTree<T> {
121 fn from_json(s: &str) -> Result<Self, Box<dyn error::Error>> {
122 let mut metadata: HashMap<String,String> = HashMap::new();
123 let mut datafeeds: HashMap<String,Collection<T>> = HashMap::new();
124 for (i,dim) in s.split(",\"datafeeds\":").enumerate() {
125 match i {
126 0 => {
127 for pair in dim.trim_matches(|p| p == '{' || p == '"' ).split("\",\"") {
128 let ar: Vec<&str> = pair.split("\":\"").collect();
129 metadata.insert(String::from(ar[0]),String::from(ar[1]));
130 }
131 },
132 1 => {
133 for pair in dim.trim_matches(|p| p == '{' || p == '}' || p == '"' ).split("],\"") {
134 let ar: Vec<&str> = pair.split("\":").collect();
135 if let Ok(feed) = Collection::<T>::from_json(&ar[1..].join("\":")){
136 datafeeds.insert(String::from(ar[0]),feed);
137 } else {
138 return Err(Box::new(CalcifyError::ParseError));
139 }
140 }
141 },
142 _ => return Err(Box::new(CalcifyError::ParseError)),
143 }
144 }
145 Ok(FeedTree{metadata, datafeeds})
146 }
147
148 fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box<dyn error::Error>> {
149 let mut metadata: HashMap<String,String> = HashMap::new();
150 let mut datafeeds: HashMap<String,Collection<T>> = HashMap::new();
151 if let Ok(len) = read_map_len(&mut bytes) {
152 for _ in 0..len {
153 let mut unparsed: &[u8] = &bytes[..];
154 if let Ok((key,v_rest)) = read_str_from_slice(unparsed) {
155 match key {
156 "datafeeds" => {
157 bytes = v_rest;
158 break;
159 },
160 _ => {
161 if let Ok((value,rest)) = read_str_from_slice(v_rest) {
162 unparsed = rest;
163 metadata.insert(String::from(key),String::from(value));
164 }
165 },
166 }
167
168 }
169 bytes = unparsed;
170 }
171 if let Ok(flen) = read_map_len(&mut bytes) {
172 for _ in 0..flen {
173 let unparsed: &[u8] = &bytes[..];
174 if let Ok((key,v_rest)) = read_str_from_slice(unparsed) {
175 if let Ok((value,rest)) = Collection::<T>::from_msg(v_rest) {
176 bytes = rest;
177 datafeeds.insert(String::from(key),value);
178 }
179 }
180 }
181 }
182 }
183 Ok((FeedTree{metadata, datafeeds},bytes))
184 }
185}
186
187impl<T: Serializable> ToFile for FeedTree<T>{}
188impl<T: Serializable + Deserializable> FromFile for FeedTree<T>{}
189
190#[cfg(test)]
191mod tests {
192 use super::*;
193 use crate::ThreeVec;
194
195 #[test]
196 fn test_ftree_write() -> Result<(),Box<dyn error::Error>>{
197 let mut col_3v: Collection<ThreeVec> = Collection::empty();
198 for _i in 0..9 {col_3v.push(ThreeVec::new(1.0,2.0,3.0));}
199 let mut ttree = FeedTree::new("Test_Tree","ThreeVec");
200 ttree.add_field("Desc", "This is a Tree for testing.")?;
201 ttree.add_feed("fcol", col_3v)?;
202 ttree.write_msg("./scratch/test_ftree.msg")?;
203 Ok(())
204 }
205
206 #[test]
207 fn test_ftree_read() -> Result<(),Box<dyn error::Error>>{
208 let mut col_3v: Collection<ThreeVec> = Collection::empty();
209 for _i in 0..9 {col_3v.push(ThreeVec::new(1.0,2.0,3.0));}
210 let mut ttree = FeedTree::new("Test_Tree","ThreeVec");
211 ttree.add_field("Desc", "This is a Tree for testing.")?;
212 ttree.add_feed("fcol", col_3v)?;
213
214 let ftree: FeedTree<ThreeVec> = FeedTree::read_msg("./scratch/test_ftree.msg")?;
215 assert_eq!(ftree,ttree);
216 Ok(())
217 }
218
219 #[test]
220 fn test_ftree_json() -> Result<(),Box<dyn error::Error>>{
221 let mut col_3v: Collection<ThreeVec> = Collection::empty();
222 for _i in 0..9 {col_3v.push(ThreeVec::random(1.0));}
223 let mut ttree = FeedTree::new("Test_Tree","ThreeVec");
224 ttree.add_field("Desc", "This is a Tree for testing.")?;
225 ttree.add_feed("fcol", col_3v.clone())?;
226 ttree.add_feed("fcol1", col_3v.clone())?;
227 ttree.add_feed("fcol2", col_3v)?;
228 let pp = ttree.to_json();
229 let oo = FeedTree::<ThreeVec>::from_json(&pp)?;
230 println!("{:?}",oo);
231 Ok(())
232 }
233
234 #[test]
235 fn test_ftree_msg() -> Result<(),Box<dyn error::Error>>{
236 let mut col_3v: Collection<ThreeVec> = Collection::empty();
237 for _i in 0..9 {col_3v.push(ThreeVec::random(1.0));}
238 let mut ttree = FeedTree::new("Test_Tree","ThreeVec");
239 ttree.add_field("Desc", "This is a Tree for testing.")?;
240 ttree.add_feed("fcol", col_3v.clone())?;
241 ttree.add_feed("fcol2", col_3v)?;
242 let pp = ttree.to_msg().unwrap();
243 let (oo,_) = FeedTree::<ThreeVec>::from_msg(&pp).unwrap();
244 assert_eq!(oo,ttree);
245 Ok(())
246 }
247}