1use crate::{
2 error::DaoError,
3 FromValue,
4 ToValue,
5 Value,
6};
7use serde::{
8 ser::{
9 Serialize,
10 Serializer,
11 },
12 Deserialize,
13 Deserializer,
14};
15use std::collections::BTreeMap;
16
17#[derive(Debug, PartialEq, Clone, Default)]
18pub struct Dao(pub BTreeMap<String, Value>);
19
20impl Dao {
21 pub fn new() -> Self { Dao::default() }
22
23 pub fn insert<K, V>(&mut self, k: K, v: V)
24 where
25 K: ToString,
26 V: ToValue,
27 {
28 self.0.insert(k.to_string(), v.to_value());
29 }
30
31 pub fn insert_value<K>(&mut self, k: K, value: &Value)
32 where
33 K: ToString,
34 {
35 self.0.insert(k.to_string(), value.clone());
36 }
37
38 pub fn get<'a, T>(&'a self, s: &str) -> Result<T, DaoError>
39 where
40 T: FromValue,
41 {
42 let value: Option<&'a Value> = self.0.get(s);
43 match value {
44 Some(v) => FromValue::from_value(v).map_err(DaoError::ConvertError),
45 None => Err(DaoError::NoSuchValueError(s.into())),
46 }
47 }
48
49 pub fn get_opt<'a, T>(&'a self, s: &str) -> Result<Option<T>, DaoError>
50 where
51 T: FromValue,
52 {
53 let value: Option<&'a Value> = self.0.get(s);
54 match value {
55 Some(v) => {
56 match v {
57 Value::Nil => Ok(None),
58 _ => {
59 Ok(Some(
60 FromValue::from_value(v).map_err(DaoError::ConvertError)?,
61 ))
62 }
63 }
64 }
65 None => Ok(None),
66 }
67 }
68
69 pub fn get_value(&self, s: &str) -> Option<&Value> { self.0.get(s) }
70
71 pub fn remove(&mut self, s: &str) -> Option<Value> { self.0.remove(s) }
72}
73
74impl<'a> Serialize for Dao {
75 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
76 where
77 S: Serializer,
78 {
79 self.0.serialize(serializer)
80 }
81}
82
83impl<'de> Deserialize<'de> for Dao {
84 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
85 where
86 D: Deserializer<'de>,
87 {
88 BTreeMap::deserialize(deserializer).map(Dao)
89 }
90}
91
92pub trait FromDao {
93 fn from_dao(dao: &Dao) -> Self;
96}
97
98pub trait ToDao {
99 fn to_dao(&self) -> Dao;
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use serde_json;
108 use uuid::Uuid;
109
110 #[test]
111 fn insert_double() {
112 let mut dao = Dao::new();
113 dao.insert("life", 42.0f64);
114 let life: Result<f64, DaoError> = dao.get("life");
115 assert_eq!(life.unwrap(), 42.0f64);
116 }
117
118 #[test]
119 fn insert_float() {
120 let mut dao = Dao::new();
121 dao.insert("life", 42.0f32);
122 let life: Result<f64, DaoError> = dao.get("life");
123 assert_eq!(life.unwrap(), 42.0f64);
124 }
125
126 #[test]
127 fn uuid() {
128 let mut dao = Dao::new();
129 let uuid = Uuid::new_v4();
130 dao.insert("user_id", uuid);
131 }
132
133 #[test]
134 fn serialize_json() {
135 let mut dao = Dao::new();
136 dao.insert("life", 42);
137 dao.insert("lemons", "lemonade");
138 let json = serde_json::to_string(&dao).unwrap();
139 let expected = r#"{"lemons":{"Text":"lemonade"},"life":{"Int":42}}"#;
140 assert_eq!(json, expected);
141 }
142
143 #[test]
144 fn test_get_opt() {
145 let mut dao = Dao::new();
146 dao.insert("life", 42);
147 let life: Result<Option<i32>, _> = dao.get("life");
148 assert!(life.is_ok());
149 let life = life.unwrap();
150 assert!(life.is_some());
151 assert_eq!(life.unwrap(), 42);
152 }
153
154 #[test]
155 fn referenced() {
156 let mut dao = Dao::new();
157 let v = 42;
158 let s = "lemonade";
159 dao.insert("life", &v);
160 dao.insert("lemons", s);
161 let life: Result<Option<i32>, _> = dao.get("life");
162 assert!(life.is_ok());
163 let life = life.unwrap();
164 assert!(life.is_some());
165 assert_eq!(life.unwrap(), 42);
166 }
167}