1use alloc::string::String;
7use alloc::vec::Vec;
8use azul_css::{
9 impl_option, impl_option_inner, impl_result, impl_result_inner, impl_vec, impl_vec_clone,
10 impl_vec_debug, impl_vec_mut, impl_vec_partialeq, AzString, OptionBool, OptionF64,
11 OptionString,
12};
13use core::fmt;
14
15#[derive(Debug, Clone, PartialEq)]
21#[repr(C)]
22pub struct Json {
23 pub value_type: JsonType,
25 pub internal: JsonInternal,
28}
29
30#[derive(Debug, Clone, PartialEq)]
38#[repr(C)]
39pub struct JsonInternal {
40 pub string_value: AzString,
42 pub number_value: f64,
44 pub bool_value: bool,
46}
47
48impl Default for Json {
51 fn default() -> Self {
52 Self::null()
53 }
54}
55
56impl Default for JsonInternal {
57 fn default() -> Self {
58 Self {
59 string_value: AzString::from(String::new()),
60 number_value: 0.0,
61 bool_value: false,
62 }
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68#[repr(C)]
69pub enum JsonType {
70 Null,
72 Bool,
74 Number,
76 String,
78 Array,
80 Object,
82}
83
84#[derive(Debug, Clone, PartialEq, Eq)]
86#[repr(C)]
87pub struct JsonParseError {
88 pub message: AzString,
90 pub line: u32,
92 pub column: u32,
94}
95
96impl fmt::Display for JsonParseError {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 if self.line > 0 {
99 write!(
100 f,
101 "{}:{}: {}",
102 self.line,
103 self.column,
104 self.message.as_str()
105 )
106 } else {
107 write!(f, "{}", self.message.as_str())
108 }
109 }
110}
111
112#[cfg(feature = "std")]
113impl std::error::Error for JsonParseError {}
114
115#[derive(Debug, Clone, PartialEq)]
117#[repr(C)]
118pub struct JsonKeyValue {
119 pub key: AzString,
121 pub value: Json,
123}
124
125impl JsonKeyValue {
126 #[must_use]
128 pub const fn create(key: AzString, value: Json) -> Self {
129 Self { key, value }
130 }
131}
132
133impl_option!(
139 JsonKeyValue,
140 OptionJsonKeyValue,
141 copy = false,
142 [Debug, Clone, PartialEq]
143);
144
145impl_vec!(
147 JsonKeyValue,
148 JsonKeyValueVec,
149 JsonKeyValueVecDestructor,
150 JsonKeyValueVecDestructorType,
151 JsonKeyValueVecSlice,
152 OptionJsonKeyValue
153);
154impl_vec_clone!(JsonKeyValue, JsonKeyValueVec, JsonKeyValueVecDestructor);
155impl_vec_debug!(JsonKeyValue, JsonKeyValueVec);
156
157impl JsonKeyValueVec {
158 #[inline]
160 #[allow(clippy::not_unsafe_ptr_arg_deref)]
161 #[must_use]
163 pub fn copy_from_array(ptr: *const JsonKeyValue, len: usize) -> Self {
164 if ptr.is_null() || len == 0 {
165 return Self::new();
166 }
167 let slice = unsafe { core::slice::from_raw_parts(ptr, len) };
168 Self::from_vec(slice.to_vec())
169 }
170}
171
172impl_vec!(
174 Json,
175 JsonVec,
176 JsonVecDestructor,
177 JsonVecDestructorType,
178 JsonVecSlice,
179 OptionJson
180);
181impl_vec_clone!(Json, JsonVec, JsonVecDestructor);
182impl_vec_debug!(Json, JsonVec);
183impl_vec_partialeq!(Json, JsonVec);
184impl_vec_mut!(Json, JsonVec);
185
186impl JsonVec {
187 #[inline]
189 #[allow(clippy::not_unsafe_ptr_arg_deref)]
190 #[must_use]
192 pub fn copy_from_array(ptr: *const Json, len: usize) -> Self {
193 if ptr.is_null() || len == 0 {
194 return Self::new();
195 }
196 let slice = unsafe { core::slice::from_raw_parts(ptr, len) };
197 Self::from_vec(slice.to_vec())
198 }
199}
200
201impl_result!(
203 Json,
204 JsonParseError,
205 ResultJsonJsonParseError,
206 copy = false,
207 [Debug, Clone, PartialEq]
208);
209
210impl_option!(Json, OptionJson, copy = false, [Clone, Debug, PartialEq]);
212impl_option!(JsonVec, OptionJsonVec, copy = false, [Clone, Debug]);
213impl_option!(
214 JsonKeyValueVec,
215 OptionJsonKeyValueVec,
216 copy = false,
217 [Clone, Debug]
218);
219
220impl_option!(
223 i64,
224 OptionI64,
225 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
226);
227
228#[allow(clippy::cast_possible_truncation)] fn f64_as_i64(n: f64) -> Option<i64> {
240 if n.fract() == 0.0 && n >= -(2_f64.powi(63)) && n < 2_f64.powi(63) {
241 Some(n as i64)
242 } else {
243 None
244 }
245}
246
247impl Json {
252 #[must_use]
254 pub fn null() -> Self {
255 Self {
256 value_type: JsonType::Null,
257 internal: JsonInternal::default(),
258 }
259 }
260
261 #[must_use]
263 pub fn bool(value: bool) -> Self {
264 Self {
265 value_type: JsonType::Bool,
266 internal: JsonInternal {
267 string_value: AzString::from(String::new()),
268 number_value: 0.0,
269 bool_value: value,
270 },
271 }
272 }
273
274 #[must_use]
276 pub fn number(value: f64) -> Self {
277 Self {
278 value_type: JsonType::Number,
279 internal: JsonInternal {
280 string_value: AzString::from(String::new()),
281 number_value: value,
282 bool_value: false,
283 },
284 }
285 }
286
287 #[allow(clippy::cast_precision_loss)] #[must_use]
293 pub fn integer(value: i64) -> Self {
294 Self {
295 value_type: JsonType::Number,
296 internal: JsonInternal {
297 string_value: AzString::from(String::new()),
298 number_value: value as f64,
299 bool_value: false,
300 },
301 }
302 }
303
304 pub fn string(value: impl Into<String>) -> Self {
306 Self {
307 value_type: JsonType::String,
308 internal: JsonInternal {
309 string_value: AzString::from(value.into()),
310 number_value: 0.0,
311 bool_value: false,
312 },
313 }
314 }
315
316 #[must_use]
318 pub fn is_null(&self) -> bool {
319 self.value_type == JsonType::Null
320 }
321
322 #[must_use]
324 pub fn is_bool(&self) -> bool {
325 self.value_type == JsonType::Bool
326 }
327
328 #[must_use]
330 pub fn is_number(&self) -> bool {
331 self.value_type == JsonType::Number
332 }
333
334 #[must_use]
336 pub fn is_string(&self) -> bool {
337 self.value_type == JsonType::String
338 }
339
340 #[must_use]
342 pub fn is_array(&self) -> bool {
343 self.value_type == JsonType::Array
344 }
345
346 #[must_use]
348 pub fn is_object(&self) -> bool {
349 self.value_type == JsonType::Object
350 }
351
352 #[must_use]
354 pub fn as_bool(&self) -> OptionBool {
355 if self.value_type == JsonType::Bool {
356 OptionBool::Some(self.internal.bool_value)
357 } else {
358 OptionBool::None
359 }
360 }
361
362 #[must_use]
364 pub fn as_number(&self) -> OptionF64 {
365 if self.value_type == JsonType::Number {
366 OptionF64::Some(self.internal.number_value)
367 } else {
368 OptionF64::None
369 }
370 }
371
372 #[must_use]
374 pub fn as_i64(&self) -> OptionI64 {
375 if self.value_type == JsonType::Number {
376 f64_as_i64(self.internal.number_value).map_or(OptionI64::None, OptionI64::Some)
377 } else {
378 OptionI64::None
379 }
380 }
381
382 #[must_use]
384 pub fn as_string(&self) -> OptionString {
385 if self.value_type == JsonType::String {
386 OptionString::Some(self.internal.string_value.clone())
387 } else {
388 OptionString::None
389 }
390 }
391
392 #[must_use]
394 pub fn raw_string(&self) -> &str {
395 self.internal.string_value.as_str()
396 }
397}
398
399impl fmt::Display for Json {
404 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405 match self.value_type {
406 JsonType::Null => write!(f, "null"),
407 JsonType::Bool => write!(f, "{}", self.internal.bool_value),
408 JsonType::Number => {
409 let num = self.internal.number_value;
410 if let Some(i) = f64_as_i64(num) {
411 write!(f, "{i}")
412 } else {
413 write!(f, "{num}")
414 }
415 }
416 JsonType::String => write!(f, "\"{}\"", self.internal.string_value.as_str()),
417 JsonType::Array | JsonType::Object => {
418 write!(f, "{}", self.internal.string_value.as_str())
419 }
420 }
421 }
422}
423
424#[cfg(feature = "serde-json")]
429impl serde::Serialize for Json {
430 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
437 self.to_serde_value().serialize(s)
438 }
439}
440
441#[cfg(feature = "serde-json")]
442impl<'de> serde::Deserialize<'de> for Json {
443 fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
444 Ok(Self::from_serde_value(serde_json::Value::deserialize(d)?))
445 }
446}
447
448#[cfg(feature = "serde-json")]
449impl Json {
450 pub fn parse(s: &str) -> Result<Self, JsonParseError> {
457 let value: serde_json::Value = serde_json::from_str(s).map_err(|e| JsonParseError {
458 message: AzString::from(alloc::format!("{e}")),
459 line: u32::try_from(e.line()).unwrap_or(u32::MAX),
460 column: u32::try_from(e.column()).unwrap_or(u32::MAX),
461 })?;
462 Ok(Self::from_serde_value(value))
463 }
464
465 pub fn parse_bytes(bytes: &[u8]) -> Result<Self, JsonParseError> {
472 let value: serde_json::Value =
473 serde_json::from_slice(bytes).map_err(|e| JsonParseError {
474 message: AzString::from(alloc::format!("{e}")),
475 line: u32::try_from(e.line()).unwrap_or(u32::MAX),
476 column: u32::try_from(e.column()).unwrap_or(u32::MAX),
477 })?;
478 Ok(Self::from_serde_value(value))
479 }
480
481 #[must_use]
483 pub fn from_serde_value(value: serde_json::Value) -> Self {
484 match value {
485 serde_json::Value::Null => Self::null(),
486 serde_json::Value::Bool(b) => Self::bool(b),
487 serde_json::Value::Number(n) => Self::number(n.as_f64().unwrap_or(0.0)),
488 serde_json::Value::String(s) => Self::string(s),
489 serde_json::Value::Array(arr) => {
490 let json_str =
491 serde_json::to_string(&serde_json::Value::Array(arr)).unwrap_or_default();
492 Self {
493 value_type: JsonType::Array,
494 internal: JsonInternal {
495 string_value: AzString::from(json_str),
496 number_value: 0.0,
497 bool_value: false,
498 },
499 }
500 }
501 serde_json::Value::Object(obj) => {
502 let json_str =
503 serde_json::to_string(&serde_json::Value::Object(obj)).unwrap_or_default();
504 Self {
505 value_type: JsonType::Object,
506 internal: JsonInternal {
507 string_value: AzString::from(json_str),
508 number_value: 0.0,
509 bool_value: false,
510 },
511 }
512 }
513 }
514 }
515
516 #[must_use]
518 pub fn to_serde_value(&self) -> serde_json::Value {
519 match self.value_type {
520 JsonType::Null => serde_json::Value::Null,
521 JsonType::Bool => serde_json::Value::Bool(self.internal.bool_value),
522 JsonType::Number => {
523 let num = self.internal.number_value;
524 f64_as_i64(num).map_or_else(
525 || {
526 serde_json::Number::from_f64(num)
527 .map_or(serde_json::Value::Null, serde_json::Value::Number)
528 },
529 |i| serde_json::Value::Number(serde_json::Number::from(i)),
530 )
531 }
532 JsonType::String => {
533 serde_json::Value::String(self.internal.string_value.as_str().to_string())
534 }
535 JsonType::Array | JsonType::Object => {
536 serde_json::from_str(self.internal.string_value.as_str())
537 .unwrap_or(serde_json::Value::Null)
538 }
539 }
540 }
541
542 #[allow(clippy::needless_pass_by_value)]
545 #[must_use]
546 pub fn array(values: JsonVec) -> Self {
547 let serde_array: Vec<serde_json::Value> =
548 values.as_slice().iter().map(Self::to_serde_value).collect();
549 let json_str = serde_json::to_string(&serde_json::Value::Array(serde_array))
550 .unwrap_or_else(|_| "[]".to_string());
551 Self {
552 value_type: JsonType::Array,
553 internal: JsonInternal {
554 string_value: AzString::from(json_str),
555 number_value: 0.0,
556 bool_value: false,
557 },
558 }
559 }
560
561 #[allow(clippy::needless_pass_by_value)]
564 #[must_use]
565 pub fn object(entries: JsonKeyValueVec) -> Self {
566 let mut map = serde_json::Map::new();
567 for kv in entries.as_slice() {
568 map.insert(kv.key.as_str().to_string(), kv.value.to_serde_value());
569 }
570 let json_str = serde_json::to_string(&serde_json::Value::Object(map))
571 .unwrap_or_else(|_| "{}".to_string());
572 Self {
573 value_type: JsonType::Object,
574 internal: JsonInternal {
575 string_value: AzString::from(json_str),
576 number_value: 0.0,
577 bool_value: false,
578 },
579 }
580 }
581
582 #[must_use]
584 pub fn len(&self) -> usize {
585 match self.value_type {
586 JsonType::Array => {
587 if let Ok(serde_json::Value::Array(arr)) =
588 serde_json::from_str(self.internal.string_value.as_str())
589 {
590 arr.len()
591 } else {
592 0
593 }
594 }
595 JsonType::Object => {
596 if let Ok(serde_json::Value::Object(obj)) =
597 serde_json::from_str(self.internal.string_value.as_str())
598 {
599 obj.len()
600 } else {
601 0
602 }
603 }
604 _ => 0,
605 }
606 }
607
608 #[must_use]
610 pub fn is_empty(&self) -> bool {
611 self.len() == 0
612 }
613
614 #[must_use]
616 pub fn get_index(&self, index: usize) -> Option<Self> {
617 if self.value_type != JsonType::Array {
618 return None;
619 }
620 let value: serde_json::Value =
621 serde_json::from_str(self.internal.string_value.as_str()).ok()?;
622 if let serde_json::Value::Array(arr) = value {
623 arr.get(index).map(|v| Self::from_serde_value(v.clone()))
624 } else {
625 None
626 }
627 }
628
629 #[must_use]
631 pub fn get_key(&self, key: &str) -> Option<Self> {
632 if self.value_type != JsonType::Object {
633 return None;
634 }
635 let value: serde_json::Value =
636 serde_json::from_str(self.internal.string_value.as_str()).ok()?;
637 if let serde_json::Value::Object(obj) = value {
638 obj.get(key).map(|v| Self::from_serde_value(v.clone()))
639 } else {
640 None
641 }
642 }
643
644 #[must_use]
646 pub fn keys(&self) -> Vec<AzString> {
647 if self.value_type != JsonType::Object {
648 return Vec::new();
649 }
650 let value: serde_json::Value =
651 match serde_json::from_str(self.internal.string_value.as_str()) {
652 Ok(v) => v,
653 Err(_) => return Vec::new(),
654 };
655 if let serde_json::Value::Object(obj) = value {
656 obj.keys().map(|k| AzString::from(k.clone())).collect()
657 } else {
658 Vec::new()
659 }
660 }
661
662 pub fn to_array(&self) -> Option<JsonVec> {
664 if self.value_type != JsonType::Array {
665 return None;
666 }
667 let value: serde_json::Value =
668 serde_json::from_str(self.internal.string_value.as_str()).ok()?;
669 if let serde_json::Value::Array(arr) = value {
670 Some(arr.into_iter().map(Self::from_serde_value).collect())
671 } else {
672 None
673 }
674 }
675
676 #[must_use]
678 pub fn to_object(&self) -> Option<JsonKeyValueVec> {
679 if self.value_type != JsonType::Object {
680 return None;
681 }
682 let value: serde_json::Value =
683 serde_json::from_str(self.internal.string_value.as_str()).ok()?;
684 if let serde_json::Value::Object(obj) = value {
685 Some(
686 obj.into_iter()
687 .map(|(k, v)| JsonKeyValue {
688 key: AzString::from(k),
689 value: Self::from_serde_value(v),
690 })
691 .collect(),
692 )
693 } else {
694 None
695 }
696 }
697
698 #[must_use]
700 pub fn to_json_string(&self) -> AzString {
701 match self.value_type {
702 JsonType::Null => AzString::from(alloc::string::String::from("null")),
703 JsonType::Bool => AzString::from(if self.internal.bool_value {
704 alloc::string::String::from("true")
705 } else {
706 alloc::string::String::from("false")
707 }),
708 JsonType::Number => {
709 let num = self.internal.number_value;
710 f64_as_i64(num).map_or_else(
711 || AzString::from(alloc::format!("{num}")),
712 |i| AzString::from(alloc::format!("{i}")),
713 )
714 }
715 JsonType::String => {
716 let escaped =
717 serde_json::to_string(self.internal.string_value.as_str()).unwrap_or_default();
718 AzString::from(escaped)
719 }
720 JsonType::Array | JsonType::Object => self.internal.string_value.clone(),
721 }
722 }
723
724 #[must_use]
726 pub fn to_string_pretty(&self) -> AzString {
727 match self.value_type {
728 JsonType::Null | JsonType::Bool | JsonType::Number | JsonType::String => {
729 self.to_json_string()
730 }
731 JsonType::Array | JsonType::Object => {
732 serde_json::from_str::<serde_json::Value>(self.internal.string_value.as_str())
733 .map_or_else(
734 |_| self.internal.string_value.clone(),
735 |value| {
736 AzString::from(serde_json::to_string_pretty(&value).unwrap_or_default())
737 },
738 )
739 }
740 }
741 }
742
743 #[must_use]
745 pub fn jq(&self, path: &str) -> Self {
746 match self.value_type {
747 JsonType::Null | JsonType::Bool | JsonType::Number | JsonType::String => {
748 if path.is_empty() {
749 self.clone()
750 } else {
751 Self::null()
752 }
753 }
754 JsonType::Array | JsonType::Object => {
755 let value: serde_json::Value =
756 match serde_json::from_str(self.internal.string_value.as_str()) {
757 Ok(v) => v,
758 Err(_) => return Self::null(),
759 };
760 value
761 .pointer(path)
762 .map_or_else(Self::null, |v| Self::from_serde_value(v.clone()))
763 }
764 }
765 }
766
767 #[must_use]
769 pub fn jq_all(&self, path: &str) -> JsonVec {
770 let result = match self.value_type {
771 JsonType::Null | JsonType::Bool | JsonType::Number | JsonType::String => {
772 if path.is_empty() {
773 vec![self.clone()]
774 } else {
775 vec![]
776 }
777 }
778 JsonType::Array | JsonType::Object => {
779 let value: serde_json::Value =
780 match serde_json::from_str(self.internal.string_value.as_str()) {
781 Ok(v) => v,
782 Err(_) => return JsonVec::from_vec(vec![]),
783 };
784 Self::jq_all_recursive(&value, path)
785 }
786 };
787 JsonVec::from_vec(result)
788 }
789
790 const JQ_MAX_WILDCARD_DEPTH: usize = 512;
799
800 fn jq_all_recursive(value: &serde_json::Value, path: &str) -> Vec<Self> {
806 Self::jq_all_recursive_depth(value, path, 0)
807 }
808
809 fn jq_all_recursive_depth(value: &serde_json::Value, path: &str, depth: usize) -> Vec<Self> {
810 if depth > Self::JQ_MAX_WILDCARD_DEPTH {
813 return vec![];
814 }
815
816 let mut value = value;
818 let mut path = path;
819 loop {
820 if path.is_empty() {
821 return vec![Self::from_serde_value(value.clone())];
822 }
823 if !path.starts_with('/') {
824 return vec![];
825 }
826 let rest = &path[1..];
827 let (component, remaining) = rest
828 .find('/')
829 .map_or((rest, ""), |idx| (&rest[..idx], &rest[idx..]));
830
831 if component == "*" {
832 let mut results = Vec::new();
833 match value {
834 serde_json::Value::Array(arr) => {
835 for item in arr {
836 results.extend(Self::jq_all_recursive_depth(
837 item,
838 remaining,
839 depth + 1,
840 ));
841 }
842 }
843 serde_json::Value::Object(obj) => {
844 for (_key, val) in obj {
845 results.extend(Self::jq_all_recursive_depth(val, remaining, depth + 1));
846 }
847 }
848 _ => {}
849 }
850 return results;
851 }
852
853 let next = match value {
855 serde_json::Value::Array(arr) => {
856 component.parse::<usize>().ok().and_then(|idx| arr.get(idx))
857 }
858 serde_json::Value::Object(obj) => obj.get(component),
859 _ => None,
860 };
861 match next {
862 Some(v) => {
863 value = v;
864 path = remaining;
865 }
866 None => return vec![],
867 }
868 }
869 }
870}
871
872#[cfg(test)]
873#[path = "json_test.rs"]
874mod json_test;