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