1pub use crate::error::{Error, JsonType};
3use core::str::FromStr;
4use data_encoding::BASE64;
5#[cfg(feature = "derive")]
6pub use lbr_prelude_derive::Json;
7use num_bigint::BigInt;
8use serde_json;
9use serde_json::Value;
10use std::collections::{BTreeMap, BTreeSet};
11#[cfg(feature = "fs")]
12use std::future::Future;
13#[cfg(feature = "fs")]
14use std::{any::type_name, path::Path};
15#[cfg(feature = "fs")]
16use tokio::fs;
17
18pub mod lamval;
19
20pub trait Json {
22 fn to_json(&self) -> Value;
23
24 fn from_json(value: &Value) -> Result<Self, Error>
25 where
26 Self: Sized;
27
28 fn to_json_string(&self) -> String {
29 self.to_json().to_string()
30 }
31
32 fn from_json_string(string: &str) -> Result<Self, Error>
33 where
34 Self: Sized,
35 {
36 Value::from_str(string)
37 .map_err(|err| Error::MalformedJson { source: err })
38 .and_then(|value| Self::from_json(&value))
39 }
40
41 #[cfg(feature = "fs")]
44 fn read_lbf_json_file(path: impl AsRef<Path>) -> impl Future<Output = anyhow::Result<Self>>
45 where
46 Self: Sized,
47 {
48 async move {
49 let type_name = type_name::<Self>();
50 let json_str = fs::read_to_string(&path).await.map_err(|err| {
51 anyhow::anyhow!(
52 "Unable to read file from {}: {}",
53 path.as_ref().display(),
54 err
55 )
56 })?;
57 let result = Self::from_json_string(&json_str).map_err(|err| {
58 anyhow::anyhow!(
59 "Bad json of type {} in file {}: {}",
60 type_name,
61 path.as_ref().display(),
62 err
63 )
64 })?;
65 Ok(result)
66 }
67 }
68
69 #[cfg(feature = "fs")]
72 fn write_lbf_json_file(
73 &self,
74 path: impl AsRef<Path>,
75 ) -> impl Future<Output = anyhow::Result<()>> {
76 async move {
77 let type_name = type_name::<Self>();
78 let json_str = self.to_json_string();
79 fs::write(&path, json_str).await.map_err(|err| {
80 anyhow::anyhow!(
81 "Unable to write value of type {} to file {}: {}",
82 type_name,
83 path.as_ref().display(),
84 err
85 )
86 })?;
87
88 Ok(())
89 }
90 }
91}
92
93impl Json for BigInt {
96 fn to_json(&self) -> Value {
97 let num = serde_json::Number::from_str(&self.to_string())
98 .expect("Failed to convert BigInt to json Number");
99
100 Value::Number(num)
101 }
102
103 fn from_json(value: &Value) -> Result<Self, Error> {
104 match value {
105 Value::Number(number) => {
106 BigInt::from_str(number.as_str()).map_err(|_| Error::UnexpectedJsonInvariant {
107 wanted: "bigint".to_owned(),
108 got: "unexpected string".to_owned(),
109 parser: "BigInt".to_owned(),
110 })
111 }
112 _ => Err(Error::UnexpectedJsonType {
113 wanted: JsonType::Number,
114 got: JsonType::from(value),
115 parser: "Prelude.Integer".to_owned(),
116 }),
117 }
118 }
119}
120
121impl Json for bool {
122 fn to_json(&self) -> Value {
123 Value::Bool(*self)
124 }
125
126 fn from_json(value: &Value) -> Result<Self, Error> {
127 match value {
128 Value::Bool(bool) => Ok(*bool),
129 _ => Err(Error::UnexpectedJsonType {
130 wanted: JsonType::Bool,
131 got: JsonType::from(value),
132 parser: "Prelude.Bool".to_owned(),
133 }),
134 }
135 }
136}
137
138impl Json for char {
139 fn to_json(&self) -> Value {
140 String::from(*self).to_json()
141 }
142
143 fn from_json(value: &Value) -> Result<Self, Error> {
144 String::from_json(value).and_then(|str| {
145 let mut chars = str.chars();
146 let ch = chars.next();
147 let rest = chars.next();
148 match (ch, rest) {
149 (Some(ch), None) => Ok(ch),
150 _ => Err(Error::UnexpectedJsonInvariant {
151 got: "string".to_owned(),
152 wanted: "char".to_owned(),
153 parser: "Prelude.Char".to_owned(),
154 }),
155 }
156 })
157 }
158}
159
160impl Json for Vec<u8> {
161 fn to_json(&self) -> Value {
162 BASE64.encode(self).to_json()
163 }
164
165 fn from_json(value: &Value) -> Result<Self, Error> {
166 String::from_json(value).and_then(|str| {
167 BASE64
168 .decode(&str.into_bytes())
169 .map_err(|_| Error::UnexpectedJsonInvariant {
170 got: "string".to_owned(),
171 wanted: "base64 string".to_owned(),
172 parser: "Prelude.Bytes".to_owned(),
173 })
174 })
175 }
176}
177
178impl Json for String {
179 fn to_json(&self) -> Value {
180 Value::String(self.to_owned())
181 }
182
183 fn from_json(value: &Value) -> Result<Self, Error> {
184 match value {
185 Value::String(str) => Ok(str.clone()),
186 _ => Err(Error::UnexpectedJsonType {
187 wanted: JsonType::String,
188 got: JsonType::from(value),
189 parser: "Prelude.Text".to_owned(),
190 }),
191 }
192 }
193}
194
195impl<T> Json for Option<T>
196where
197 T: Json,
198{
199 fn to_json(&self) -> Value {
200 match self {
201 Some(val) => json_constructor("Just", vec![val.to_json()]),
202 None => json_constructor("Nothing", Vec::with_capacity(0)),
203 }
204 }
205
206 fn from_json(value: &Value) -> Result<Self, Error> {
207 case_json_constructor(
208 "Prelude.Maybe",
209 vec![
210 (
211 "Nothing",
212 Box::new(|ctor_fields| match &ctor_fields[..] {
213 [] => Ok(None),
214 _ => Err(Error::UnexpectedArrayLength {
215 wanted: 0,
216 got: ctor_fields.len(),
217 parser: "Prelude.Maybe".to_owned(),
218 }),
219 }),
220 ),
221 (
222 "Just",
223 Box::new(|ctor_fields| match &ctor_fields[..] {
224 [val] => Ok(Some(T::from_json(val)?)),
225 _ => Err(Error::UnexpectedArrayLength {
226 wanted: 1,
227 got: ctor_fields.len(),
228 parser: "Prelude.Maybe".to_owned(),
229 }),
230 }),
231 ),
232 ],
233 value,
234 )
235 }
236}
237
238impl<T, E> Json for Result<T, E>
239where
240 T: Json,
241 E: Json,
242{
243 fn to_json(&self) -> Value {
244 match self {
245 Ok(val) => json_constructor("Right", vec![val.to_json()]),
246 Err(val) => json_constructor("Left", vec![val.to_json()]),
247 }
248 }
249
250 fn from_json(value: &Value) -> Result<Self, Error> {
251 case_json_constructor(
252 "Prelude.Either",
253 vec![
254 (
255 "Right",
256 Box::new(|ctor_fields| match &ctor_fields[..] {
257 [val] => Ok(Ok(T::from_json(val)?)),
258 _ => Err(Error::UnexpectedArrayLength {
259 wanted: 1,
260 got: ctor_fields.len(),
261 parser: "Prelude.Either".to_owned(),
262 }),
263 }),
264 ),
265 (
266 "Left",
267 Box::new(|ctor_fields| match &ctor_fields[..] {
268 [val] => Ok(Err(E::from_json(val)?)),
269 _ => Err(Error::UnexpectedArrayLength {
270 wanted: 1,
271 got: ctor_fields.len(),
272 parser: "Prelude.Either".to_owned(),
273 }),
274 }),
275 ),
276 ],
277 value,
278 )
279 }
280}
281
282impl<T> Json for Vec<T>
283where
284 T: Json,
285{
286 fn to_json(&self) -> Value {
287 let values = self.iter().map(|val| val.to_json()).collect();
288
289 Value::Array(values)
290 }
291
292 fn from_json(value: &Value) -> Result<Self, Error> {
293 match value {
294 Value::Array(vec) => vec
295 .iter()
296 .map(|val| T::from_json(val))
297 .collect::<Result<Vec<T>, Error>>(),
298 _ => Err(Error::UnexpectedJsonType {
299 wanted: JsonType::Array,
300 got: JsonType::from(value),
301 parser: "Prelude.List".to_owned(),
302 }),
303 }
304 }
305}
306
307impl<T> Json for BTreeSet<T>
308where
309 T: Json + Eq + Ord,
310{
311 fn to_json(&self) -> Value {
312 let values = self.iter().map(|val| val.to_json()).collect();
313
314 Value::Array(values)
315 }
316
317 fn from_json(value: &Value) -> Result<Self, Error> {
318 Vec::from_json(value).and_then(|vec: Vec<Value>| {
319 let set = vec
320 .iter()
321 .map(|val| T::from_json(val))
322 .collect::<Result<BTreeSet<T>, Error>>()?;
323
324 if set.len() == vec.len() {
325 Ok(set)
326 } else {
327 Err(Error::UnexpectedJsonInvariant {
328 wanted: "array with all unique elements".to_owned(),
329 got: "invalid set".to_owned(),
330 parser: "Prelude.Set".to_owned(),
331 })
332 }
333 })
334 }
335}
336
337impl<K, V> Json for BTreeMap<K, V>
338where
339 K: Json + Eq + Ord,
340 V: Json,
341{
342 fn to_json(&self) -> Value {
343 let values = self
344 .iter()
345 .map(|(key, val)| Value::Array(vec![key.to_json(), val.to_json()]))
346 .collect();
347
348 Value::Array(values)
349 }
350
351 fn from_json(value: &Value) -> Result<Self, Error> {
352 Vec::from_json(value).and_then(|vec: Vec<Value>| {
353 let set = vec
354 .iter()
355 .map(|kv_tuple| <(K, V)>::from_json(kv_tuple))
356 .collect::<Result<BTreeMap<K, V>, Error>>()?;
357
358 if set.len() == vec.len() {
359 Ok(set)
360 } else {
361 Err(Error::UnexpectedJsonInvariant {
362 wanted: "array with all unique elements".to_owned(),
363 got: "invalid set".to_owned(),
364 parser: "Prelude.Map".to_owned(),
365 })
366 }
367 })
368 }
369}
370
371impl Json for () {
372 fn to_json(&self) -> Value {
373 Value::Null
374 }
375
376 fn from_json(value: &Value) -> Result<Self, Error> {
377 match value {
378 Value::Null => Ok(()),
379 _ => Err(Error::UnexpectedJsonType {
380 wanted: JsonType::Null,
381 got: JsonType::from(value),
382 parser: "Prelude.Unit".to_owned(),
383 }),
384 }
385 }
386}
387
388impl Json for Value {
389 fn to_json(&self) -> Value {
390 self.clone()
391 }
392
393 fn from_json(value: &Value) -> Result<Self, Error> {
394 Ok(value.clone())
395 }
396}
397
398impl<A, B> Json for (A, B)
399where
400 A: Json,
401 B: Json,
402{
403 fn to_json(&self) -> Value {
404 Value::Array(vec![self.0.to_json(), self.1.to_json()])
405 }
406
407 fn from_json(value: &Value) -> Result<Self, Error> {
408 Vec::from_json(value).and_then(|vec: Vec<Value>| match &vec[..] {
409 [a, b] => Ok((A::from_json(a)?, B::from_json(b)?)),
410 _ => Err(Error::UnexpectedArrayLength {
411 wanted: 2,
412 got: vec.len(),
413 parser: "Prelude.Tuple".to_owned(),
414 }),
415 })
416 }
417}
418
419pub fn json_array(array: Vec<Value>) -> Value {
423 Value::Array(array)
424}
425
426pub fn case_json_array<'a, T>(
430 parser_name: &'a str,
431 parse_arr: impl FnOnce(&'a Vec<Value>) -> Result<T, Error>,
432 value: &'a Value,
433) -> Result<T, Error> {
434 match value {
435 Value::Array(array) => parse_arr(array),
436 _ => Err(Error::UnexpectedJsonType {
437 wanted: JsonType::Array,
438 got: JsonType::from(value),
439 parser: parser_name.to_owned(),
440 }),
441 }
442}
443
444pub fn json_map(map: Vec<(Value, Value)>) -> Value {
449 Value::Array(
450 map.into_iter()
451 .map(|(k, v)| Value::Array(vec![k, v]))
452 .collect(),
453 )
454}
455
456pub fn case_json_map<'a, K, V>(
460 parser_name: &'a str,
461 parse_elem: impl Fn(&(Value, Value)) -> Result<(K, V), Error>,
462 value: &'a Value,
463) -> Result<BTreeMap<K, V>, Error>
464where
465 K: Ord,
466{
467 match value {
468 Value::Array(vec) => vec
469 .into_iter()
470 .map(|kv_tuple| parse_elem(&<(Value, Value)>::from_json(kv_tuple)?))
471 .collect::<Result<BTreeMap<K, V>, Error>>(),
472 _ => Err(Error::UnexpectedJsonType {
473 wanted: JsonType::Array,
474 got: JsonType::from(value),
475 parser: parser_name.to_owned(),
476 }),
477 }
478}
479
480pub fn json_object(kvs: Vec<(String, Value)>) -> Value {
484 Value::Object(
485 kvs.iter()
486 .cloned()
487 .map(|(k, v)| (k, v))
488 .collect::<serde_json::Map<String, Value>>(),
489 )
490}
491
492pub fn case_json_object<'a, T>(
496 parse_obj: impl FnOnce(&'a serde_json::Map<String, Value>) -> Result<T, Error>,
497 value: &'a Value,
498) -> Result<T, Error> {
499 match value {
500 Value::Object(obj) => parse_obj(obj),
501 _ => Err(Error::UnexpectedJsonType {
502 wanted: JsonType::Object,
503 got: JsonType::from(value),
504 parser: "Prelude.caseJsonObject".to_owned(),
505 }),
506 }
507}
508
509pub fn json_field<'a, T>(
513 name: &'a str,
514 obj: &'a serde_json::Map<String, Value>,
515 parse_field: impl Fn(&'a Value) -> Result<T, Error>,
516) -> Result<T, Error> {
517 obj.get(name)
518 .ok_or_else(|| Error::UnexpectedFieldName {
519 wanted: name.to_owned(),
520 got: obj.keys().cloned().collect(),
521 parser: name.to_owned(),
522 })
523 .and_then(parse_field)
524}
525
526pub fn json_constructor(ctor_name: &str, ctor_product: impl AsRef<Vec<Value>>) -> Value {
531 let mut obj = serde_json::Map::new();
532 obj.insert("name".to_owned(), Value::String(ctor_name.to_owned()));
533 obj.insert(
534 "fields".to_owned(),
535 Value::Array(ctor_product.as_ref().clone()),
536 );
537
538 Value::Object(obj)
539}
540
541pub fn case_json_constructor<'a, T: 'a>(
546 parser_name: &'a str,
547 ctor_parsers: Vec<(
548 &'a str,
549 Box<dyn 'a + Fn(&'a Vec<Value>) -> Result<T, Error>>,
550 )>,
551 value: &'a Value,
552) -> Result<T, Error> {
553 let ctor_parsers: BTreeMap<&'a str, Box<dyn 'a + Fn(&'a Vec<Value>) -> Result<T, Error>>> =
554 BTreeMap::from_iter(ctor_parsers);
555
556 match value {
557 Value::Object(ref obj) => {
558 let name = obj
559 .get("name")
560 .ok_or(Error::UnexpectedFieldName {
561 wanted: "name".to_owned(),
562 got: obj.keys().cloned().collect(),
563 parser: parser_name.to_owned(),
564 })
565 .and_then(|name| match name {
566 Value::String(str) => Ok(str),
567 _ => Err(Error::UnexpectedJsonType {
568 wanted: JsonType::String,
569 got: JsonType::from(value),
570 parser: parser_name.to_owned(),
571 }),
572 })?;
573 let fields = obj
574 .get("fields")
575 .ok_or(Error::UnexpectedFieldName {
576 wanted: "fields".to_owned(),
577 got: obj.keys().cloned().collect(),
578 parser: parser_name.to_owned(),
579 })
580 .and_then(|fields| match fields {
581 Value::Array(str) => Ok(str),
582 _ => Err(Error::UnexpectedJsonType {
583 wanted: JsonType::Array,
584 got: JsonType::from(value),
585 parser: parser_name.to_owned(),
586 }),
587 })?;
588
589 let names = ctor_parsers
590 .keys()
591 .map(std::ops::Deref::deref)
592 .collect::<Vec<_>>()
593 .join(", ");
594
595 let ctor_parser =
596 ctor_parsers
597 .get(name.as_str())
598 .ok_or(Error::UnexpectedJsonInvariant {
599 wanted: format!("constructor names ({})", names),
600 got: format!("unknown constructor name: {}", name),
601 parser: parser_name.to_owned(),
602 })?;
603
604 ctor_parser(fields)
605 }
606 _ => Err(Error::UnexpectedJsonType {
607 wanted: JsonType::Null,
608 got: JsonType::from(value),
609 parser: parser_name.to_owned(),
610 }),
611 }
612}