1use alloc::string::String;
4use alloc::vec::Vec;
5
6use serde_json::{self, Map, json};
7
8use base64::{Engine, engine::general_purpose};
9
10use crate::array::Array;
11use crate::id::Id;
12use crate::map::Map as NsonMap;
13use crate::value::Value;
14
15impl From<Value> for serde_json::Value {
16 fn from(value: Value) -> Self {
17 match value {
18 Value::F32(v) => json!(v),
19 Value::F64(v) => json!({"$f64": v}),
20 Value::I32(v) => json!(v),
21 Value::I64(v) => json!({"$i64": v}),
22 Value::U32(v) => json!({"$u32": v}),
23 Value::U64(v) => json!({"$u64": v}),
24 Value::I8(v) => json!({"$i8": v}),
25 Value::U8(v) => json!({"$u8": v}),
26 Value::I16(v) => json!({"$i16": v}),
27 Value::U16(v) => json!({"$u16": v}),
28 Value::String(v) => json!(v),
29 Value::Array(v) => {
30 let array: Vec<serde_json::Value> = v.into_iter().map(|v| v.into()).collect();
31 json!(array)
32 }
33 Value::Map(v) => {
34 let map: Map<String, serde_json::Value> =
35 v.into_iter().map(|(k, v)| (k, v.into())).collect();
36 json!(map)
37 }
38 Value::Bool(v) => json!(v),
39 Value::Null => json!(null),
40 Value::Binary(v) => json!({"$bin": general_purpose::STANDARD.encode(v.0)}),
41 Value::TimeStamp(v) => json!({"$tim": v.0}),
42 Value::Id(v) => json!({"$mid": v.to_hex()}),
43 }
44 }
45}
46
47impl From<serde_json::Value> for Value {
48 fn from(value: serde_json::Value) -> Self {
49 match value {
50 serde_json::Value::Number(v) => {
51 if let Some(i) = v.as_i64() {
52 Value::I32(i as i32)
53 } else if let Some(u) = v.as_u64() {
54 Value::I32(u as i32)
55 } else if let Some(f) = v.as_f64() {
56 Value::F32(f as f32)
57 } else {
58 unreachable!()
59 }
60 }
61 serde_json::Value::String(v) => v.into(),
62 serde_json::Value::Bool(v) => v.into(),
63 serde_json::Value::Array(v) => {
64 let array: Vec<Value> = v.into_iter().map(|v| v.into()).collect();
65 Value::Array(Array::from_vec(array))
66 }
67 serde_json::Value::Object(map) => {
68 if map.len() == 1 {
69 let keys: Vec<_> = map.keys().map(|s| s.as_str()).collect();
70
71 match keys.as_slice() {
72 ["$tim"] => {
73 if let Some(v) = map.get("$tim")
74 && let Some(u) = v.as_u64()
75 {
76 return Value::TimeStamp(u.into());
77 }
78 }
79 ["$bin"] => {
80 if let Some(v) = map.get("$bin")
81 && let Some(hex) = v.as_str()
82 && let Ok(bin) = general_purpose::STANDARD.decode(hex)
83 {
84 return bin.into();
85 }
86 }
87 ["$mid"] => {
88 if let Some(v) = map.get("$mid")
89 && let Some(hex) = v.as_str()
90 && let Ok(message_id) = Id::with_string(hex)
91 {
92 return message_id.into();
93 }
94 }
95 ["$f64"] => {
96 if let Some(v) = map.get("$f64")
97 && let Some(f) = v.as_f64()
98 {
99 return Value::F64(f);
100 }
101 }
102 ["$i64"] => {
103 if let Some(v) = map.get("$i64")
104 && let Some(i) = v.as_i64()
105 {
106 return Value::I64(i);
107 }
108 }
109 ["$u32"] => {
110 if let Some(v) = map.get("$u32")
111 && let Some(u) = v.as_u64()
112 {
113 return Value::U32(u as u32);
114 }
115 }
116 ["$u64"] => {
117 if let Some(v) = map.get("$u64")
118 && let Some(u) = v.as_u64()
119 {
120 return Value::U64(u);
121 }
122 }
123 ["$i8"] => {
124 if let Some(v) = map.get("$i8")
125 && let Some(i) = v.as_i64()
126 {
127 return Value::I8(i as i8);
128 }
129 }
130 ["$u8"] => {
131 if let Some(v) = map.get("$u8")
132 && let Some(u) = v.as_u64()
133 {
134 return Value::U8(u as u8);
135 }
136 }
137 ["$i16"] => {
138 if let Some(v) = map.get("$i16")
139 && let Some(i) = v.as_i64()
140 {
141 return Value::I16(i as i16);
142 }
143 }
144 ["$u16"] => {
145 if let Some(v) = map.get("$u16")
146 && let Some(u) = v.as_u64()
147 {
148 return Value::U16(u as u16);
149 }
150 }
151 _ => (),
152 }
153 }
154
155 let map: NsonMap = map.into_iter().map(|(k, v)| (k, v.into())).collect();
156
157 Value::Map(map)
158 }
159 serde_json::Value::Null => Value::Null,
160 }
161 }
162}
163
164impl From<NsonMap> for serde_json::Value {
165 fn from(map: NsonMap) -> Self {
166 Value::Map(map).into()
167 }
168}
169
170impl From<serde_json::Value> for NsonMap {
171 fn from(json: serde_json::Value) -> Self {
172 let value: Value = json.into();
173
174 match value {
175 Value::Map(map) => map,
176 _ => NsonMap::new(),
177 }
178 }
179}
180
181#[cfg(test)]
182mod test {
183 use crate::{Id, TimeStamp, Value, m};
184 use serde_json::{self, json};
185
186 use crate::__vec;
187
188 #[test]
189 fn convert_json() {
190 let json = json!({
191 "a": 1i32,
192 "b": {"$i64": 2i64},
193 "c": {"$u32": 3u32},
194 "d": {"$u64": 4u64},
195 "e": 5.6f32,
196 "f": {"$f64": 7.8f64},
197 "g": {
198 "$tim": 456
199 },
200 "h": {
201 "$mid": "0171253e54db9aef760d5fbd"
202 },
203 "i": {
204 "$bin": "AQIDBAUG"
205 }
206 });
207
208 let message = m! {
209 "a": 1i32,
210 "b": 2i64,
211 "c": 3u32,
212 "d": 4u64,
213 "e": 5.6f32,
214 "f": 7.8f64,
215 "g": TimeStamp(456),
216 "h": Id::with_string("0171253e54db9aef760d5fbd").unwrap(),
217 "i": __vec![1u8, 2, 3, 4, 5, 6]
218 };
219
220 let nson_value: Value = message.clone().into();
221
222 let value: serde_json::Value = message.into();
223
224 assert!(json == value);
225
226 let value2: Value = json.into();
227
228 assert!(nson_value == value2);
229 }
230}