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