1#![doc = include_str!("readme.md")]
2use core::range::Range;
3use oak_core::source::{SourceBuffer, ToSource};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7#[cfg(feature = "oak-pretty-print")]
8use oak_pretty_print::{AsDocument, doc as pp_doc};
9
10#[derive(Clone, Debug, PartialEq)]
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13pub struct JsonRoot {
14 pub value: JsonValue,
16}
17
18impl ToSource for JsonRoot {
19 fn to_source(&self, buffer: &mut SourceBuffer) {
20 self.value.to_source(buffer)
21 }
22}
23
24#[derive(Clone, Debug, PartialEq)]
26#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27#[cfg_attr(feature = "oak-pretty-print", derive(AsDocument))]
28pub enum JsonValue {
29 Object(JsonObject),
31 Array(JsonArray),
33 String(JsonString),
35 Number(JsonNumber),
37 Boolean(JsonBoolean),
39 Null(JsonNull),
41}
42
43impl JsonValue {
44 pub fn as_str(&self) -> Option<&str> {
46 match self {
47 JsonValue::String(s) => Some(&s.value),
48 _ => None,
49 }
50 }
51
52 pub fn as_f64(&self) -> Option<f64> {
54 match self {
55 JsonValue::Number(n) => Some(n.value),
56 _ => None,
57 }
58 }
59
60 pub fn as_bool(&self) -> Option<bool> {
62 match self {
63 JsonValue::Boolean(b) => Some(b.value),
64 _ => None,
65 }
66 }
67
68 pub fn as_u64(&self) -> Option<u64> {
70 self.as_f64().map(|f| f as u64)
71 }
72
73 pub fn as_array(&self) -> Option<&JsonArray> {
75 match self {
76 JsonValue::Array(a) => Some(a),
77 _ => None,
78 }
79 }
80
81 pub fn as_object(&self) -> Option<&JsonObject> {
83 match self {
84 JsonValue::Object(o) => Some(o),
85 _ => None,
86 }
87 }
88
89 pub fn get(&self, key: &str) -> Option<&JsonValue> {
91 match self {
92 JsonValue::Object(o) => o.get(key),
93 _ => None,
94 }
95 }
96
97 pub fn to_string(&self) -> String {
99 match self {
100 JsonValue::Null(_) => "null".to_string(),
101 JsonValue::Boolean(b) => b.value.to_string(),
102 JsonValue::Number(n) => n.value.to_string(),
103 JsonValue::String(s) => format!("\"{}\"", s.value),
104 JsonValue::Array(a) => {
105 let elements: Vec<String> = a.elements.iter().map(|e| e.to_string()).collect();
106 format!("[{}]", elements.join(","))
107 }
108 JsonValue::Object(o) => {
109 let fields: Vec<String> = o.fields.iter().map(|f| format!("\"{}\":{}", f.name.value, f.value.to_string())).collect();
110 format!("{{{}}}", fields.join(","))
111 }
112 }
113 }
114}
115
116impl std::fmt::Display for JsonValue {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 write!(f, "{}", self.to_string())
119 }
120}
121
122impl From<&str> for JsonValue {
123 fn from(s: &str) -> Self {
124 JsonValue::String(JsonString { value: s.to_string(), span: (0..0).into() })
125 }
126}
127
128impl From<String> for JsonValue {
129 fn from(s: String) -> Self {
130 JsonValue::String(JsonString { value: s, span: (0..0).into() })
131 }
132}
133
134impl From<f64> for JsonValue {
135 fn from(f: f64) -> Self {
136 JsonValue::Number(JsonNumber { value: f, span: (0..0).into() })
137 }
138}
139
140impl From<u64> for JsonValue {
141 fn from(u: u64) -> Self {
142 JsonValue::Number(JsonNumber { value: u as f64, span: (0..0).into() })
143 }
144}
145
146impl From<i32> for JsonValue {
147 fn from(i: i32) -> Self {
148 JsonValue::Number(JsonNumber { value: i as f64, span: (0..0).into() })
149 }
150}
151
152impl From<i64> for JsonValue {
153 fn from(i: i64) -> Self {
154 JsonValue::Number(JsonNumber { value: i as f64, span: (0..0).into() })
155 }
156}
157
158impl From<usize> for JsonValue {
159 fn from(u: usize) -> Self {
160 JsonValue::Number(JsonNumber { value: u as f64, span: (0..0).into() })
161 }
162}
163
164impl From<bool> for JsonValue {
165 fn from(b: bool) -> Self {
166 JsonValue::Boolean(JsonBoolean { value: b, span: (0..0).into() })
167 }
168}
169
170impl From<u32> for JsonValue {
171 fn from(value: u32) -> Self {
172 JsonValue::Number(JsonNumber { value: value as f64, span: (0..0).into() })
173 }
174}
175
176impl From<f32> for JsonValue {
177 fn from(value: f32) -> Self {
178 JsonValue::Number(JsonNumber { value: value as f64, span: (0..0).into() })
179 }
180}
181
182impl<T: Into<JsonValue>> From<Option<T>> for JsonValue {
183 fn from(value: Option<T>) -> Self {
184 match value {
185 Some(v) => v.into(),
186 None => JsonValue::Null(JsonNull { span: (0..0).into() }),
187 }
188 }
189}
190
191impl From<()> for JsonValue {
192 fn from(_: ()) -> Self {
193 JsonValue::Null(JsonNull { span: (0..0).into() })
194 }
195}
196
197impl From<Vec<JsonValue>> for JsonValue {
198 fn from(elements: Vec<JsonValue>) -> Self {
199 JsonValue::Array(JsonArray { elements, span: (0..0).into() })
200 }
201}
202
203impl From<std::collections::HashMap<String, JsonValue>> for JsonValue {
204 fn from(fields: std::collections::HashMap<String, JsonValue>) -> Self {
205 let mut fields_vec: Vec<JsonField> = fields.into_iter().map(|(k, v)| JsonField { name: JsonString { value: k, span: (0..0).into() }, value: v, span: (0..0).into() }).collect();
206 fields_vec.sort_by(|a, b| a.name.value.cmp(&b.name.value));
208 JsonValue::Object(JsonObject { fields: fields_vec, span: (0..0).into() })
209 }
210}
211
212impl<T: Into<JsonValue>> FromIterator<T> for JsonValue {
213 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
214 JsonValue::Array(JsonArray { elements: iter.into_iter().map(Into::into).collect(), span: (0..0).into() })
215 }
216}
217
218impl ToSource for JsonValue {
219 fn to_source(&self, buffer: &mut SourceBuffer) {
220 match self {
221 JsonValue::Object(v) => v.to_source(buffer),
222 JsonValue::Array(v) => v.to_source(buffer),
223 JsonValue::String(v) => v.to_source(buffer),
224 JsonValue::Number(v) => v.to_source(buffer),
225 JsonValue::Boolean(v) => v.to_source(buffer),
226 JsonValue::Null(v) => v.to_source(buffer),
227 }
228 }
229}
230
231#[derive(Clone, Debug, PartialEq)]
233#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
234#[cfg_attr(feature = "oak-pretty-print", derive(AsDocument))]
235#[cfg_attr(feature = "oak-pretty-print", oak(doc =
236 if _self.fields.is_empty() {
237 pp_doc!("{}")
238 } else {
239 pp_doc!(group( [
240 "{",
241 indent( [line, join(_self.fields.iter(), [",", line])]),
242 line,
243 "}"
244 ]))
245 }
246))]
247pub struct JsonObject {
248 pub fields: Vec<JsonField>,
250 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
252 pub span: Range<usize>,
253}
254
255impl JsonObject {
256 pub fn get(&self, key: &str) -> Option<&JsonValue> {
258 self.fields.iter().find(|f| f.name.value == key).map(|f| &f.value)
259 }
260}
261
262impl ToSource for JsonObject {
263 fn to_source(&self, buffer: &mut SourceBuffer) {
264 buffer.push("{");
265 for (i, field) in self.fields.iter().enumerate() {
266 if i > 0 {
267 buffer.push(",")
268 }
269 field.to_source(buffer)
270 }
271 buffer.push("}")
272 }
273}
274
275#[derive(Clone, Debug, PartialEq)]
277#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
278#[cfg_attr(feature = "oak-pretty-print", derive(AsDocument))]
279#[cfg_attr(feature = "oak-pretty-print", oak(doc = [self.name.as_document(), ": ", self.value.as_document()]))]
280pub struct JsonField {
281 pub name: JsonString,
283 pub value: JsonValue,
285 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
287 pub span: Range<usize>,
288}
289
290impl ToSource for JsonField {
291 fn to_source(&self, buffer: &mut SourceBuffer) {
292 self.name.to_source(buffer);
293 buffer.push(":");
294 self.value.to_source(buffer)
295 }
296}
297
298#[derive(Clone, Debug, PartialEq)]
300#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
301#[cfg_attr(feature = "oak-pretty-print", derive(AsDocument))]
302#[cfg_attr(feature = "oak-pretty-print", oak(doc =
303 if _self.elements.is_empty() {
304 pp_doc!("[]")
305 } else {
306 pp_doc!(group( [
307 "[",
308 indent( [line, join(_self.elements.iter(), [",", line])]),
309 line,
310 "]"
311 ]))
312 }
313))]
314pub struct JsonArray {
315 pub elements: Vec<JsonValue>,
317 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
319 pub span: Range<usize>,
320}
321
322impl ToSource for JsonArray {
323 fn to_source(&self, buffer: &mut SourceBuffer) {
324 buffer.push("[");
325 for (i, element) in self.elements.iter().enumerate() {
326 if i > 0 {
327 buffer.push(",")
328 }
329 element.to_source(buffer)
330 }
331 buffer.push("]")
332 }
333}
334
335#[derive(Clone, Debug, PartialEq)]
337#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
338#[cfg_attr(feature = "oak-pretty-print", derive(AsDocument))]
339#[cfg_attr(feature = "oak-pretty-print", oak(doc = format!("\"{}\"", self.value)))]
340pub struct JsonString {
341 pub value: String,
343 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
345 pub span: Range<usize>,
346}
347
348impl ToSource for JsonString {
349 fn to_source(&self, buffer: &mut SourceBuffer) {
350 buffer.push("\"");
351 buffer.push(&self.value);
352 buffer.push("\"")
353 }
354}
355
356#[derive(Clone, Debug, PartialEq)]
358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
359#[cfg_attr(feature = "oak-pretty-print", derive(AsDocument))]
360#[cfg_attr(feature = "oak-pretty-print", oak(doc = self.value.to_string()))]
361pub struct JsonNumber {
362 pub value: f64,
364 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
366 pub span: Range<usize>,
367}
368
369impl ToSource for JsonNumber {
370 fn to_source(&self, buffer: &mut SourceBuffer) {
371 buffer.push(&self.value.to_string())
372 }
373}
374
375#[derive(Clone, Debug, PartialEq)]
377#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
378#[cfg_attr(feature = "oak-pretty-print", derive(AsDocument))]
379#[cfg_attr(feature = "oak-pretty-print", oak(doc = if self.value { "true" } else { "false" }))]
380pub struct JsonBoolean {
381 pub value: bool,
383 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
385 pub span: Range<usize>,
386}
387
388impl ToSource for JsonBoolean {
389 fn to_source(&self, buffer: &mut SourceBuffer) {
390 buffer.push(if self.value { "true" } else { "false" })
391 }
392}
393
394#[derive(Clone, Debug, PartialEq)]
396#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
397#[cfg_attr(feature = "oak-pretty-print", derive(AsDocument))]
398#[cfg_attr(feature = "oak-pretty-print", oak(doc = "null"))]
399pub struct JsonNull {
400 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
402 pub span: Range<usize>,
403}
404
405impl ToSource for JsonNull {
406 fn to_source(&self, buffer: &mut SourceBuffer) {
407 buffer.push("null")
408 }
409}