1use std::fmt;
5use std::rc::Rc;
6
7use indexmap::IndexMap;
8use serde::de::{self, Deserializer, MapAccess, SeqAccess, Visitor};
9use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
10
11#[derive(Clone, Debug)]
17pub enum JValue {
18 Null,
20 Bool(bool),
21 Number(f64),
22 String(Rc<str>),
23 Array(Rc<Vec<JValue>>),
24 Object(Rc<IndexMap<String, JValue>>),
25
26 Undefined,
28 Lambda {
29 lambda_id: Rc<str>,
30 params: Rc<Vec<String>>,
31 name: Option<Rc<str>>,
32 signature: Option<Rc<str>>,
33 },
34 Builtin {
35 name: Rc<str>,
36 },
37 Regex {
38 pattern: Rc<str>,
39 flags: Rc<str>,
40 },
41}
42
43impl JValue {
46 #[inline]
47 pub fn is_null(&self) -> bool {
48 matches!(self, JValue::Null)
49 }
50
51 #[inline]
52 pub fn is_undefined(&self) -> bool {
53 matches!(self, JValue::Undefined)
54 }
55
56 #[inline]
57 pub fn is_bool(&self) -> bool {
58 matches!(self, JValue::Bool(_))
59 }
60
61 #[inline]
62 pub fn is_number(&self) -> bool {
63 matches!(self, JValue::Number(_))
64 }
65
66 #[inline]
67 pub fn is_string(&self) -> bool {
68 matches!(self, JValue::String(_))
69 }
70
71 #[inline]
72 pub fn is_array(&self) -> bool {
73 matches!(self, JValue::Array(_))
74 }
75
76 #[inline]
77 pub fn is_object(&self) -> bool {
78 matches!(self, JValue::Object(_))
79 }
80
81 #[inline]
82 pub fn is_lambda(&self) -> bool {
83 matches!(self, JValue::Lambda { .. })
84 }
85
86 #[inline]
87 pub fn is_builtin(&self) -> bool {
88 matches!(self, JValue::Builtin { .. })
89 }
90
91 #[inline]
92 pub fn is_function(&self) -> bool {
93 matches!(self, JValue::Lambda { .. } | JValue::Builtin { .. })
94 }
95
96 #[inline]
97 pub fn is_regex(&self) -> bool {
98 matches!(self, JValue::Regex { .. })
99 }
100}
101
102impl JValue {
105 #[inline]
106 pub fn as_f64(&self) -> Option<f64> {
107 match self {
108 JValue::Number(n) => Some(*n),
109 _ => None,
110 }
111 }
112
113 #[inline]
114 pub fn as_i64(&self) -> Option<i64> {
115 match self {
116 JValue::Number(n) => {
117 let f = *n;
118 if f.fract() == 0.0 && f >= i64::MIN as f64 && f <= i64::MAX as f64 {
119 Some(f as i64)
120 } else {
121 None
122 }
123 }
124 _ => None,
125 }
126 }
127
128 #[inline]
129 pub fn as_str(&self) -> Option<&str> {
130 match self {
131 JValue::String(s) => Some(s),
132 _ => None,
133 }
134 }
135
136 #[inline]
137 pub fn as_bool(&self) -> Option<bool> {
138 match self {
139 JValue::Bool(b) => Some(*b),
140 _ => None,
141 }
142 }
143
144 #[inline]
145 pub fn as_array(&self) -> Option<&Vec<JValue>> {
146 match self {
147 JValue::Array(arr) => Some(arr),
148 _ => None,
149 }
150 }
151
152 #[inline]
153 pub fn as_object(&self) -> Option<&IndexMap<String, JValue>> {
154 match self {
155 JValue::Object(map) => Some(map),
156 _ => None,
157 }
158 }
159
160 #[inline]
162 pub fn as_array_mut(&mut self) -> Option<&mut Vec<JValue>> {
163 match self {
164 JValue::Array(arr) => Some(Rc::make_mut(arr)),
165 _ => None,
166 }
167 }
168
169 #[inline]
171 pub fn as_object_mut(&mut self) -> Option<&mut IndexMap<String, JValue>> {
172 match self {
173 JValue::Object(map) => Some(Rc::make_mut(map)),
174 _ => None,
175 }
176 }
177
178 #[inline]
180 pub fn as_rc_str(&self) -> Option<&Rc<str>> {
181 match self {
182 JValue::String(s) => Some(s),
183 _ => None,
184 }
185 }
186
187 #[inline]
189 pub fn get(&self, key: &str) -> Option<&JValue> {
190 match self {
191 JValue::Object(map) => map.get(key),
192 _ => None,
193 }
194 }
195
196 #[inline]
198 pub fn get_index(&self, index: usize) -> Option<&JValue> {
199 match self {
200 JValue::Array(arr) => arr.get(index),
201 _ => None,
202 }
203 }
204}
205
206impl JValue {
209 #[inline]
210 pub fn from_i64(n: i64) -> Self {
211 JValue::Number(n as f64)
212 }
213
214 #[inline]
215 pub fn from_f64(n: f64) -> Self {
216 JValue::Number(n)
217 }
218
219 #[inline]
220 pub fn string(s: impl Into<Rc<str>>) -> Self {
221 JValue::String(s.into())
222 }
223
224 #[inline]
225 pub fn array(v: Vec<JValue>) -> Self {
226 JValue::Array(Rc::new(v))
227 }
228
229 #[inline]
230 pub fn object(m: IndexMap<String, JValue>) -> Self {
231 JValue::Object(Rc::new(m))
232 }
233
234 #[inline]
235 pub fn lambda(
236 lambda_id: impl Into<Rc<str>>,
237 params: Vec<String>,
238 name: Option<impl Into<Rc<str>>>,
239 signature: Option<impl Into<Rc<str>>>,
240 ) -> Self {
241 JValue::Lambda {
242 lambda_id: lambda_id.into(),
243 params: Rc::new(params),
244 name: name.map(|n| n.into()),
245 signature: signature.map(|s| s.into()),
246 }
247 }
248
249 #[inline]
250 pub fn builtin(name: impl Into<Rc<str>>) -> Self {
251 JValue::Builtin { name: name.into() }
252 }
253
254 #[inline]
255 pub fn regex(pattern: impl Into<Rc<str>>, flags: impl Into<Rc<str>>) -> Self {
256 JValue::Regex {
257 pattern: pattern.into(),
258 flags: flags.into(),
259 }
260 }
261}
262
263impl From<bool> for JValue {
266 #[inline]
267 fn from(b: bool) -> Self {
268 JValue::Bool(b)
269 }
270}
271
272impl From<i64> for JValue {
273 #[inline]
274 fn from(n: i64) -> Self {
275 JValue::Number(n as f64)
276 }
277}
278
279impl From<i32> for JValue {
280 #[inline]
281 fn from(n: i32) -> Self {
282 JValue::Number(n as f64)
283 }
284}
285
286impl From<u64> for JValue {
287 #[inline]
288 fn from(n: u64) -> Self {
289 JValue::Number(n as f64)
290 }
291}
292
293impl From<usize> for JValue {
294 #[inline]
295 fn from(n: usize) -> Self {
296 JValue::Number(n as f64)
297 }
298}
299
300impl From<f64> for JValue {
301 #[inline]
302 fn from(n: f64) -> Self {
303 JValue::Number(n)
304 }
305}
306
307impl From<&str> for JValue {
308 #[inline]
309 fn from(s: &str) -> Self {
310 JValue::String(s.into())
311 }
312}
313
314impl From<String> for JValue {
315 #[inline]
316 fn from(s: String) -> Self {
317 JValue::String(s.into())
318 }
319}
320
321impl From<Rc<str>> for JValue {
322 #[inline]
323 fn from(s: Rc<str>) -> Self {
324 JValue::String(s)
325 }
326}
327
328impl From<Vec<JValue>> for JValue {
329 #[inline]
330 fn from(v: Vec<JValue>) -> Self {
331 JValue::Array(Rc::new(v))
332 }
333}
334
335impl From<IndexMap<String, JValue>> for JValue {
336 #[inline]
337 fn from(m: IndexMap<String, JValue>) -> Self {
338 JValue::Object(Rc::new(m))
339 }
340}
341
342impl PartialEq for JValue {
345 fn eq(&self, other: &Self) -> bool {
346 match (self, other) {
347 (JValue::Null, JValue::Null) => true,
348 (JValue::Undefined, JValue::Undefined) => true,
349 (JValue::Bool(a), JValue::Bool(b)) => a == b,
350 (JValue::Number(a), JValue::Number(b)) => {
351 if a.is_nan() && b.is_nan() {
353 return false;
354 }
355 a == b
356 }
357 (JValue::String(a), JValue::String(b)) => a == b,
358 (JValue::Array(a), JValue::Array(b)) => a == b,
359 (JValue::Object(a), JValue::Object(b)) => a == b,
360 (JValue::Lambda { lambda_id: a, .. }, JValue::Lambda { lambda_id: b, .. }) => a == b,
361 (JValue::Builtin { name: a }, JValue::Builtin { name: b }) => a == b,
362 (
363 JValue::Regex {
364 pattern: ap,
365 flags: af,
366 },
367 JValue::Regex {
368 pattern: bp,
369 flags: bf,
370 },
371 ) => ap == bp && af == bf,
372 _ => false,
373 }
374 }
375}
376
377impl fmt::Display for JValue {
380 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
381 match self {
382 JValue::Null => write!(f, "null"),
383 JValue::Undefined => write!(f, "undefined"),
384 JValue::Bool(b) => write!(f, "{}", b),
385 JValue::Number(n) => format_number(*n, f),
386 JValue::String(s) => write!(f, "\"{}\"", escape_json_string(s)),
387 JValue::Array(arr) => {
388 write!(f, "[")?;
389 for (i, v) in arr.iter().enumerate() {
390 if i > 0 {
391 write!(f, ",")?;
392 }
393 write!(f, "{}", v)?;
394 }
395 write!(f, "]")
396 }
397 JValue::Object(map) => {
398 write!(f, "{{")?;
399 for (i, (k, v)) in map.iter().enumerate() {
400 if i > 0 {
401 write!(f, ",")?;
402 }
403 write!(f, "\"{}\":{}", escape_json_string(k), v)?;
404 }
405 write!(f, "}}")
406 }
407 JValue::Lambda { lambda_id, .. } => write!(f, "\"<lambda:{}>\"", lambda_id),
408 JValue::Builtin { name } => write!(f, "\"<builtin:{}>\"", name),
409 JValue::Regex { pattern, flags } => write!(f, "\"<regex:/{}/{}>\"", pattern, flags),
410 }
411 }
412}
413
414fn escape_json_string(s: &str) -> String {
415 let mut result = String::with_capacity(s.len());
416 for c in s.chars() {
417 match c {
418 '"' => result.push_str("\\\""),
419 '\\' => result.push_str("\\\\"),
420 '\n' => result.push_str("\\n"),
421 '\r' => result.push_str("\\r"),
422 '\t' => result.push_str("\\t"),
423 c if c < '\x20' => {
424 result.push_str(&format!("\\u{:04x}", c as u32));
425 }
426 c => result.push(c),
427 }
428 }
429 result
430}
431
432fn format_number(n: f64, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433 if !n.is_finite() {
434 write!(f, "null")
436 } else if n.fract() == 0.0 && n.abs() < 1e20 {
437 write!(f, "{}", n as i64)
438 } else {
439 write!(f, "{}", n)
441 }
442}
443
444impl Serialize for JValue {
447 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
448 where
449 S: Serializer,
450 {
451 match self {
452 JValue::Null => serializer.serialize_none(),
453 JValue::Undefined => serializer.serialize_none(),
454 JValue::Bool(b) => serializer.serialize_bool(*b),
455 JValue::Number(n) => {
456 if n.is_nan() || n.is_infinite() {
457 serializer.serialize_none()
458 } else if n.fract() == 0.0 && *n >= i64::MIN as f64 && *n <= i64::MAX as f64 {
459 serializer.serialize_i64(*n as i64)
460 } else {
461 serializer.serialize_f64(*n)
462 }
463 }
464 JValue::String(s) => serializer.serialize_str(s),
465 JValue::Array(arr) => {
466 let mut seq = serializer.serialize_seq(Some(arr.len()))?;
467 for v in arr.iter() {
468 seq.serialize_element(v)?;
469 }
470 seq.end()
471 }
472 JValue::Object(map) => {
473 let mut m = serializer.serialize_map(Some(map.len()))?;
474 for (k, v) in map.iter() {
475 m.serialize_entry(k, v)?;
476 }
477 m.end()
478 }
479 JValue::Lambda { .. } => serializer.serialize_str(""),
480 JValue::Builtin { .. } => serializer.serialize_str(""),
481 JValue::Regex { pattern, flags } => {
482 let mut m = serializer.serialize_map(Some(2))?;
483 m.serialize_entry("pattern", &**pattern)?;
484 m.serialize_entry("flags", &**flags)?;
485 m.end()
486 }
487 }
488 }
489}
490
491impl<'de> serde::Deserialize<'de> for JValue {
494 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
495 where
496 D: Deserializer<'de>,
497 {
498 deserializer.deserialize_any(JValueVisitor)
499 }
500}
501
502struct JValueVisitor;
503
504impl<'de> Visitor<'de> for JValueVisitor {
505 type Value = JValue;
506
507 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
508 write!(f, "any valid JSON value")
509 }
510
511 fn visit_bool<E: de::Error>(self, v: bool) -> Result<JValue, E> {
512 Ok(JValue::Bool(v))
513 }
514
515 fn visit_i64<E: de::Error>(self, v: i64) -> Result<JValue, E> {
516 Ok(JValue::Number(v as f64))
517 }
518
519 fn visit_u64<E: de::Error>(self, v: u64) -> Result<JValue, E> {
520 Ok(JValue::Number(v as f64))
521 }
522
523 fn visit_f64<E: de::Error>(self, v: f64) -> Result<JValue, E> {
524 Ok(JValue::Number(v))
525 }
526
527 fn visit_str<E: de::Error>(self, v: &str) -> Result<JValue, E> {
528 Ok(JValue::string(v))
529 }
530
531 fn visit_string<E: de::Error>(self, v: String) -> Result<JValue, E> {
532 Ok(JValue::String(v.into()))
533 }
534
535 fn visit_none<E: de::Error>(self) -> Result<JValue, E> {
536 Ok(JValue::Null)
537 }
538
539 fn visit_unit<E: de::Error>(self) -> Result<JValue, E> {
540 Ok(JValue::Null)
541 }
542
543 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<JValue, A::Error> {
544 let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or(0));
545 while let Some(elem) = seq.next_element()? {
546 vec.push(elem);
547 }
548 Ok(JValue::array(vec))
549 }
550
551 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<JValue, A::Error> {
552 let mut m = IndexMap::with_capacity(map.size_hint().unwrap_or(0));
553 while let Some((k, v)) = map.next_entry()? {
554 m.insert(k, v);
555 }
556 Ok(JValue::object(m))
557 }
558}
559
560impl JValue {
563 pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
565 serde_json::to_string(self)
566 }
567
568 pub fn to_json_string_pretty(&self) -> Result<String, serde_json::Error> {
570 serde_json::to_string_pretty(self)
571 }
572
573 pub fn from_json_str(s: &str) -> Result<JValue, serde_json::Error> {
578 #[cfg(feature = "simd")]
579 {
580 let mut bytes = s.as_bytes().to_vec();
582 if let Ok(value) = simd_json::serde::from_slice::<JValue>(&mut bytes) {
583 return Ok(value);
584 }
585 }
587 serde_json::from_str(s)
588 }
589}
590
591impl From<serde_json::Value> for JValue {
594 fn from(v: serde_json::Value) -> Self {
595 match v {
596 serde_json::Value::Null => JValue::Null,
597 serde_json::Value::Bool(b) => JValue::Bool(b),
598 serde_json::Value::Number(n) => JValue::Number(n.as_f64().unwrap_or(0.0)),
599 serde_json::Value::String(s) => JValue::String(s.into()),
600 serde_json::Value::Array(arr) => {
601 JValue::Array(Rc::new(arr.into_iter().map(JValue::from).collect()))
602 }
603 serde_json::Value::Object(map) => {
604 let m: IndexMap<String, JValue> =
605 map.into_iter().map(|(k, v)| (k, JValue::from(v))).collect();
606 JValue::Object(Rc::new(m))
607 }
608 }
609 }
610}
611
612impl From<&JValue> for serde_json::Value {
615 fn from(v: &JValue) -> Self {
616 match v {
617 JValue::Null | JValue::Undefined => serde_json::Value::Null,
618 JValue::Bool(b) => serde_json::Value::Bool(*b),
619 JValue::Number(n) => {
620 if n.is_nan() || n.is_infinite() {
621 serde_json::Value::Null
622 } else {
623 serde_json::json!(*n)
624 }
625 }
626 JValue::String(s) => serde_json::Value::String(s.to_string()),
627 JValue::Array(arr) => {
628 serde_json::Value::Array(arr.iter().map(serde_json::Value::from).collect())
629 }
630 JValue::Object(map) => {
631 let m: serde_json::Map<String, serde_json::Value> = map
632 .iter()
633 .map(|(k, v)| (k.clone(), serde_json::Value::from(v)))
634 .collect();
635 serde_json::Value::Object(m)
636 }
637 JValue::Lambda { .. } | JValue::Builtin { .. } => serde_json::Value::Null,
638 JValue::Regex { pattern, flags } => {
639 let mut m = serde_json::Map::new();
640 m.insert(
641 "pattern".to_string(),
642 serde_json::Value::String(pattern.to_string()),
643 );
644 m.insert(
645 "flags".to_string(),
646 serde_json::Value::String(flags.to_string()),
647 );
648 serde_json::Value::Object(m)
649 }
650 }
651 }
652}
653
654#[macro_export]
669macro_rules! jvalue {
670 (null) => {
672 $crate::value::JValue::Null
673 };
674
675 (true) => {
677 $crate::value::JValue::Bool(true)
678 };
679
680 (false) => {
682 $crate::value::JValue::Bool(false)
683 };
684
685 ([ $($elem:tt),* $(,)? ]) => {
687 $crate::value::JValue::Array(std::rc::Rc::new(vec![ $( jvalue!($elem) ),* ]))
688 };
689
690 ({ $($key:tt : $val:tt),* $(,)? }) => {
692 {
693 let mut map = indexmap::IndexMap::new();
694 $(
695 map.insert(($key).to_string(), jvalue!($val));
696 )*
697 $crate::value::JValue::Object(std::rc::Rc::new(map))
698 }
699 };
700
701 ($other:expr) => {
703 $crate::value::JValue::from($other)
704 };
705}
706
707#[cfg(test)]
710mod tests {
711 use super::*;
712
713 #[test]
714 fn test_clone_is_cheap() {
715 let arr = JValue::array(vec![
717 JValue::from(1i64),
718 JValue::from(2i64),
719 JValue::from(3i64),
720 ]);
721 let arr2 = arr.clone();
722 if let (JValue::Array(a), JValue::Array(b)) = (&arr, &arr2) {
723 assert!(Rc::ptr_eq(a, b));
724 } else {
725 panic!("expected arrays");
726 }
727
728 let mut map = IndexMap::new();
730 map.insert("x".to_string(), JValue::from(1i64));
731 let obj = JValue::object(map);
732 let obj2 = obj.clone();
733 if let (JValue::Object(a), JValue::Object(b)) = (&obj, &obj2) {
734 assert!(Rc::ptr_eq(a, b));
735 } else {
736 panic!("expected objects");
737 }
738
739 let s = JValue::string("hello");
741 let s2 = s.clone();
742 if let (JValue::String(a), JValue::String(b)) = (&s, &s2) {
743 assert!(Rc::ptr_eq(a, b));
744 } else {
745 panic!("expected strings");
746 }
747 }
748
749 #[test]
750 fn test_type_checks() {
751 assert!(JValue::Null.is_null());
752 assert!(JValue::Undefined.is_undefined());
753 assert!(JValue::Bool(true).is_bool());
754 assert!(JValue::Number(42.0).is_number());
755 assert!(JValue::string("hello").is_string());
756 assert!(JValue::array(vec![]).is_array());
757 assert!(JValue::object(IndexMap::new()).is_object());
758 assert!(JValue::lambda("id", vec![], None::<&str>, None::<&str>).is_lambda());
759 assert!(JValue::lambda("id", vec![], None::<&str>, None::<&str>).is_function());
760 assert!(JValue::builtin("sum").is_builtin());
761 assert!(JValue::builtin("sum").is_function());
762 assert!(JValue::regex(".*", "i").is_regex());
763 }
764
765 #[test]
766 fn test_extraction() {
767 assert_eq!(JValue::Number(42.0).as_f64(), Some(42.0));
768 assert_eq!(JValue::Number(42.0).as_i64(), Some(42));
769 assert_eq!(JValue::Number(42.5).as_i64(), None);
770 assert_eq!(JValue::string("hello").as_str(), Some("hello"));
771 assert_eq!(JValue::Bool(true).as_bool(), Some(true));
772 assert_eq!(
773 JValue::array(vec![JValue::from(1i64)])
774 .as_array()
775 .map(|a| a.len()),
776 Some(1)
777 );
778 }
779
780 #[test]
781 fn test_jvalue_macro() {
782 let n = jvalue!(null);
783 assert!(n.is_null());
784
785 let b = jvalue!(true);
786 assert_eq!(b.as_bool(), Some(true));
787
788 let arr = jvalue!([1i64, 2i64, 3i64]);
789 assert_eq!(arr.as_array().map(|a| a.len()), Some(3));
790
791 let obj = jvalue!({"name": "Alice", "age": 30i64});
792 assert_eq!(obj.get("name").and_then(|v| v.as_str()), Some("Alice"));
793 }
794
795 #[test]
796 fn test_equality() {
797 assert_eq!(JValue::Null, JValue::Null);
798 assert_eq!(JValue::Bool(true), JValue::Bool(true));
799 assert_ne!(JValue::Bool(true), JValue::Bool(false));
800 assert_eq!(JValue::Number(42.0), JValue::Number(42.0));
801 assert_ne!(JValue::Number(f64::NAN), JValue::Number(f64::NAN));
802 assert_eq!(JValue::string("hello"), JValue::string("hello"));
803 assert_ne!(JValue::Null, JValue::Undefined);
804 }
805
806 #[test]
807 fn test_serde_roundtrip() {
808 let v = jvalue!({"name": "Alice", "scores": [1i64, 2i64, 3i64], "active": true});
809 let json_str = v.to_json_string().unwrap();
810 let parsed = JValue::from_json_str(&json_str).unwrap();
811 assert_eq!(v, parsed);
812 }
813
814 #[test]
815 fn test_from_serde_json() {
816 let sv = serde_json::json!({"name": "Alice", "age": 30, "scores": [1, 2, 3]});
817 let jv = JValue::from(sv);
818 assert_eq!(jv.get("name").and_then(|v| v.as_str()), Some("Alice"));
819 assert_eq!(jv.get("age").and_then(|v| v.as_f64()), Some(30.0));
820 }
821
822 #[test]
823 fn test_make_mut() {
824 let mut arr = JValue::array(vec![JValue::from(1i64), JValue::from(2i64)]);
825 let arr2 = arr.clone();
826
827 arr.as_array_mut().unwrap().push(JValue::from(3i64));
829
830 assert_eq!(arr.as_array().unwrap().len(), 3);
832 assert_eq!(arr2.as_array().unwrap().len(), 2);
833 }
834}