vertigo/driver_module/js_value/
serialize.rs1use std::collections::{BTreeMap, HashMap};
2use std::rc::Rc;
3
4use super::js_json_struct::JsJson;
5
6struct JsJsonContextInner {
7 parent: Option<Rc<JsJsonContextInner>>,
8 current: String,
9}
10
11#[derive(Clone)]
12pub struct JsJsonContext {
13 inner: Rc<JsJsonContextInner>,
14}
15
16impl JsJsonContext {
17 pub fn new(current: impl Into<String>) -> JsJsonContext {
18 Self {
19 inner: Rc::new(JsJsonContextInner {
20 parent: None,
21 current: current.into(),
22 }),
23 }
24 }
25
26 pub fn add(&self, child: impl ToString) -> JsJsonContext {
27 Self {
28 inner: Rc::new(JsJsonContextInner {
29 parent: Some(self.inner.clone()),
30 current: child.to_string(),
31 }),
32 }
33 }
34
35 pub fn convert_to_string(&self) -> String {
36 let mut path = Vec::new();
37 let mut current = self.inner.clone();
38
39 loop {
40 path.push(current.current.clone());
41
42 let Some(parent) = current.parent.clone() else {
43 return path.into_iter().rev().collect::<Vec<_>>().join(" -> ");
44 };
45
46 current = parent;
47 }
48 }
49}
50
51pub trait JsJsonSerialize {
52 fn to_json(self) -> JsJson;
53}
54
55pub trait JsJsonDeserialize
56where
57 Self: Sized,
58{
59 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext>;
60}
61
62impl JsJsonSerialize for String {
63 fn to_json(self) -> JsJson {
64 JsJson::String(self)
65 }
66}
67
68impl JsJsonDeserialize for String {
69 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
70 match json {
71 JsJson::String(value) => Ok(value),
72 other => {
73 let message = ["string expected, received ", other.typename()].concat();
74 Err(context.add(message))
75 }
76 }
77 }
78}
79
80impl JsJsonSerialize for u64 {
81 fn to_json(self) -> JsJson {
82 JsJson::Number(self as f64)
83 }
84}
85
86impl JsJsonDeserialize for u64 {
87 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
88 match json {
89 JsJson::Number(value) => Ok(value as u64),
90 other => {
91 let message = ["number(u64) expected, received ", other.typename()].concat();
92 Err(context.add(message))
93 }
94 }
95 }
96}
97
98impl JsJsonSerialize for i64 {
99 fn to_json(self) -> JsJson {
100 JsJson::Number(self as f64)
101 }
102}
103
104impl JsJsonDeserialize for i64 {
105 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
106 match json {
107 JsJson::Number(value) => Ok(value as i64),
108 other => {
109 let message = ["number(i64) expected, received ", other.typename()].concat();
110 Err(context.add(message))
111 }
112 }
113 }
114}
115
116impl JsJsonSerialize for u32 {
117 fn to_json(self) -> JsJson {
118 JsJson::Number(self as f64)
119 }
120}
121
122impl JsJsonDeserialize for u32 {
123 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
124 match json {
125 JsJson::Number(value) => Ok(value as u32),
126 other => {
127 let message = ["number(u32) expected, received ", other.typename()].concat();
128 Err(context.add(message))
129 }
130 }
131 }
132}
133
134impl JsJsonSerialize for i32 {
135 fn to_json(self) -> JsJson {
136 JsJson::Number(self as f64)
137 }
138}
139
140impl JsJsonDeserialize for i32 {
141 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
142 match json {
143 JsJson::Number(value) => Ok(value as i32),
144 other => {
145 let message = ["number(i32) expected, received ", other.typename()].concat();
146 Err(context.add(message))
147 }
148 }
149 }
150}
151
152impl JsJsonSerialize for bool {
153 fn to_json(self) -> JsJson {
154 match self {
155 false => JsJson::False,
156 true => JsJson::True,
157 }
158 }
159}
160
161impl JsJsonDeserialize for bool {
162 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
163 match json {
164 JsJson::False => Ok(false),
165 JsJson::True => Ok(true),
166 other => {
167 let message = ["bool expected, received ", other.typename()].concat();
168 Err(context.add(message))
169 }
170 }
171 }
172}
173
174impl JsJsonSerialize for () {
175 fn to_json(self) -> JsJson {
176 JsJson::Object(HashMap::default())
177 }
178}
179
180impl JsJsonDeserialize for () {
181 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
182 let map = json.get_hashmap(&context)?;
183
184 if !map.is_empty() {
185 let message = "Empty {} expected, inner content received".to_string();
186 return Err(context.add(message))
187 }
188
189 Ok(())
190 }
191}
192
193impl JsJsonSerialize for &str {
194 fn to_json(self) -> JsJson {
195 JsJson::String(self.into())
196 }
197}
198
199impl<T: JsJsonSerialize> JsJsonSerialize for Vec<T> {
200 fn to_json(self) -> JsJson {
201 let mut list = Vec::new();
202
203 for item in self {
204 list.push(item.to_json());
205 }
206
207 JsJson::List(list)
208 }
209}
210
211impl<T: JsJsonDeserialize> JsJsonDeserialize for Vec<T> {
212 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
213 let mut list = Vec::new();
214
215 let JsJson::List(inner) = json else {
216 let message = ["List expected, received ", json.typename()].concat();
217 return Err(context.add(message));
218 };
219
220 for (index, item) in inner.into_iter().enumerate() {
221 list.push(T::from_json(context.add(index), item)?);
222 }
223
224 Ok(list)
225 }
226}
227
228impl<T: JsJsonSerialize> JsJsonSerialize for Option<T> {
229 fn to_json(self) -> JsJson {
230 match self {
231 Some(value) => value.to_json(),
232 None => JsJson::Null,
233 }
234 }
235}
236
237impl<T: JsJsonDeserialize> JsJsonDeserialize for Option<T> {
238 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
239 if let JsJson::Null = json {
240 return Ok(None);
241 }
242
243 Ok(Some(T::from_json(context, json)?))
244 }
245}
246
247impl<T: JsJsonSerialize> JsJsonSerialize for HashMap<String, T> {
248 fn to_json(self) -> JsJson {
249 let mut result = HashMap::new();
250
251 for (key, item) in self {
252 result.insert(key, item.to_json());
253 }
254
255 JsJson::Object(result)
256 }
257}
258
259impl<T: JsJsonDeserialize> JsJsonDeserialize for HashMap<String, T> {
260 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
261 let map = json.get_hashmap(&context)?;
262
263 let mut result = HashMap::new();
264
265 for (key, item) in map {
266 let context = context.add(["field: '", key.as_str(), "'"].concat());
267 let value = T::from_json(context, item)?;
268 result.insert(key, value);
269 }
270
271 Ok(result)
272 }
273}
274
275impl<T: JsJsonSerialize> JsJsonSerialize for BTreeMap<String, T> {
276 fn to_json(self) -> JsJson {
277 let mut result = HashMap::new();
278
279 for (key, item) in self {
280 result.insert(key, item.to_json());
281 }
282
283 JsJson::Object(result)
284 }
285}
286
287impl<T: JsJsonDeserialize> JsJsonDeserialize for BTreeMap<String, T> {
288 fn from_json(context: JsJsonContext, json: JsJson) -> Result<Self, JsJsonContext> {
289 let map = json.get_hashmap(&context)?;
290
291 let mut result = BTreeMap::new();
292
293 for (key, item) in map {
294 let context = context.add(["field: '", key.as_str(), "'"].concat());
295 let value = T::from_json(context, item)?;
296 result.insert(key, value);
297 }
298
299 Ok(result)
300 }
301}
302
303pub fn from_json<T: JsJsonDeserialize>(json: JsJson) -> Result<T, String> {
305 let context = JsJsonContext::new("root");
306 let result = T::from_json(context, json);
307 result.map_err(|context| context.convert_to_string())
308}
309
310pub fn to_json<T: JsJsonSerialize>(value: T) -> JsJson {
312 value.to_json()
313}
314
315#[cfg(test)]
316mod tests {
317 use super::*;
318
319 #[derive(Debug, PartialEq, Clone)]
320 struct Post {
321 name: String,
322 age: u64,
323 }
324
325 impl JsJsonSerialize for Post {
326 fn to_json(self) -> JsJson {
327 JsJson::Object(HashMap::from([
328 ("name".to_string(), self.name.to_json()),
329 ("age".to_string(), self.age.to_json()),
330 ]))
331 }
332 }
333
334 impl JsJsonDeserialize for Post {
335 fn from_json(context: JsJsonContext, mut json: JsJson) -> Result<Self, JsJsonContext> {
336 Ok(Self {
337 name: json.get_property(&context, "name")?,
338 age: json.get_property(&context, "age")?,
339 })
340 }
341 }
342
343 #[test]
344 fn aaaa() {
345 let aaa = JsJson::String("aaa".into());
346 let aaa_post = from_json::<Post>(aaa);
347 assert_eq!(
348 aaa_post,
349 Err(String::from("root -> object expected, received string"))
350 );
351
352 let bbb = Post {
353 name: "dsada".into(),
354 age: 33,
355 };
356
357 let ccc = bbb.clone().to_json();
358 let Ok(ddd) = from_json::<Post>(ccc) else {
359 unreachable!();
360 };
361 assert_eq!(bbb, ddd);
362 }
363
364 #[test]
365 fn test_vec() {
366 let aaa = Post {
367 name: "aaa".into(),
368 age: 11,
369 };
370
371 let bbb = Post {
372 name: "bbb".into(),
373 age: 22,
374 };
375
376 let ccc = vec![aaa, bbb];
377
378 let ddd = ccc.clone().to_json();
379
380 let Ok(eee) = from_json::<Vec<Post>>(ddd) else {
381 unreachable!();
382 };
383
384 assert_eq!(ccc, eee);
385 }
386
387 #[test]
388 fn test_unit() {
389 let unit = JsJson::Object(HashMap::default());
390
391 let Ok(()) = from_json::<()>(unit.clone()) else {
392 unreachable!();
393 };
394
395 let unit2 = to_json(());
396
397 assert_eq!(unit2, unit)
398 }
399}