1use core::ops::Index;
13
14use bumpalo::Bump;
15
16#[cfg(feature = "datetime")]
17use crate::datetime::{DataDateTime, DataDuration};
18use crate::number::NumberValue;
19use crate::parser::ParseError;
20use crate::value::DataValue;
21
22#[derive(Debug, Clone, Default)]
25pub enum OwnedDataValue {
26 #[default]
27 Null,
28 Bool(bool),
29 Number(NumberValue),
30 String(String),
31 Array(Vec<OwnedDataValue>),
32 Object(Vec<(String, OwnedDataValue)>),
33 #[cfg(feature = "datetime")]
34 DateTime(DataDateTime),
35 #[cfg(feature = "datetime")]
36 Duration(DataDuration),
37}
38
39static OWNED_NULL: OwnedDataValue = OwnedDataValue::Null;
40
41impl core::str::FromStr for OwnedDataValue {
42 type Err = ParseError;
43 fn from_str(s: &str) -> Result<Self, Self::Err> {
44 let arena = Bump::new();
45 let v = DataValue::from_str(s, &arena)?;
46 Ok(v.to_owned())
47 }
48}
49
50impl OwnedDataValue {
51 pub fn from_json(input: &str) -> Result<Self, ParseError> {
60 input.parse()
61 }
62
63 #[inline]
66 pub fn is_null(&self) -> bool {
67 matches!(self, OwnedDataValue::Null)
68 }
69 #[inline]
70 pub fn is_bool(&self) -> bool {
71 matches!(self, OwnedDataValue::Bool(_))
72 }
73 #[inline]
74 pub fn is_number(&self) -> bool {
75 matches!(self, OwnedDataValue::Number(_))
76 }
77 #[inline]
78 pub fn is_i64(&self) -> bool {
79 matches!(self, OwnedDataValue::Number(NumberValue::Integer(_)))
80 }
81 #[inline]
82 pub fn is_f64(&self) -> bool {
83 matches!(self, OwnedDataValue::Number(NumberValue::Float(_)))
84 }
85 #[inline]
86 pub fn is_string(&self) -> bool {
87 matches!(self, OwnedDataValue::String(_))
88 }
89 #[inline]
90 pub fn is_array(&self) -> bool {
91 matches!(self, OwnedDataValue::Array(_))
92 }
93 #[inline]
94 pub fn is_object(&self) -> bool {
95 matches!(self, OwnedDataValue::Object(_))
96 }
97 #[cfg(feature = "datetime")]
98 #[inline]
99 pub fn is_datetime(&self) -> bool {
100 matches!(self, OwnedDataValue::DateTime(_))
101 }
102 #[cfg(feature = "datetime")]
103 #[inline]
104 pub fn is_duration(&self) -> bool {
105 matches!(self, OwnedDataValue::Duration(_))
106 }
107
108 #[inline]
111 pub fn as_bool(&self) -> Option<bool> {
112 match self {
113 OwnedDataValue::Bool(b) => Some(*b),
114 _ => None,
115 }
116 }
117 #[inline]
118 pub fn as_i64(&self) -> Option<i64> {
119 match self {
120 OwnedDataValue::Number(n) => n.as_i64(),
121 _ => None,
122 }
123 }
124 #[inline]
125 pub fn as_f64(&self) -> Option<f64> {
126 match self {
127 OwnedDataValue::Number(n) => Some(n.as_f64()),
128 _ => None,
129 }
130 }
131 #[inline]
132 pub fn as_number(&self) -> Option<&NumberValue> {
133 match self {
134 OwnedDataValue::Number(n) => Some(n),
135 _ => None,
136 }
137 }
138 #[inline]
139 pub fn as_str(&self) -> Option<&str> {
140 match self {
141 OwnedDataValue::String(s) => Some(s.as_str()),
142 _ => None,
143 }
144 }
145 #[inline]
146 pub fn as_array(&self) -> Option<&[OwnedDataValue]> {
147 match self {
148 OwnedDataValue::Array(items) => Some(items.as_slice()),
149 _ => None,
150 }
151 }
152 #[inline]
153 pub fn as_object(&self) -> Option<&[(String, OwnedDataValue)]> {
154 match self {
155 OwnedDataValue::Object(pairs) => Some(pairs.as_slice()),
156 _ => None,
157 }
158 }
159 #[cfg(feature = "datetime")]
160 #[inline]
161 pub fn as_datetime(&self) -> Option<&DataDateTime> {
162 match self {
163 OwnedDataValue::DateTime(d) => Some(d),
164 _ => None,
165 }
166 }
167 #[cfg(feature = "datetime")]
168 #[inline]
169 pub fn as_duration(&self) -> Option<&DataDuration> {
170 match self {
171 OwnedDataValue::Duration(d) => Some(d),
172 _ => None,
173 }
174 }
175
176 #[inline]
178 pub fn get<I: OwnedValueIndex>(&self, index: I) -> Option<&OwnedDataValue> {
179 I::index_into(&index, self)
180 }
181
182 #[inline]
183 pub fn len(&self) -> Option<usize> {
184 match self {
185 OwnedDataValue::Array(a) => Some(a.len()),
186 OwnedDataValue::Object(o) => Some(o.len()),
187 _ => None,
188 }
189 }
190
191 #[inline]
192 pub fn is_empty(&self) -> Option<bool> {
193 self.len().map(|n| n == 0)
194 }
195
196 #[inline]
199 pub fn members(&self) -> core::slice::Iter<'_, OwnedDataValue> {
200 match self {
201 OwnedDataValue::Array(items) => items.iter(),
202 _ => [].iter(),
203 }
204 }
205
206 #[inline]
209 pub fn entries(&self) -> OwnedEntriesIter<'_> {
210 match self {
211 OwnedDataValue::Object(pairs) => OwnedEntriesIter {
212 inner: pairs.iter(),
213 },
214 _ => OwnedEntriesIter { inner: [].iter() },
215 }
216 }
217
218 #[inline]
222 pub fn to_json_string(&self) -> String {
223 self.to_string()
224 }
225
226 pub fn to_arena<'a>(&self, arena: &'a Bump) -> DataValue<'a> {
235 match self {
236 OwnedDataValue::Null => DataValue::Null,
237 OwnedDataValue::Bool(b) => DataValue::Bool(*b),
238 OwnedDataValue::Number(n) => DataValue::Number(*n),
239 OwnedDataValue::String(s) => DataValue::String(arena.alloc_str(s)),
240 OwnedDataValue::Array(items) => {
241 let slice = arena.alloc_slice_fill_with(items.len(), |i| items[i].to_arena(arena));
242 DataValue::Array(slice)
243 }
244 OwnedDataValue::Object(pairs) => {
245 let slice = arena.alloc_slice_fill_with(pairs.len(), |i| {
246 let (k, v) = &pairs[i];
247 (arena.alloc_str(k) as &str, v.to_arena(arena))
248 });
249 DataValue::Object(slice)
250 }
251 #[cfg(feature = "datetime")]
252 OwnedDataValue::DateTime(d) => DataValue::DateTime(*d),
253 #[cfg(feature = "datetime")]
254 OwnedDataValue::Duration(d) => DataValue::Duration(*d),
255 }
256 }
257}
258
259impl<'a> DataValue<'a> {
260 pub fn to_owned(&self) -> OwnedDataValue {
263 match *self {
264 DataValue::Null => OwnedDataValue::Null,
265 DataValue::Bool(b) => OwnedDataValue::Bool(b),
266 DataValue::Number(n) => OwnedDataValue::Number(n),
267 DataValue::String(s) => OwnedDataValue::String(s.to_string()),
268 DataValue::Array(items) => {
269 OwnedDataValue::Array(items.iter().map(DataValue::to_owned).collect())
270 }
271 DataValue::Object(pairs) => OwnedDataValue::Object(
272 pairs
273 .iter()
274 .map(|(k, v)| ((*k).to_string(), v.to_owned()))
275 .collect(),
276 ),
277 #[cfg(feature = "datetime")]
278 DataValue::DateTime(d) => OwnedDataValue::DateTime(d),
279 #[cfg(feature = "datetime")]
280 DataValue::Duration(d) => OwnedDataValue::Duration(d),
281 }
282 }
283}
284
285pub struct OwnedEntriesIter<'v> {
288 inner: core::slice::Iter<'v, (String, OwnedDataValue)>,
289}
290
291impl<'v> Iterator for OwnedEntriesIter<'v> {
292 type Item = (&'v str, &'v OwnedDataValue);
293 #[inline]
294 fn next(&mut self) -> Option<Self::Item> {
295 self.inner.next().map(|(k, v)| (k.as_str(), v))
296 }
297 #[inline]
298 fn size_hint(&self) -> (usize, Option<usize>) {
299 self.inner.size_hint()
300 }
301}
302
303impl ExactSizeIterator for OwnedEntriesIter<'_> {}
304
305impl PartialEq for OwnedDataValue {
306 #[inline]
307 fn eq(&self, other: &Self) -> bool {
308 match (self, other) {
309 (OwnedDataValue::Null, OwnedDataValue::Null) => true,
310 (OwnedDataValue::Bool(a), OwnedDataValue::Bool(b)) => a == b,
311 (OwnedDataValue::Number(a), OwnedDataValue::Number(b)) => a == b,
312 (OwnedDataValue::String(a), OwnedDataValue::String(b)) => a == b,
313 (OwnedDataValue::Array(a), OwnedDataValue::Array(b)) => a == b,
314 (OwnedDataValue::Object(a), OwnedDataValue::Object(b)) => {
315 if a.len() != b.len() {
316 return false;
317 }
318 a.iter().all(|(k, v)| {
319 b.iter()
320 .find(|(bk, _)| bk == k)
321 .is_some_and(|(_, bv)| v == bv)
322 })
323 }
324 #[cfg(feature = "datetime")]
325 (OwnedDataValue::DateTime(a), OwnedDataValue::DateTime(b)) => a == b,
326 #[cfg(feature = "datetime")]
327 (OwnedDataValue::Duration(a), OwnedDataValue::Duration(b)) => a == b,
328 _ => false,
329 }
330 }
331}
332
333pub trait OwnedValueIndex: private::Sealed {
336 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue>;
337 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue;
338}
339
340mod private {
341 pub trait Sealed {}
342 impl Sealed for str {}
343 impl Sealed for String {}
344 impl Sealed for usize {}
345 impl<T: Sealed + ?Sized> Sealed for &T {}
346}
347
348impl OwnedValueIndex for str {
349 #[inline]
350 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue> {
351 match value {
352 OwnedDataValue::Object(pairs) => pairs.iter().find(|(k, _)| k == self).map(|(_, v)| v),
353 _ => None,
354 }
355 }
356 #[inline]
357 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue {
358 self.index_into(value).unwrap_or(&OWNED_NULL)
359 }
360}
361
362impl OwnedValueIndex for String {
363 #[inline]
364 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue> {
365 self.as_str().index_into(value)
366 }
367 #[inline]
368 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue {
369 self.as_str().index_into_or_null(value)
370 }
371}
372
373impl OwnedValueIndex for usize {
374 #[inline]
375 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue> {
376 match value {
377 OwnedDataValue::Array(items) => items.get(*self),
378 _ => None,
379 }
380 }
381 #[inline]
382 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue {
383 self.index_into(value).unwrap_or(&OWNED_NULL)
384 }
385}
386
387impl<T: OwnedValueIndex + ?Sized> OwnedValueIndex for &T {
388 #[inline]
389 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue> {
390 (**self).index_into(value)
391 }
392 #[inline]
393 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue {
394 (**self).index_into_or_null(value)
395 }
396}
397
398impl<I: OwnedValueIndex> Index<I> for OwnedDataValue {
399 type Output = OwnedDataValue;
400 #[inline]
401 fn index(&self, index: I) -> &OwnedDataValue {
402 index.index_into_or_null(self)
403 }
404}
405
406impl OwnedDataValue {
409 #[inline]
410 pub fn from_i64(i: i64) -> Self {
411 OwnedDataValue::Number(NumberValue::Integer(i))
412 }
413 #[inline]
414 pub fn from_f64(f: f64) -> Self {
415 OwnedDataValue::Number(NumberValue::from_f64(f))
416 }
417
418 pub fn array<I, V>(items: I) -> Self
430 where
431 I: IntoIterator<Item = V>,
432 V: Into<OwnedDataValue>,
433 {
434 OwnedDataValue::Array(items.into_iter().map(Into::into).collect())
435 }
436
437 pub fn object<I, K, V>(pairs: I) -> Self
447 where
448 I: IntoIterator<Item = (K, V)>,
449 K: Into<String>,
450 V: Into<OwnedDataValue>,
451 {
452 OwnedDataValue::Object(
453 pairs
454 .into_iter()
455 .map(|(k, v)| (k.into(), v.into()))
456 .collect(),
457 )
458 }
459}
460
461impl From<Vec<(String, OwnedDataValue)>> for OwnedDataValue {
462 #[inline]
463 fn from(pairs: Vec<(String, OwnedDataValue)>) -> Self {
464 OwnedDataValue::Object(pairs)
465 }
466}
467
468impl From<bool> for OwnedDataValue {
469 #[inline]
470 fn from(b: bool) -> Self {
471 OwnedDataValue::Bool(b)
472 }
473}
474
475macro_rules! from_int {
476 ($($t:ty),*) => {$(
477 impl From<$t> for OwnedDataValue {
478 #[inline]
479 fn from(v: $t) -> Self { OwnedDataValue::from_i64(v as i64) }
480 }
481 )*};
482}
483from_int!(i8, i16, i32, i64, u8, u16, u32);
484
485impl From<u64> for OwnedDataValue {
486 #[inline]
489 fn from(v: u64) -> Self {
490 if v <= i64::MAX as u64 {
491 OwnedDataValue::from_i64(v as i64)
492 } else {
493 OwnedDataValue::Number(NumberValue::Float(v as f64))
496 }
497 }
498}
499impl From<usize> for OwnedDataValue {
500 #[inline]
501 fn from(v: usize) -> Self {
502 OwnedDataValue::from(v as u64)
503 }
504}
505impl From<isize> for OwnedDataValue {
506 #[inline]
507 fn from(v: isize) -> Self {
508 OwnedDataValue::from_i64(v as i64)
509 }
510}
511
512impl From<f32> for OwnedDataValue {
513 #[inline]
514 fn from(v: f32) -> Self {
515 OwnedDataValue::from_f64(v as f64)
516 }
517}
518impl From<f64> for OwnedDataValue {
519 #[inline]
520 fn from(v: f64) -> Self {
521 OwnedDataValue::from_f64(v)
522 }
523}
524
525impl From<String> for OwnedDataValue {
526 #[inline]
527 fn from(s: String) -> Self {
528 OwnedDataValue::String(s)
529 }
530}
531impl From<&str> for OwnedDataValue {
532 #[inline]
533 fn from(s: &str) -> Self {
534 OwnedDataValue::String(s.to_string())
535 }
536}
537impl From<&String> for OwnedDataValue {
538 #[inline]
539 fn from(s: &String) -> Self {
540 OwnedDataValue::String(s.clone())
541 }
542}
543impl From<std::borrow::Cow<'_, str>> for OwnedDataValue {
544 #[inline]
545 fn from(s: std::borrow::Cow<'_, str>) -> Self {
546 OwnedDataValue::String(s.into_owned())
547 }
548}
549
550impl From<()> for OwnedDataValue {
551 #[inline]
552 fn from(_: ()) -> Self {
553 OwnedDataValue::Null
554 }
555}
556
557impl<T: Into<OwnedDataValue>> From<Option<T>> for OwnedDataValue {
558 #[inline]
559 fn from(opt: Option<T>) -> Self {
560 match opt {
561 Some(v) => v.into(),
562 None => OwnedDataValue::Null,
563 }
564 }
565}
566
567impl<T: Into<OwnedDataValue>> From<Vec<T>> for OwnedDataValue {
568 #[inline]
569 fn from(v: Vec<T>) -> Self {
570 OwnedDataValue::Array(v.into_iter().map(Into::into).collect())
571 }
572}
573
574impl<T: Into<OwnedDataValue> + Clone> From<&[T]> for OwnedDataValue {
575 #[inline]
576 fn from(v: &[T]) -> Self {
577 OwnedDataValue::Array(v.iter().cloned().map(Into::into).collect())
578 }
579}
580
581impl<T: Into<OwnedDataValue>, const N: usize> From<[T; N]> for OwnedDataValue {
582 #[inline]
583 fn from(v: [T; N]) -> Self {
584 OwnedDataValue::Array(v.into_iter().map(Into::into).collect())
585 }
586}
587
588impl<K: Into<String>, V: Into<OwnedDataValue>> From<std::collections::HashMap<K, V>>
589 for OwnedDataValue
590{
591 #[inline]
595 fn from(m: std::collections::HashMap<K, V>) -> Self {
596 OwnedDataValue::Object(m.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
597 }
598}
599
600impl<K: Into<String>, V: Into<OwnedDataValue>> From<std::collections::BTreeMap<K, V>>
601 for OwnedDataValue
602{
603 #[inline]
604 fn from(m: std::collections::BTreeMap<K, V>) -> Self {
605 OwnedDataValue::Object(m.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
606 }
607}
608
609#[cfg(test)]
610mod tests {
611 use super::*;
612
613 #[test]
614 fn parse_round_trip_via_owned() {
615 let v = OwnedDataValue::from_json(r#"{"a":1,"b":[true,null,"x"]}"#).unwrap();
616 assert_eq!(v["a"].as_i64(), Some(1));
617 assert_eq!(v["b"][0].as_bool(), Some(true));
618 assert!(v["b"][1].is_null());
619 assert_eq!(v["b"][2].as_str(), Some("x"));
620 }
621
622 #[test]
623 fn arena_to_owned_to_arena_round_trip() {
624 let arena = Bump::new();
625 let original =
626 DataValue::from_str(r#"{"x":42,"y":[1,2,3],"z":{"k":true}}"#, &arena).unwrap();
627 let owned = original.to_owned();
628
629 drop(arena);
631 assert_eq!(owned["x"].as_i64(), Some(42));
632 assert_eq!(owned["y"][1].as_i64(), Some(2));
633 assert_eq!(owned["z"]["k"].as_bool(), Some(true));
634
635 let arena2 = Bump::new();
637 let back = owned.to_arena(&arena2);
638 assert_eq!(back["x"].as_i64(), Some(42));
639 assert_eq!(back["y"][1].as_i64(), Some(2));
640 assert_eq!(back["z"]["k"].as_bool(), Some(true));
641
642 assert_eq!(back.to_owned(), owned);
644 }
645
646 #[test]
647 fn missing_index_returns_null() {
648 let v = OwnedDataValue::from_json(r#"{"a":1}"#).unwrap();
649 assert!(v["missing"].is_null());
650 assert!(v["a"][99].is_null());
651 }
652
653 #[test]
654 fn equality_object_order_insensitive() {
655 let a = OwnedDataValue::Object(vec![
656 ("x".to_string(), OwnedDataValue::from_i64(1)),
657 ("y".to_string(), OwnedDataValue::from_i64(2)),
658 ]);
659 let b = OwnedDataValue::Object(vec![
660 ("y".to_string(), OwnedDataValue::from_i64(2)),
661 ("x".to_string(), OwnedDataValue::from_i64(1)),
662 ]);
663 assert_eq!(a, b);
664 }
665
666 #[cfg(feature = "datetime")]
667 #[test]
668 fn datetime_variant_round_trips_through_owned() {
669 use crate::datetime::DataDateTime;
670 let arena = Bump::new();
671 let dt = DataDateTime::parse("2024-01-15T12:30:45Z").unwrap();
672 let bv = DataValue::DateTime(dt);
673 let owned = bv.to_owned();
674 assert!(owned.is_datetime());
675 assert_eq!(
676 owned.as_datetime().unwrap().to_iso_string(),
677 "2024-01-15T12:30:45Z"
678 );
679 let back = owned.to_arena(&arena);
680 assert_eq!(back, bv);
681 }
682}