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;
20#[cfg(feature = "tensor")]
21use crate::tensor::OwnedDataTensor;
22use crate::value::DataValue;
23#[cfg(feature = "tensor")]
24use std::sync::Arc;
25
26#[derive(Debug, Clone, Default)]
29pub enum OwnedDataValue {
30 #[default]
31 Null,
32 Bool(bool),
33 Number(NumberValue),
34 String(String),
35 Array(Vec<OwnedDataValue>),
36 Object(Vec<(String, OwnedDataValue)>),
37 #[cfg(feature = "datetime")]
38 DateTime(DataDateTime),
39 #[cfg(feature = "datetime")]
40 Duration(DataDuration),
41 #[cfg(feature = "tensor")]
45 Tensor(Arc<OwnedDataTensor>),
46}
47
48static OWNED_NULL: OwnedDataValue = OwnedDataValue::Null;
49
50#[cfg(target_pointer_width = "64")]
53const _: () = assert!(core::mem::size_of::<OwnedDataValue>() == 32);
54
55impl core::str::FromStr for OwnedDataValue {
56 type Err = ParseError;
57 fn from_str(s: &str) -> Result<Self, Self::Err> {
58 let arena = Bump::new();
59 let v = DataValue::from_str(s, &arena)?;
60 Ok(v.to_owned())
61 }
62}
63
64impl OwnedDataValue {
65 pub fn from_json(input: &str) -> Result<Self, ParseError> {
74 input.parse()
75 }
76
77 #[inline]
80 pub fn is_null(&self) -> bool {
81 matches!(self, OwnedDataValue::Null)
82 }
83 #[inline]
84 pub fn is_bool(&self) -> bool {
85 matches!(self, OwnedDataValue::Bool(_))
86 }
87 #[inline]
88 pub fn is_number(&self) -> bool {
89 matches!(self, OwnedDataValue::Number(_))
90 }
91 #[inline]
92 pub fn is_i64(&self) -> bool {
93 matches!(self, OwnedDataValue::Number(NumberValue::Integer(_)))
94 }
95 #[inline]
96 pub fn is_f64(&self) -> bool {
97 matches!(self, OwnedDataValue::Number(NumberValue::Float(_)))
98 }
99 #[inline]
100 pub fn is_string(&self) -> bool {
101 matches!(self, OwnedDataValue::String(_))
102 }
103 #[inline]
104 pub fn is_array(&self) -> bool {
105 matches!(self, OwnedDataValue::Array(_))
106 }
107 #[inline]
108 pub fn is_object(&self) -> bool {
109 matches!(self, OwnedDataValue::Object(_))
110 }
111 #[cfg(feature = "datetime")]
112 #[inline]
113 pub fn is_datetime(&self) -> bool {
114 matches!(self, OwnedDataValue::DateTime(_))
115 }
116 #[cfg(feature = "datetime")]
117 #[inline]
118 pub fn is_duration(&self) -> bool {
119 matches!(self, OwnedDataValue::Duration(_))
120 }
121 #[cfg(feature = "tensor")]
122 #[inline]
123 pub fn is_tensor(&self) -> bool {
124 matches!(self, OwnedDataValue::Tensor(_))
125 }
126
127 #[inline]
130 pub fn as_bool(&self) -> Option<bool> {
131 match self {
132 OwnedDataValue::Bool(b) => Some(*b),
133 _ => None,
134 }
135 }
136 #[inline]
137 pub fn as_i64(&self) -> Option<i64> {
138 match self {
139 OwnedDataValue::Number(n) => n.as_i64(),
140 _ => None,
141 }
142 }
143 #[inline]
144 pub fn as_f64(&self) -> Option<f64> {
145 match self {
146 OwnedDataValue::Number(n) => Some(n.as_f64()),
147 _ => None,
148 }
149 }
150 #[inline]
151 pub fn as_number(&self) -> Option<&NumberValue> {
152 match self {
153 OwnedDataValue::Number(n) => Some(n),
154 _ => None,
155 }
156 }
157 #[inline]
158 pub fn as_str(&self) -> Option<&str> {
159 match self {
160 OwnedDataValue::String(s) => Some(s.as_str()),
161 _ => None,
162 }
163 }
164 #[inline]
165 pub fn as_array(&self) -> Option<&[OwnedDataValue]> {
166 match self {
167 OwnedDataValue::Array(items) => Some(items.as_slice()),
168 _ => None,
169 }
170 }
171 #[inline]
172 pub fn as_object(&self) -> Option<&[(String, OwnedDataValue)]> {
173 match self {
174 OwnedDataValue::Object(pairs) => Some(pairs.as_slice()),
175 _ => None,
176 }
177 }
178 #[cfg(feature = "datetime")]
179 #[inline]
180 pub fn as_datetime(&self) -> Option<&DataDateTime> {
181 match self {
182 OwnedDataValue::DateTime(d) => Some(d),
183 _ => None,
184 }
185 }
186 #[cfg(feature = "datetime")]
187 #[inline]
188 pub fn as_duration(&self) -> Option<&DataDuration> {
189 match self {
190 OwnedDataValue::Duration(d) => Some(d),
191 _ => None,
192 }
193 }
194 #[cfg(feature = "tensor")]
195 #[inline]
196 pub fn as_tensor(&self) -> Option<&OwnedDataTensor> {
197 match self {
198 OwnedDataValue::Tensor(t) => Some(t),
199 _ => None,
200 }
201 }
202
203 #[cfg(feature = "tensor")]
206 #[inline]
207 pub fn tensor(t: OwnedDataTensor) -> Self {
208 OwnedDataValue::Tensor(Arc::new(t))
209 }
210
211 #[inline]
213 pub fn get<I: OwnedValueIndex>(&self, index: I) -> Option<&OwnedDataValue> {
214 I::index_into(&index, self)
215 }
216
217 #[inline]
218 pub fn len(&self) -> Option<usize> {
219 match self {
220 OwnedDataValue::Array(a) => Some(a.len()),
221 OwnedDataValue::Object(o) => Some(o.len()),
222 _ => None,
223 }
224 }
225
226 #[inline]
227 pub fn is_empty(&self) -> Option<bool> {
228 self.len().map(|n| n == 0)
229 }
230
231 #[inline]
234 pub fn members(&self) -> core::slice::Iter<'_, OwnedDataValue> {
235 match self {
236 OwnedDataValue::Array(items) => items.iter(),
237 _ => [].iter(),
238 }
239 }
240
241 #[inline]
244 pub fn entries(&self) -> OwnedEntriesIter<'_> {
245 match self {
246 OwnedDataValue::Object(pairs) => OwnedEntriesIter {
247 inner: pairs.iter(),
248 },
249 _ => OwnedEntriesIter { inner: [].iter() },
250 }
251 }
252
253 #[inline]
257 pub fn to_json_string(&self) -> String {
258 self.to_string()
259 }
260
261 pub fn to_arena<'a>(&self, arena: &'a Bump) -> DataValue<'a> {
270 match self {
271 OwnedDataValue::Null => DataValue::Null,
272 OwnedDataValue::Bool(b) => DataValue::Bool(*b),
273 OwnedDataValue::Number(n) => DataValue::Number(*n),
274 OwnedDataValue::String(s) => DataValue::String(arena.alloc_str(s)),
275 OwnedDataValue::Array(items) => {
276 let slice = arena.alloc_slice_fill_with(items.len(), |i| items[i].to_arena(arena));
277 DataValue::Array(slice)
278 }
279 OwnedDataValue::Object(pairs) => {
280 let slice = arena.alloc_slice_fill_with(pairs.len(), |i| {
281 let (k, v) = &pairs[i];
282 (arena.alloc_str(k) as &str, v.to_arena(arena))
283 });
284 DataValue::Object(slice)
285 }
286 #[cfg(feature = "datetime")]
287 OwnedDataValue::DateTime(d) => DataValue::DateTime(*d),
288 #[cfg(feature = "datetime")]
289 OwnedDataValue::Duration(d) => DataValue::Duration(*d),
290 #[cfg(feature = "tensor")]
291 OwnedDataValue::Tensor(t) => DataValue::tensor_in(t.to_arena(arena), arena),
292 }
293 }
294}
295
296impl<'a> DataValue<'a> {
297 pub fn to_owned(&self) -> OwnedDataValue {
300 match *self {
301 DataValue::Null => OwnedDataValue::Null,
302 DataValue::Bool(b) => OwnedDataValue::Bool(b),
303 DataValue::Number(n) => OwnedDataValue::Number(n),
304 DataValue::String(s) => OwnedDataValue::String(s.to_string()),
305 DataValue::Array(items) => {
306 OwnedDataValue::Array(items.iter().map(DataValue::to_owned).collect())
307 }
308 DataValue::Object(pairs) => OwnedDataValue::Object(
309 pairs
310 .iter()
311 .map(|(k, v)| ((*k).to_string(), v.to_owned()))
312 .collect(),
313 ),
314 #[cfg(feature = "datetime")]
315 DataValue::DateTime(d) => OwnedDataValue::DateTime(d),
316 #[cfg(feature = "datetime")]
317 DataValue::Duration(d) => OwnedDataValue::Duration(d),
318 #[cfg(feature = "tensor")]
319 DataValue::Tensor(t) => OwnedDataValue::tensor(t.to_owned()),
320 }
321 }
322}
323
324pub struct OwnedEntriesIter<'v> {
327 inner: core::slice::Iter<'v, (String, OwnedDataValue)>,
328}
329
330impl<'v> Iterator for OwnedEntriesIter<'v> {
331 type Item = (&'v str, &'v OwnedDataValue);
332 #[inline]
333 fn next(&mut self) -> Option<Self::Item> {
334 self.inner.next().map(|(k, v)| (k.as_str(), v))
335 }
336 #[inline]
337 fn size_hint(&self) -> (usize, Option<usize>) {
338 self.inner.size_hint()
339 }
340}
341
342impl ExactSizeIterator for OwnedEntriesIter<'_> {}
343
344impl PartialEq for OwnedDataValue {
345 #[inline]
346 fn eq(&self, other: &Self) -> bool {
347 match (self, other) {
348 (OwnedDataValue::Null, OwnedDataValue::Null) => true,
349 (OwnedDataValue::Bool(a), OwnedDataValue::Bool(b)) => a == b,
350 (OwnedDataValue::Number(a), OwnedDataValue::Number(b)) => a == b,
351 (OwnedDataValue::String(a), OwnedDataValue::String(b)) => a == b,
352 (OwnedDataValue::Array(a), OwnedDataValue::Array(b)) => a == b,
353 (OwnedDataValue::Object(a), OwnedDataValue::Object(b)) => {
354 if a.len() != b.len() {
355 return false;
356 }
357 a.iter().all(|(k, v)| {
358 b.iter()
359 .find(|(bk, _)| bk == k)
360 .is_some_and(|(_, bv)| v == bv)
361 })
362 }
363 #[cfg(feature = "datetime")]
364 (OwnedDataValue::DateTime(a), OwnedDataValue::DateTime(b)) => a == b,
365 #[cfg(feature = "datetime")]
366 (OwnedDataValue::Duration(a), OwnedDataValue::Duration(b)) => a == b,
367 #[cfg(feature = "tensor")]
368 (OwnedDataValue::Tensor(a), OwnedDataValue::Tensor(b)) => a == b,
369 _ => false,
370 }
371 }
372}
373
374pub trait OwnedValueIndex: private::Sealed {
377 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue>;
378 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue;
379}
380
381mod private {
382 pub trait Sealed {}
383 impl Sealed for str {}
384 impl Sealed for String {}
385 impl Sealed for usize {}
386 impl<T: Sealed + ?Sized> Sealed for &T {}
387}
388
389impl OwnedValueIndex for str {
390 #[inline]
391 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue> {
392 match value {
393 OwnedDataValue::Object(pairs) => pairs.iter().find(|(k, _)| k == self).map(|(_, v)| v),
394 _ => None,
395 }
396 }
397 #[inline]
398 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue {
399 self.index_into(value).unwrap_or(&OWNED_NULL)
400 }
401}
402
403impl OwnedValueIndex for String {
404 #[inline]
405 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue> {
406 self.as_str().index_into(value)
407 }
408 #[inline]
409 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue {
410 self.as_str().index_into_or_null(value)
411 }
412}
413
414impl OwnedValueIndex for usize {
415 #[inline]
416 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue> {
417 match value {
418 OwnedDataValue::Array(items) => items.get(*self),
419 _ => None,
420 }
421 }
422 #[inline]
423 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue {
424 self.index_into(value).unwrap_or(&OWNED_NULL)
425 }
426}
427
428impl<T: OwnedValueIndex + ?Sized> OwnedValueIndex for &T {
429 #[inline]
430 fn index_into<'v>(&self, value: &'v OwnedDataValue) -> Option<&'v OwnedDataValue> {
431 (**self).index_into(value)
432 }
433 #[inline]
434 fn index_into_or_null<'v>(&self, value: &'v OwnedDataValue) -> &'v OwnedDataValue {
435 (**self).index_into_or_null(value)
436 }
437}
438
439impl<I: OwnedValueIndex> Index<I> for OwnedDataValue {
440 type Output = OwnedDataValue;
441 #[inline]
442 fn index(&self, index: I) -> &OwnedDataValue {
443 index.index_into_or_null(self)
444 }
445}
446
447impl OwnedDataValue {
450 #[inline]
451 pub fn from_i64(i: i64) -> Self {
452 OwnedDataValue::Number(NumberValue::Integer(i))
453 }
454 #[inline]
455 pub fn from_f64(f: f64) -> Self {
456 OwnedDataValue::Number(NumberValue::from_f64(f))
457 }
458
459 pub fn array<I, V>(items: I) -> Self
471 where
472 I: IntoIterator<Item = V>,
473 V: Into<OwnedDataValue>,
474 {
475 OwnedDataValue::Array(items.into_iter().map(Into::into).collect())
476 }
477
478 pub fn object<I, K, V>(pairs: I) -> Self
488 where
489 I: IntoIterator<Item = (K, V)>,
490 K: Into<String>,
491 V: Into<OwnedDataValue>,
492 {
493 OwnedDataValue::Object(
494 pairs
495 .into_iter()
496 .map(|(k, v)| (k.into(), v.into()))
497 .collect(),
498 )
499 }
500}
501
502impl From<Vec<(String, OwnedDataValue)>> for OwnedDataValue {
503 #[inline]
504 fn from(pairs: Vec<(String, OwnedDataValue)>) -> Self {
505 OwnedDataValue::Object(pairs)
506 }
507}
508
509#[cfg(feature = "tensor")]
510impl From<OwnedDataTensor> for OwnedDataValue {
511 #[inline]
512 fn from(t: OwnedDataTensor) -> Self {
513 OwnedDataValue::tensor(t)
514 }
515}
516
517#[cfg(feature = "tensor")]
518impl From<Arc<OwnedDataTensor>> for OwnedDataValue {
519 #[inline]
521 fn from(t: Arc<OwnedDataTensor>) -> Self {
522 OwnedDataValue::Tensor(t)
523 }
524}
525
526impl From<bool> for OwnedDataValue {
527 #[inline]
528 fn from(b: bool) -> Self {
529 OwnedDataValue::Bool(b)
530 }
531}
532
533macro_rules! from_int {
534 ($($t:ty),*) => {$(
535 impl From<$t> for OwnedDataValue {
536 #[inline]
537 fn from(v: $t) -> Self { OwnedDataValue::from_i64(v as i64) }
538 }
539 )*};
540}
541from_int!(i8, i16, i32, i64, u8, u16, u32);
542
543impl From<u64> for OwnedDataValue {
544 #[inline]
547 fn from(v: u64) -> Self {
548 OwnedDataValue::Number(NumberValue::from_u64(v))
549 }
550}
551impl From<usize> for OwnedDataValue {
552 #[inline]
553 fn from(v: usize) -> Self {
554 OwnedDataValue::from(v as u64)
555 }
556}
557impl From<isize> for OwnedDataValue {
558 #[inline]
559 fn from(v: isize) -> Self {
560 OwnedDataValue::from_i64(v as i64)
561 }
562}
563
564impl From<f32> for OwnedDataValue {
565 #[inline]
566 fn from(v: f32) -> Self {
567 OwnedDataValue::from_f64(v as f64)
568 }
569}
570impl From<f64> for OwnedDataValue {
571 #[inline]
572 fn from(v: f64) -> Self {
573 OwnedDataValue::from_f64(v)
574 }
575}
576
577impl From<String> for OwnedDataValue {
578 #[inline]
579 fn from(s: String) -> Self {
580 OwnedDataValue::String(s)
581 }
582}
583impl From<&str> for OwnedDataValue {
584 #[inline]
585 fn from(s: &str) -> Self {
586 OwnedDataValue::String(s.to_string())
587 }
588}
589impl From<&String> for OwnedDataValue {
590 #[inline]
591 fn from(s: &String) -> Self {
592 OwnedDataValue::String(s.clone())
593 }
594}
595impl From<std::borrow::Cow<'_, str>> for OwnedDataValue {
596 #[inline]
597 fn from(s: std::borrow::Cow<'_, str>) -> Self {
598 OwnedDataValue::String(s.into_owned())
599 }
600}
601
602impl From<()> for OwnedDataValue {
603 #[inline]
604 fn from(_: ()) -> Self {
605 OwnedDataValue::Null
606 }
607}
608
609impl<T: Into<OwnedDataValue>> From<Option<T>> for OwnedDataValue {
610 #[inline]
611 fn from(opt: Option<T>) -> Self {
612 match opt {
613 Some(v) => v.into(),
614 None => OwnedDataValue::Null,
615 }
616 }
617}
618
619impl<T: Into<OwnedDataValue>> From<Vec<T>> for OwnedDataValue {
620 #[inline]
621 fn from(v: Vec<T>) -> Self {
622 OwnedDataValue::Array(v.into_iter().map(Into::into).collect())
623 }
624}
625
626impl<T: Into<OwnedDataValue> + Clone> From<&[T]> for OwnedDataValue {
627 #[inline]
628 fn from(v: &[T]) -> Self {
629 OwnedDataValue::Array(v.iter().cloned().map(Into::into).collect())
630 }
631}
632
633impl<T: Into<OwnedDataValue>, const N: usize> From<[T; N]> for OwnedDataValue {
634 #[inline]
635 fn from(v: [T; N]) -> Self {
636 OwnedDataValue::Array(v.into_iter().map(Into::into).collect())
637 }
638}
639
640impl<K: Into<String>, V: Into<OwnedDataValue>> From<std::collections::HashMap<K, V>>
641 for OwnedDataValue
642{
643 #[inline]
647 fn from(m: std::collections::HashMap<K, V>) -> Self {
648 OwnedDataValue::Object(m.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
649 }
650}
651
652impl<K: Into<String>, V: Into<OwnedDataValue>> From<std::collections::BTreeMap<K, V>>
653 for OwnedDataValue
654{
655 #[inline]
656 fn from(m: std::collections::BTreeMap<K, V>) -> Self {
657 OwnedDataValue::Object(m.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
658 }
659}
660
661#[cfg(test)]
662mod tests {
663 use super::*;
664
665 #[test]
666 fn parse_round_trip_via_owned() {
667 let v = OwnedDataValue::from_json(r#"{"a":1,"b":[true,null,"x"]}"#).unwrap();
668 assert_eq!(v["a"].as_i64(), Some(1));
669 assert_eq!(v["b"][0].as_bool(), Some(true));
670 assert!(v["b"][1].is_null());
671 assert_eq!(v["b"][2].as_str(), Some("x"));
672 }
673
674 #[test]
675 fn arena_to_owned_to_arena_round_trip() {
676 let arena = Bump::new();
677 let original =
678 DataValue::from_str(r#"{"x":42,"y":[1,2,3],"z":{"k":true}}"#, &arena).unwrap();
679 let owned = original.to_owned();
680
681 drop(arena);
683 assert_eq!(owned["x"].as_i64(), Some(42));
684 assert_eq!(owned["y"][1].as_i64(), Some(2));
685 assert_eq!(owned["z"]["k"].as_bool(), Some(true));
686
687 let arena2 = Bump::new();
689 let back = owned.to_arena(&arena2);
690 assert_eq!(back["x"].as_i64(), Some(42));
691 assert_eq!(back["y"][1].as_i64(), Some(2));
692 assert_eq!(back["z"]["k"].as_bool(), Some(true));
693
694 assert_eq!(back.to_owned(), owned);
696 }
697
698 #[test]
699 fn missing_index_returns_null() {
700 let v = OwnedDataValue::from_json(r#"{"a":1}"#).unwrap();
701 assert!(v["missing"].is_null());
702 assert!(v["a"][99].is_null());
703 }
704
705 #[test]
706 fn equality_object_order_insensitive() {
707 let a = OwnedDataValue::Object(vec![
708 ("x".to_string(), OwnedDataValue::from_i64(1)),
709 ("y".to_string(), OwnedDataValue::from_i64(2)),
710 ]);
711 let b = OwnedDataValue::Object(vec![
712 ("y".to_string(), OwnedDataValue::from_i64(2)),
713 ("x".to_string(), OwnedDataValue::from_i64(1)),
714 ]);
715 assert_eq!(a, b);
716 }
717
718 #[cfg(feature = "datetime")]
719 #[test]
720 fn datetime_variant_round_trips_through_owned() {
721 use crate::datetime::DataDateTime;
722 let arena = Bump::new();
723 let dt = DataDateTime::parse("2024-01-15T12:30:45Z").unwrap();
724 let bv = DataValue::DateTime(dt);
725 let owned = bv.to_owned();
726 assert!(owned.is_datetime());
727 assert_eq!(
728 owned.as_datetime().unwrap().to_iso_string(),
729 "2024-01-15T12:30:45Z"
730 );
731 let back = owned.to_arena(&arena);
732 assert_eq!(back, bv);
733 }
734
735 #[cfg(feature = "tensor")]
736 #[test]
737 fn tensor_variant_round_trips_and_shares_on_clone() {
738 use crate::tensor::{DataTensor, OwnedDataTensor};
739 let arena = Bump::new();
740 let t = DataTensor::from_slice_in(&[3], &[1i64, 2, 3], &arena).unwrap();
741 let bv = DataValue::tensor_in(t, &arena);
742 let owned = bv.to_owned();
743 assert!(owned.is_tensor());
744 assert_eq!(
745 owned.as_tensor().unwrap().as_slice::<i64>(),
746 Some(&[1i64, 2, 3][..])
747 );
748 assert!(owned.as_array().is_none());
749 assert!(owned["x"].is_null());
750 assert_eq!(owned.len(), None);
751 drop(arena);
752
753 let cloned = owned.clone();
754 match (&owned, &cloned) {
755 (OwnedDataValue::Tensor(a), OwnedDataValue::Tensor(b)) => {
756 assert!(Arc::ptr_eq(a, b), "clone shares the buffer");
757 }
758 _ => unreachable!(),
759 }
760 assert_eq!(owned, cloned);
761
762 let arena2 = Bump::new();
763 let back = owned.to_arena(&arena2);
764 assert_eq!(back.to_owned(), owned);
765 assert_eq!(back.as_tensor().unwrap().shape(), &[3]);
766
767 let direct = OwnedDataTensor::from_slice([3], &[1i64, 2, 3]).unwrap();
768 let v = crate::owned_json!({"t": direct, "n": 1});
769 assert!(v["t"].is_tensor());
770 assert_eq!(v["t"], owned);
771 }
772}