1use crate::path::Path;
2use sede::{deserialize_rc_box_any_map, serialize_rc_box_any_map};
3use serde::Deserialize;
4use serde::Serialize;
5use std::any::Any;
6use std::collections::HashMap;
7use std::fmt::{Debug, Display, Formatter};
8use std::rc::Rc;
9use std::str::FromStr;
10
11pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct Export {
18 #[serde(
19 serialize_with = "serialize_rc_box_any_map",
20 deserialize_with = "deserialize_rc_box_any_map"
21 )]
22 map: HashMap<Path, Rc<Box<dyn Any>>>,
23}
24
25#[macro_export]
26macro_rules! export {
27 ($($x:expr),*) => {{
28 let mut temp_map = std::collections::HashMap::new();
29 $(
30 temp_map.insert($x.0, std::rc::Rc::new(Box::new($x.1) as Box<dyn Any>));
31 )*
32 Export::from(temp_map)
33 }};
34 }
35
36impl Export {
37 pub fn new() -> Self {
43 Self {
44 map: HashMap::new(),
45 }
46 }
47
48 pub fn put<A: 'static>(&mut self, path: Path, value: A) {
59 self.map.insert(path, Rc::new(Box::new(value)));
60 }
61
62 pub fn put_lazy<A: 'static, F>(&mut self, path: Path, fun: F)
75 where
76 F: FnOnce() -> A,
77 {
78 let value = fun();
79 self.put(path, value);
80 }
81
82 pub fn put_lazy_and_return<A: 'static + Clone, F>(&mut self, path: Path, fun: F) -> A
99 where
100 F: FnOnce() -> A,
101 {
102 let value = fun();
103 self.put(path, value.clone());
104 value
105 }
106
107 pub fn get<A: 'static + FromStr + Clone>(&self, path: &Path) -> Result<A> {
121 let get_result: Result<&A> = self.get_from_map::<A>(path);
122
123 match get_result {
124 Ok(any_val) => Ok(any_val.clone()),
125 _ => {
126 let str_result = self.get_from_map::<String>(path);
128 str_result?.parse::<A>().map_err(|_| "Cannot parse".into())
129 }
130 }
131 }
132
133 fn get_from_map<A>(&self, path: &Path) -> Result<&A>
134 where
135 A: 'static + FromStr + Clone,
136 {
137 self.map
138 .get(path)
139 .and_then(|value| value.downcast_ref::<A>())
140 .ok_or("No value at the given Path".into())
141 }
142
143 pub fn root<A: 'static + FromStr + Clone>(&self) -> A {
158 self.get(&Path::new()).unwrap()
159 }
160
161 pub fn root_as_result<A: 'static + FromStr + Clone>(&self) -> Result<A> {
171 self.get(&Path::new())
172 }
173
174 pub fn paths(&self) -> &HashMap<Path, Rc<Box<dyn Any>>> {
180 &self.map
181 }
182}
183
184impl Default for Export {
185 fn default() -> Self {
186 Self::new()
187 }
188}
189
190impl From<HashMap<Path, Rc<Box<dyn Any>>>> for Export {
191 fn from(map: HashMap<Path, Rc<Box<dyn Any>>>) -> Self {
192 Self { map }
193 }
194}
195
196impl Display for Export {
197 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
198 let string = serde_json::to_string(&self);
199 write!(f, "{}", string.unwrap())
200 }
201}
202
203impl PartialEq for Export {
204 fn eq(&self, other: &Self) -> bool {
205 let keys_len_equality = self.map.keys().len() == other.map.keys().len();
206
207 let values_equality = self.map.iter().all(|(key, _value)| {
208 if let Ok(value) = self.get::<i32>(key) {
209 if let Ok(other_value) = other.get::<i32>(key) {
210 value == other_value
211 } else {
212 false
213 }
214 } else if let Ok(value) = self.get::<bool>(key) {
215 if let Ok(other_value) = other.get::<bool>(key) {
216 value == other_value
217 } else {
218 false
219 }
220 } else if let Ok(value) = self.get::<String>(key) {
221 if let Ok(other_value) = other.get::<String>(key) {
222 value == other_value
223 } else {
224 false
225 }
226 } else if let Ok(value) = self.get::<f64>(key) {
227 if let Ok(other_value) = other.get::<f64>(key) {
228 value == other_value
229 } else {
230 false
231 }
232 } else {
233 false
234 }
235 });
236
237 keys_len_equality && values_equality
238 }
239}
240
241mod sede {
243 use crate::path::Path;
244 use serde::de::Visitor;
245 use serde::{Deserializer, Serialize, Serializer};
246 use std::any::Any;
247 use std::collections::HashMap;
248 use std::rc::Rc;
249
250 pub fn serialize_rc_box_any_map<S>(
251 data: &HashMap<Path, Rc<Box<dyn Any>>>,
252 serializer: S,
253 ) -> Result<S::Ok, S::Error>
254 where
255 S: Serializer,
256 {
257 let serializable_data: HashMap<String, String> = data
259 .iter()
260 .map(|(key, value)| {
261 let key_str = serde_json::to_string(key).unwrap();
262 if let Some(value) = value.downcast_ref::<i32>() {
264 (key_str, value.clone().to_string())
265 } else if let Some(value) = value.downcast_ref::<bool>() {
266 (key_str, value.clone().to_string())
267 } else if let Some(value) = value.downcast_ref::<String>() {
268 (key_str, value.clone())
269 } else if let Some(value) = value.downcast_ref::<f64>() {
270 (key_str, value.clone().to_string())
271 } else {
272 panic!("Cannot serialize type")
273 }
274 })
275 .collect();
276 serializable_data.serialize(serializer)
277 }
278
279 struct ExportMapVisitor;
280
281 impl<'de> Visitor<'de> for ExportMapVisitor {
282 type Value = HashMap<Path, Rc<Box<dyn Any>>>;
283 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
284 formatter.write_str("a map of Paths and Any")
285 }
286
287 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
288 where
289 A: serde::de::MapAccess<'de>,
290 {
291 let mut result = HashMap::new();
292 while let Some((key, value)) = map.next_entry::<String, String>()? {
293 let path: Path = serde_json::from_str(&key).unwrap();
294 let value: Rc<Box<dyn Any>> = Rc::new(Box::new(value) as Box<dyn Any>);
295 result.insert(path, value);
296 }
297 Ok(result)
298 }
299 }
300
301 pub fn deserialize_rc_box_any_map<'de, D>(
302 deserializer: D,
303 ) -> Result<HashMap<Path, Rc<Box<dyn Any>>>, D::Error>
304 where
305 D: Deserializer<'de>,
306 {
307 deserializer.deserialize_map(ExportMapVisitor)
308 }
309}
310
311#[cfg(test)]
312mod tests {
313 use super::*;
314 use crate::path;
315 use crate::path::Path;
316 use crate::slot::Slot::{Nbr, Rep};
317
318 #[test]
319 fn test_new_empty() {
320 let export: Export = Export::new();
321 assert!(export.map.is_empty())
322 }
323
324 #[test]
325 fn test_new() {
326 let export = export!((path!(Rep(0), Nbr(0)), 10));
331 assert_eq!(export.map.len(), 1);
332 }
333
334 #[test]
335 fn test_put() {
336 let mut export = export!((path!(Rep(0)), 10));
337 export.put(path!(Rep(0), Nbr(0)), 20);
338 export.put(Path::from(vec![Nbr(0)]), "foo");
339 assert_eq!(export.paths().len(), 3);
340 }
341
342 #[test]
343 fn test_get() {
344 let export = export!((path!(Nbr(0), Rep(0)), 10));
345 assert_eq!(
346 export
348 .get::<i32>(&Path::from(vec![Rep(0), Nbr(0)]))
349 .unwrap(),
350 10
351 );
352 }
353
354 #[test]
355 fn test_get_none() {
356 let export = export!((path!(Rep(0), Nbr(0)), 10));
357 assert!(export
358 .get::<String>(&Path::from(vec![Rep(0), Nbr(0)]))
359 .is_err());
360 }
361
362 #[test]
363 fn test_root() {
364 let export = export!((Path::new(), 10));
365 assert_eq!(export.root::<i32>(), 10);
366 }
367
368 #[test]
369 #[should_panic]
370 fn test_root_panic() {
371 let export = export!((Path::new(), 10));
372 assert_eq!(export.root::<String>(), "foo");
373 }
374
375 #[test]
376 fn test_paths() {
377 let export = export!((Path::new(), 10));
378 let mut map2: HashMap<Path, Rc<Box<dyn Any>>> = HashMap::new();
379 map2.insert(Path::new(), Rc::new(Box::new(10)));
380 assert!(export.map.keys().eq(map2.keys()));
381 }
382
383 #[test]
384 fn test_empty_state() {
385 let export: Export = Export::new();
386 let path = path!(Nbr(0), Rep(0));
387 assert!(export.get::<i32>(&Path::new()).is_err());
388 assert!(export.get::<i32>(&path).is_err());
389 }
390
391 #[test]
392 fn test_root_path() {
393 let mut export: Export = Export::new();
394 export.put(Path::new(), String::from("foo"));
395 assert_eq!(
396 export.get::<String>(&Path::new()).unwrap(),
397 export.root::<String>()
398 );
399 assert_eq!(
400 export.get::<String>(&Path::new()).unwrap(),
401 "foo".to_string()
402 );
403 }
404
405 #[test]
406 fn test_non_root_path() {
407 let mut export: Export = Export::new();
408 let path = path!(Nbr(0), Rep(0));
409 export.put(path.clone(), String::from("bar"));
410 assert_eq!(export.get::<String>(&path).unwrap(), String::from("bar"));
411 }
412
413 #[test]
414 fn test_overwriting_with_different_type() {
415 let mut export: Export = Export::new();
416 export.put(Path::new(), String::from("foo"));
417 assert_eq!(
418 export.get::<String>(&Path::new()).unwrap(),
419 "foo".to_string()
420 );
421 export.put(Path::new(), 77);
422 assert_eq!(export.get::<i32>(&Path::new()).unwrap(), 77);
423 }
424
425 #[test]
426 fn test_put_lazy() {
427 let mut export: Export = Export::new();
428 export.put_lazy(path!(Nbr(0)), || 10);
429 assert_eq!(export.get::<i32>(&path!(Nbr(0))).unwrap(), 10);
430 }
431
432 #[test]
433 fn test_put_lazy_and_return() {
434 let mut export: Export = Export::new();
435 let value = export.put_lazy_and_return(path!(Nbr(0)), || 10);
436 assert_eq!(value, 10);
437 assert_eq!(export.get::<i32>(&path!(Nbr(0))).unwrap(), 10);
438 }
439
440 #[test]
441 fn test_partial_eq() {
442 let export1 = export!((path!(Rep(0), Nbr(0)), 10));
444 let export2 = export!((path!(Rep(0), Nbr(0)), 10));
445 assert_eq!(export1, export2);
446
447 let export3 = export!((path!(Rep(0), Nbr(0)), 100));
449 assert_ne!(export1, export3);
450 }
451
452 #[test]
453 fn test_serialize_and_deserialize() {
454 let export = export![
455 (path!(Rep(0), Nbr(0)), 10),
456 (path!(Nbr(0)), 10),
457 (path!(Rep(0)), 10),
458 (Path::new(), 10)
459 ];
460 let export_ser = serde_json::to_string(&export).unwrap();
461 let export_des: Export = serde_json::from_str(&export_ser).unwrap();
462 assert_eq!(export, export_des);
463 }
464}