object_rainbow_json/
distributed.rs1use std::collections::BTreeMap;
2
3use futures_util::future::try_join_all;
4use object_rainbow::{
5 Enum, Fetch, InlineOutput, ListHashes, MaybeHasNiche, NicheForUnsized, NoNiche, Parse,
6 ParseInline, Tagged, ToOutput, Topological, length_prefixed::LpString, numeric::Le,
7};
8use object_rainbow_point::{IntoPoint, Point};
9use serde::{Deserialize, Serialize};
10
11#[derive(
12 Enum,
13 ToOutput,
14 InlineOutput,
15 ListHashes,
16 Topological,
17 Parse,
18 ParseInline,
19 Clone,
20 Default,
21 Serialize,
22 Deserialize,
23)]
24#[serde(untagged)]
25#[topology(recursive)]
26pub enum Distributed {
27 #[default]
28 Null,
29 Bool(bool),
30 I64(Le<i64>),
31 U64(Le<u64>),
32 F64(Le<f64>),
33 String(Point<String>),
34 Array(#[parse(unchecked)] Point<Vec<Self>>),
35 Object(#[parse(unchecked)] Point<BTreeMap<LpString, Self>>),
36}
37
38impl Tagged for Distributed {}
39impl MaybeHasNiche for Distributed {
40 type MnArray = NoNiche<NicheForUnsized>;
41}
42
43impl Distributed {
44 pub async fn to_value(&self) -> object_rainbow::Result<serde_json::Value> {
45 Ok(match *self {
46 Distributed::Null => serde_json::Value::Null,
47 Distributed::Bool(x) => x.into(),
48 Distributed::I64(x) => x.0.into(),
49 Distributed::U64(x) => x.0.into(),
50 Distributed::F64(x) => x.0.into(),
51 Distributed::String(ref point) => point.fetch().await?.into(),
52 Distributed::Array(ref point) => try_join_all(
53 point
54 .fetch()
55 .await?
56 .into_iter()
57 .map(async |x| x.to_value().await),
58 )
59 .await?
60 .into(),
61 Distributed::Object(ref point) => {
62 try_join_all(
63 point.fetch().await?.into_iter().map(async |(k, x)| {
64 Ok::<_, object_rainbow::Error>((k.0, x.to_value().await?))
65 }),
66 )
67 .await?
68 .into_iter()
69 .collect::<serde_json::Map<_, _>>()
70 .into()
71 }
72 })
73 }
74}
75
76#[derive(Debug, thiserror::Error)]
77#[non_exhaustive]
78pub enum DistributedParseError {
79 #[error("invalid number")]
80 InvalidNumber,
81}
82
83impl TryFrom<serde_json::Value> for Distributed {
84 type Error = DistributedParseError;
85
86 fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
87 Ok(match value {
88 serde_json::Value::Null => Self::Null,
89 serde_json::Value::Bool(x) => Self::Bool(x),
90 serde_json::Value::Number(x) => {
91 if let Some(x) = x.as_u64() {
92 Self::U64(x.into())
93 } else if let Some(x) = x.as_i64() {
94 Self::I64(x.into())
95 } else if let Some(x) = x.as_f64() {
96 Self::F64(x.into())
97 } else {
98 return Err(DistributedParseError::InvalidNumber);
99 }
100 }
101 serde_json::Value::String(x) => Self::String(x.point()),
102 serde_json::Value::Array(vec) => Self::Array(
103 vec.into_iter()
104 .map(Self::try_from)
105 .collect::<Result<Vec<_>, _>>()?
106 .point(),
107 ),
108 serde_json::Value::Object(map) => Self::Object(
109 map.into_iter()
110 .map(|(k, v)| Ok((LpString(k), Self::try_from(v)?)))
111 .collect::<Result<BTreeMap<_, _>, _>>()?
112 .point(),
113 ),
114 })
115 }
116}