sapio_base/effects/
mod.rs1use crate::reverse_path::ReversePath;
10use crate::serialization_helpers::SArc;
11use schemars::JsonSchema;
12use serde::{Deserialize, Serialize};
13use std::collections::BTreeMap;
14
15use std::sync::Arc;
16pub mod path_fragment;
17pub use path_fragment::*;
18pub mod reverse_path;
19pub use reverse_path::*;
20
21pub type EffectPath = ReversePath<PathFragment>;
23
24#[derive(Debug)]
26pub enum EffectDBError {
27 SerializationError(serde_json::Error),
29}
30
31impl From<serde_json::Error> for EffectDBError {
32 fn from(e: serde_json::Error) -> Self {
33 EffectDBError::SerializationError(e)
34 }
35}
36pub trait EffectDB {
38 fn get_value<'a>(
40 &'a self,
41 at: &Arc<EffectPath>,
42 ) -> Box<dyn Iterator<Item = (&'a Arc<String>, &'a serde_json::Value)> + 'a>;
43}
44#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
48pub struct MapEffectDB {
49 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
52 effects: BTreeMap<SArc<EffectPath>, BTreeMap<SArc<String>, serde_json::Value>>,
53 #[serde(skip, default)]
54 empty: BTreeMap<SArc<String>, serde_json::Value>,
55}
56
57pub struct EditableMapEffectDB {
62 pub effects: BTreeMap<SArc<EffectPath>, BTreeMap<SArc<String>, serde_json::Value>>,
64 pub empty: BTreeMap<SArc<String>, serde_json::Value>,
66}
67
68impl From<MapEffectDB> for EditableMapEffectDB {
69 fn from(MapEffectDB { effects, empty }: MapEffectDB) -> Self {
70 Self { effects, empty }
71 }
72}
73impl From<EditableMapEffectDB> for MapEffectDB {
74 fn from(EditableMapEffectDB { effects, empty }: EditableMapEffectDB) -> Self {
75 Self { effects, empty }
76 }
77}
78
79impl MapEffectDB {
80 pub fn skip_serializing(&self) -> bool {
82 self.effects.is_empty()
83 }
84}
85
86impl EffectDB for MapEffectDB {
87 fn get_value<'a>(
88 &'a self,
89 at: &Arc<EffectPath>,
90 ) -> Box<dyn Iterator<Item = (&'a Arc<String>, &'a serde_json::Value)> + 'a> {
91 let r: &BTreeMap<_, _> = self.effects.get(&SArc(at.clone())).unwrap_or(&self.empty);
92 Box::new(r.iter().map(|(a, b)| (&a.0, b)))
93 }
94}
95
96#[cfg(test)]
97mod test {
98 use super::*;
99 use std::convert::{TryFrom, TryInto};
100 #[test]
101 fn test_string() {
102 let v: Vec<PathFragment> = vec![
103 "hello".try_into().unwrap(),
104 "#123".try_into().unwrap(),
105 PathFragment::FinishFn,
106 ];
107 let r = EffectPath::try_from(v).unwrap();
108 assert_eq!(String::from(r.clone()), "hello/#123/@finish_fn");
109 assert_eq!(Ok(r), EffectPath::try_from("hello/#123/@finish_fn"));
110 }
111 #[test]
112 fn test_serde() {
113 let v: Vec<PathFragment> = vec![
114 "hello".try_into().unwrap(),
115 PathFragment::Branch(100),
116 PathFragment::FinishFn,
117 ];
118 let r = EffectPath::try_from(v).unwrap();
119 assert_eq!(
120 serde_json::to_string(&r).unwrap(),
121 "\"hello/#100/@finish_fn\""
122 );
123 assert_eq!(
124 Ok(r),
125 serde_json::from_str("\"hello/#100/@finish_fn\"").map_err(|_| ())
126 );
127 }
128}