1use std::cmp::Ordering;
2use std::collections::{BTreeMap, HashMap};
3use std::convert::TryFrom;
4use std::fmt::{self, Debug, Formatter};
5use std::hash::Hash;
6use std::hint::unreachable_unchecked;
7use std::mem;
8use std::ops::{Deref, Index, IndexMut};
9use std::ptr::NonNull;
10
11#[cfg(feature = "indexmap")]
12use indexmap::IndexMap;
13
14use super::array::IArray;
15use super::number::INumber;
16use super::object::IObject;
17use super::string::IString;
18
19#[repr(transparent)]
61#[derive(size_of::SizeOf)]
62pub struct IValue {
63 ptr: NonNull<u8>,
64}
65
66impl Ord for IValue {
67 fn cmp(&self, other: &Self) -> Ordering {
68 self.partial_cmp(other).unwrap_or(Ordering::Equal)
69 }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
75pub enum Destructured {
76 Null,
78 Bool(bool),
80 Number(INumber),
82 String(IString),
84 Array(IArray),
86 Object(IObject),
88}
89
90impl Destructured {
91 #[must_use]
93 pub fn as_ref(&self) -> DestructuredRef {
94 use DestructuredRef::{Array, Bool, Null, Number, Object, String};
95 match self {
96 Self::Null => Null,
97 Self::Bool(b) => Bool(*b),
98 Self::Number(v) => Number(v),
99 Self::String(v) => String(v),
100 Self::Array(v) => Array(v),
101 Self::Object(v) => Object(v),
102 }
103 }
104}
105
106#[derive(Debug, Copy, Clone, PartialEq, Eq)]
109pub enum DestructuredRef<'a> {
110 Null,
112 Bool(bool),
116 Number(&'a INumber),
118 String(&'a IString),
120 Array(&'a IArray),
122 Object(&'a IObject),
124}
125
126#[derive(Debug)]
129pub enum DestructuredMut<'a> {
130 Null,
132 Bool(BoolMut<'a>),
137 Number(&'a mut INumber),
139 String(&'a mut IString),
141 Array(&'a mut IArray),
143 Object(&'a mut IObject),
145}
146
147#[derive(Debug)]
149pub struct BoolMut<'a>(&'a mut IValue);
150
151impl<'a> BoolMut<'a> {
152 pub fn set(&mut self, value: bool) {
155 *self.0 = value.into();
156 }
157 #[must_use]
160 pub fn get(&self) -> bool {
161 self.0.is_true()
162 }
163}
164
165impl<'a> Deref for BoolMut<'a> {
166 type Target = bool;
167 fn deref(&self) -> &bool {
168 if self.get() {
169 &true
170 } else {
171 &false
172 }
173 }
174}
175
176pub(crate) const ALIGNMENT: usize = 4;
177
178#[repr(usize)]
179#[derive(Copy, Clone, Debug, PartialEq, Eq)]
180pub(crate) enum TypeTag {
181 Number = 0,
182 StringOrNull = 1,
183 ArrayOrFalse = 2,
184 ObjectOrTrue = 3,
185}
186
187impl From<usize> for TypeTag {
188 fn from(other: usize) -> Self {
189 unsafe { mem::transmute(other % ALIGNMENT) }
191 }
192}
193
194#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
196pub enum ValueType {
197 Null,
200 Bool,
202
203 Number,
206 String,
208 Array,
210 Object,
212}
213
214unsafe impl Send for IValue {}
215unsafe impl Sync for IValue {}
216
217impl IValue {
218 const unsafe fn new_inline(tag: TypeTag) -> Self {
220 Self {
221 ptr: NonNull::new_unchecked(tag as usize as *mut u8),
222 }
223 }
224 pub(crate) unsafe fn new_ptr(p: *mut u8, tag: TypeTag) -> Self {
226 Self {
227 ptr: NonNull::new_unchecked(p.add(tag as usize)),
228 }
229 }
230 pub(crate) unsafe fn new_ref<T>(r: &T, tag: TypeTag) -> Self {
232 Self::new_ptr(r as *const _ as *mut u8, tag)
233 }
234
235 pub const NULL: Self = unsafe { Self::new_inline(TypeTag::StringOrNull) };
237 pub const FALSE: Self = unsafe { Self::new_inline(TypeTag::ArrayOrFalse) };
239 pub const TRUE: Self = unsafe { Self::new_inline(TypeTag::ObjectOrTrue) };
241
242 pub(crate) fn ptr_usize(&self) -> usize {
243 self.ptr.as_ptr() as usize
244 }
245 pub(crate) unsafe fn ptr(&self) -> *mut u8 {
247 self.ptr
248 .as_ptr()
249 .wrapping_offset(-((self.ptr_usize() % ALIGNMENT) as isize))
250 }
251 pub(crate) unsafe fn set_ptr(&mut self, ptr: *mut u8) {
253 let tag = self.type_tag();
254 self.ptr = NonNull::new_unchecked(ptr.add(tag as usize));
255 }
256 pub(crate) unsafe fn set_ref<T>(&mut self, r: &T) {
258 self.set_ptr(r as *const T as *mut u8);
259 }
260 pub(crate) unsafe fn raw_copy(&self) -> Self {
261 Self { ptr: self.ptr }
262 }
263 pub(crate) fn raw_eq(&self, other: &Self) -> bool {
264 self.ptr == other.ptr
265 }
266 pub(crate) fn raw_hash<H: std::hash::Hasher>(&self, state: &mut H) {
267 self.ptr.hash(state);
268 }
269 fn is_ptr(&self) -> bool {
270 self.ptr_usize() >= ALIGNMENT
271 }
272 fn type_tag(&self) -> TypeTag {
273 self.ptr_usize().into()
274 }
275
276 #[must_use]
278 pub fn type_(&self) -> ValueType {
279 match (self.type_tag(), self.is_ptr()) {
280 (TypeTag::Number, true) => ValueType::Number,
282 (TypeTag::StringOrNull, true) => ValueType::String,
283 (TypeTag::ArrayOrFalse, true) => ValueType::Array,
284 (TypeTag::ObjectOrTrue, true) => ValueType::Object,
285
286 (TypeTag::StringOrNull, false) => ValueType::Null,
288 (TypeTag::ArrayOrFalse, false) | (TypeTag::ObjectOrTrue, false) => ValueType::Bool,
289
290 _ => unsafe { unreachable_unchecked() },
292 }
293 }
294
295 #[must_use]
297 pub fn destructure(self) -> Destructured {
298 match self.type_() {
299 ValueType::Null => Destructured::Null,
300 ValueType::Bool => Destructured::Bool(self.is_true()),
301 ValueType::Number => Destructured::Number(INumber(self)),
302 ValueType::String => Destructured::String(IString(self)),
303 ValueType::Array => Destructured::Array(IArray(self)),
304 ValueType::Object => Destructured::Object(IObject(self)),
305 }
306 }
307
308 #[must_use]
310 pub fn destructure_ref(&self) -> DestructuredRef {
311 unsafe {
313 match self.type_() {
314 ValueType::Null => DestructuredRef::Null,
315 ValueType::Bool => DestructuredRef::Bool(self.is_true()),
316 ValueType::Number => DestructuredRef::Number(self.as_number_unchecked()),
317 ValueType::String => DestructuredRef::String(self.as_string_unchecked()),
318 ValueType::Array => DestructuredRef::Array(self.as_array_unchecked()),
319 ValueType::Object => DestructuredRef::Object(self.as_object_unchecked()),
320 }
321 }
322 }
323
324 pub fn destructure_mut(&mut self) -> DestructuredMut {
326 unsafe {
328 match self.type_() {
329 ValueType::Null => DestructuredMut::Null,
330 ValueType::Bool => DestructuredMut::Bool(BoolMut(self)),
331 ValueType::Number => DestructuredMut::Number(self.as_number_unchecked_mut()),
332 ValueType::String => DestructuredMut::String(self.as_string_unchecked_mut()),
333 ValueType::Array => DestructuredMut::Array(self.as_array_unchecked_mut()),
334 ValueType::Object => DestructuredMut::Object(self.as_object_unchecked_mut()),
335 }
336 }
337 }
338
339 pub fn get(&self, index: impl ValueIndex) -> Option<&IValue> {
346 index.index_into(self)
347 }
348
349 pub fn get_mut(&mut self, index: impl ValueIndex) -> Option<&mut IValue> {
356 index.index_into_mut(self)
357 }
358
359 pub fn remove(&mut self, index: impl ValueIndex) -> Option<IValue> {
366 index.remove(self)
367 }
368
369 pub fn take(&mut self) -> IValue {
371 mem::replace(self, IValue::NULL)
372 }
373
374 #[must_use]
377 pub fn len(&self) -> Option<usize> {
378 match self.type_() {
379 ValueType::Array => Some(unsafe { self.as_array_unchecked().len() }),
381 ValueType::Object => Some(unsafe { self.as_object_unchecked().len() }),
383 _ => None,
384 }
385 }
386
387 #[must_use]
390 pub fn is_empty(&self) -> Option<bool> {
391 match self.type_() {
392 ValueType::Array => Some(unsafe { self.as_array_unchecked().is_empty() }),
394 ValueType::Object => Some(unsafe { self.as_object_unchecked().is_empty() }),
396 _ => None,
397 }
398 }
399
400 #[must_use]
403 pub fn is_null(&self) -> bool {
404 self.ptr == Self::NULL.ptr
405 }
406
407 #[must_use]
410 pub fn is_bool(&self) -> bool {
411 self.ptr == Self::TRUE.ptr || self.ptr == Self::FALSE.ptr
412 }
413
414 #[must_use]
416 pub fn is_true(&self) -> bool {
417 self.ptr == Self::TRUE.ptr
418 }
419
420 #[must_use]
422 pub fn is_false(&self) -> bool {
423 self.ptr == Self::FALSE.ptr
424 }
425
426 #[must_use]
429 pub fn to_bool(&self) -> Option<bool> {
430 if self.is_bool() {
431 Some(self.is_true())
432 } else {
433 None
434 }
435 }
436
437 #[must_use]
440 pub fn is_number(&self) -> bool {
441 self.type_tag() == TypeTag::Number
442 }
443
444 unsafe fn unchecked_cast_ref<T>(&self) -> &T {
445 &*(self as *const Self).cast::<T>()
446 }
447
448 unsafe fn unchecked_cast_mut<T>(&mut self) -> &mut T {
449 &mut *(self as *mut Self).cast::<T>()
450 }
451
452 unsafe fn as_number_unchecked(&self) -> &INumber {
454 self.unchecked_cast_ref()
455 }
456
457 unsafe fn as_number_unchecked_mut(&mut self) -> &mut INumber {
459 self.unchecked_cast_mut()
460 }
461
462 #[must_use]
465 pub fn as_number(&self) -> Option<&INumber> {
466 if self.is_number() {
467 Some(unsafe { self.as_number_unchecked() })
469 } else {
470 None
471 }
472 }
473
474 pub fn as_number_mut(&mut self) -> Option<&mut INumber> {
477 if self.is_number() {
478 Some(unsafe { self.as_number_unchecked_mut() })
480 } else {
481 None
482 }
483 }
484
485 pub fn into_number(self) -> Result<INumber, IValue> {
491 if self.is_number() {
492 Ok(INumber(self))
493 } else {
494 Err(self)
495 }
496 }
497
498 #[must_use]
500 pub fn to_i64(&self) -> Option<i64> {
501 self.as_number()?.to_i64()
502 }
503 #[must_use]
505 pub fn to_u64(&self) -> Option<u64> {
506 self.as_number()?.to_u64()
507 }
508 #[must_use]
510 pub fn to_f64(&self) -> Option<f64> {
511 self.as_number()?.to_f64()
512 }
513 #[must_use]
515 pub fn to_f32(&self) -> Option<f32> {
516 self.as_number()?.to_f32()
517 }
518 #[must_use]
520 pub fn to_i32(&self) -> Option<i32> {
521 self.as_number()?.to_i32()
522 }
523 #[must_use]
525 pub fn to_u32(&self) -> Option<u32> {
526 self.as_number()?.to_u32()
527 }
528 #[must_use]
530 pub fn to_isize(&self) -> Option<isize> {
531 self.as_number()?.to_isize()
532 }
533 #[must_use]
535 pub fn to_usize(&self) -> Option<usize> {
536 self.as_number()?.to_usize()
537 }
538 #[must_use]
541 pub fn to_f64_lossy(&self) -> Option<f64> {
542 Some(self.as_number()?.to_f64_lossy())
543 }
544 #[must_use]
547 pub fn to_f32_lossy(&self) -> Option<f32> {
548 Some(self.as_number()?.to_f32_lossy())
549 }
550
551 #[must_use]
554 pub fn is_string(&self) -> bool {
555 self.type_tag() == TypeTag::StringOrNull && self.is_ptr()
556 }
557
558 unsafe fn as_string_unchecked(&self) -> &IString {
560 self.unchecked_cast_ref()
561 }
562
563 unsafe fn as_string_unchecked_mut(&mut self) -> &mut IString {
565 self.unchecked_cast_mut()
566 }
567
568 #[must_use]
571 pub fn as_string(&self) -> Option<&IString> {
572 if self.is_string() {
573 Some(unsafe { self.as_string_unchecked() })
575 } else {
576 None
577 }
578 }
579
580 pub fn as_string_mut(&mut self) -> Option<&mut IString> {
583 if self.is_string() {
584 Some(unsafe { self.as_string_unchecked_mut() })
586 } else {
587 None
588 }
589 }
590
591 pub fn into_string(self) -> Result<IString, IValue> {
597 if self.is_string() {
598 Ok(IString(self))
599 } else {
600 Err(self)
601 }
602 }
603
604 #[must_use]
607 pub fn is_array(&self) -> bool {
608 self.type_tag() == TypeTag::ArrayOrFalse && self.is_ptr()
609 }
610
611 unsafe fn as_array_unchecked(&self) -> &IArray {
613 self.unchecked_cast_ref()
614 }
615
616 unsafe fn as_array_unchecked_mut(&mut self) -> &mut IArray {
618 self.unchecked_cast_mut()
619 }
620
621 #[must_use]
624 pub fn as_array(&self) -> Option<&IArray> {
625 if self.is_array() {
626 Some(unsafe { self.as_array_unchecked() })
628 } else {
629 None
630 }
631 }
632
633 pub fn as_array_mut(&mut self) -> Option<&mut IArray> {
636 if self.is_array() {
637 Some(unsafe { self.as_array_unchecked_mut() })
639 } else {
640 None
641 }
642 }
643
644 pub fn into_array(self) -> Result<IArray, IValue> {
650 if self.is_array() {
651 Ok(IArray(self))
652 } else {
653 Err(self)
654 }
655 }
656
657 #[must_use]
660 pub fn is_object(&self) -> bool {
661 self.type_tag() == TypeTag::ObjectOrTrue && self.is_ptr()
662 }
663
664 unsafe fn as_object_unchecked(&self) -> &IObject {
666 self.unchecked_cast_ref()
667 }
668
669 unsafe fn as_object_unchecked_mut(&mut self) -> &mut IObject {
671 self.unchecked_cast_mut()
672 }
673
674 #[must_use]
677 pub fn as_object(&self) -> Option<&IObject> {
678 if self.is_object() {
679 Some(unsafe { self.as_object_unchecked() })
681 } else {
682 None
683 }
684 }
685
686 pub fn as_object_mut(&mut self) -> Option<&mut IObject> {
689 if self.is_object() {
690 Some(unsafe { self.as_object_unchecked_mut() })
692 } else {
693 None
694 }
695 }
696
697 pub fn into_object(self) -> Result<IObject, IValue> {
703 if self.is_object() {
704 Ok(IObject(self))
705 } else {
706 Err(self)
707 }
708 }
709}
710
711impl Clone for IValue {
712 fn clone(&self) -> Self {
713 match self.type_() {
714 ValueType::Null | ValueType::Bool => Self { ptr: self.ptr },
716 ValueType::Array => unsafe { self.as_array_unchecked() }.clone_impl(),
718 ValueType::Object => unsafe { self.as_object_unchecked() }.clone_impl(),
719 ValueType::String => unsafe { self.as_string_unchecked() }.clone_impl(),
720 ValueType::Number => unsafe { self.as_number_unchecked() }.clone_impl(),
721 }
722 }
723}
724
725impl Drop for IValue {
726 fn drop(&mut self) {
727 match self.type_() {
728 ValueType::Null | ValueType::Bool => {}
730 ValueType::Array => unsafe { self.as_array_unchecked_mut() }.drop_impl(),
732 ValueType::Object => unsafe { self.as_object_unchecked_mut() }.drop_impl(),
733 ValueType::String => unsafe { self.as_string_unchecked_mut() }.drop_impl(),
734 ValueType::Number => unsafe { self.as_number_unchecked_mut() }.drop_impl(),
735 }
736 }
737}
738
739impl Hash for IValue {
740 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
741 match self.type_() {
742 ValueType::Null | ValueType::Bool | ValueType::String => self.ptr.hash(state),
744 ValueType::Array => unsafe { self.as_array_unchecked() }.hash(state),
746 ValueType::Object => unsafe { self.as_object_unchecked() }.hash(state),
748 ValueType::Number => unsafe { self.as_number_unchecked() }.hash(state),
750 }
751 }
752}
753
754impl PartialEq for IValue {
755 fn eq(&self, other: &Self) -> bool {
756 let (t1, t2) = (self.type_(), other.type_());
757 if t1 == t2 {
758 unsafe {
760 match t1 {
761 ValueType::Null | ValueType::Bool | ValueType::String => self.ptr == other.ptr,
763 ValueType::Number => self.as_number_unchecked() == other.as_number_unchecked(),
764 ValueType::Array => self.as_array_unchecked() == other.as_array_unchecked(),
765 ValueType::Object => self.as_object_unchecked() == other.as_object_unchecked(),
766 }
767 }
768 } else {
769 false
770 }
771 }
772}
773
774impl Eq for IValue {}
775impl PartialOrd for IValue {
776 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
777 let (t1, t2) = (self.type_(), other.type_());
778 if t1 == t2 {
779 unsafe {
781 match t1 {
782 ValueType::Null => Some(Ordering::Equal),
784 ValueType::Bool => self.is_true().partial_cmp(&other.is_true()),
785 ValueType::String => self
786 .as_string_unchecked()
787 .partial_cmp(other.as_string_unchecked()),
788 ValueType::Number => self
789 .as_number_unchecked()
790 .partial_cmp(other.as_number_unchecked()),
791 ValueType::Array => self
792 .as_array_unchecked()
793 .partial_cmp(other.as_array_unchecked()),
794 ValueType::Object => None,
795 }
796 }
797 } else {
798 t1.partial_cmp(&t2)
799 }
800 }
801}
802
803mod private {
804 #[doc(hidden)]
805 pub trait Sealed {}
806 impl Sealed for usize {}
807 impl Sealed for &str {}
808 impl Sealed for &super::IString {}
809 impl<T: Sealed> Sealed for &T {}
810}
811
812pub trait ValueIndex: private::Sealed + Copy {
815 #[doc(hidden)]
816 fn index_into(self, v: &IValue) -> Option<&IValue>;
817
818 #[doc(hidden)]
819 fn index_into_mut(self, v: &mut IValue) -> Option<&mut IValue>;
820
821 #[doc(hidden)]
822 fn index_or_insert(self, v: &mut IValue) -> &mut IValue;
823
824 #[doc(hidden)]
825 fn remove(self, v: &mut IValue) -> Option<IValue>;
826}
827
828impl ValueIndex for usize {
829 fn index_into(self, v: &IValue) -> Option<&IValue> {
830 v.as_array().unwrap().get(self)
831 }
832
833 fn index_into_mut(self, v: &mut IValue) -> Option<&mut IValue> {
834 v.as_array_mut().unwrap().get_mut(self)
835 }
836
837 fn index_or_insert(self, v: &mut IValue) -> &mut IValue {
838 self.index_into_mut(v).unwrap()
839 }
840
841 fn remove(self, v: &mut IValue) -> Option<IValue> {
842 v.as_array_mut().unwrap().remove(self)
843 }
844}
845
846impl ValueIndex for &str {
847 fn index_into(self, v: &IValue) -> Option<&IValue> {
848 v.as_object().unwrap().get(&IString::intern(self))
849 }
850
851 fn index_into_mut(self, v: &mut IValue) -> Option<&mut IValue> {
852 v.as_object_mut().unwrap().get_mut(&IString::intern(self))
853 }
854
855 fn index_or_insert(self, v: &mut IValue) -> &mut IValue {
856 &mut v.as_object_mut().unwrap()[self]
857 }
858
859 fn remove(self, v: &mut IValue) -> Option<IValue> {
860 v.as_object_mut().unwrap().remove(self)
861 }
862}
863
864impl ValueIndex for &IString {
865 fn index_into(self, v: &IValue) -> Option<&IValue> {
866 v.as_object().unwrap().get(self)
867 }
868
869 fn index_into_mut(self, v: &mut IValue) -> Option<&mut IValue> {
870 v.as_object_mut().unwrap().get_mut(self)
871 }
872
873 fn index_or_insert(self, v: &mut IValue) -> &mut IValue {
874 &mut v.as_object_mut().unwrap()[self]
875 }
876
877 fn remove(self, v: &mut IValue) -> Option<IValue> {
878 v.as_object_mut().unwrap().remove(self)
879 }
880}
881
882impl<T: ValueIndex> ValueIndex for &T {
883 fn index_into(self, v: &IValue) -> Option<&IValue> {
884 (*self).index_into(v)
885 }
886
887 fn index_into_mut(self, v: &mut IValue) -> Option<&mut IValue> {
888 (*self).index_into_mut(v)
889 }
890
891 fn index_or_insert(self, v: &mut IValue) -> &mut IValue {
892 (*self).index_or_insert(v)
893 }
894
895 fn remove(self, v: &mut IValue) -> Option<IValue> {
896 (*self).remove(v)
897 }
898}
899
900impl<I: ValueIndex> Index<I> for IValue {
901 type Output = IValue;
902
903 #[inline]
904 fn index(&self, index: I) -> &IValue {
905 index.index_into(self).unwrap()
906 }
907}
908
909impl<I: ValueIndex> IndexMut<I> for IValue {
910 #[inline]
911 fn index_mut(&mut self, index: I) -> &mut IValue {
912 index.index_or_insert(self)
913 }
914}
915
916impl Debug for IValue {
917 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
918 unsafe {
919 match self.type_() {
920 ValueType::Null => f.write_str("null"),
922 ValueType::Bool => Debug::fmt(&self.is_true(), f),
923 ValueType::String => Debug::fmt(self.as_string_unchecked(), f),
925 ValueType::Array => Debug::fmt(self.as_array_unchecked(), f),
927 ValueType::Object => Debug::fmt(self.as_object_unchecked(), f),
929 ValueType::Number => Debug::fmt(self.as_number_unchecked(), f),
931 }
932 }
933 }
934}
935
936impl<T: Into<IValue>> From<Option<T>> for IValue {
937 fn from(other: Option<T>) -> Self {
938 if let Some(v) = other {
939 v.into()
940 } else {
941 Self::NULL
942 }
943 }
944}
945
946impl From<bool> for IValue {
947 fn from(other: bool) -> Self {
948 if other {
949 Self::TRUE
950 } else {
951 Self::FALSE
952 }
953 }
954}
955
956typed_conversions! {
957 INumber: i8, u8, i16, u16, i32, u32, i64, u64, isize, usize;
958 IString: String, &String, &mut String, &str, &mut str;
959 IArray:
960 Vec<T> where (T: Into<IValue>),
961 &[T] where (T: Into<IValue> + Clone);
962 IObject:
963 HashMap<K, V> where (K: Into<IString>, V: Into<IValue>),
964 BTreeMap<K, V> where (K: Into<IString>, V: Into<IValue>);
965}
966
967#[cfg(feature = "indexmap")]
968typed_conversions! {
969 IObject:
970 IndexMap<K, V> where (K: Into<IString>, V: Into<IValue>);
971}
972
973impl From<f32> for IValue {
974 fn from(v: f32) -> Self {
975 INumber::try_from(v).map(Into::into).unwrap_or(IValue::NULL)
976 }
977}
978
979impl From<f64> for IValue {
980 fn from(v: f64) -> Self {
981 INumber::try_from(v).map(Into::into).unwrap_or(IValue::NULL)
982 }
983}
984
985impl Default for IValue {
986 fn default() -> Self {
987 Self::NULL
988 }
989}
990
991#[cfg(test)]
992mod tests {
993 use super::*;
994
995 #[mockalloc::test]
996 fn can_use_literal() {
997 let x: IValue = ijson!({
998 "foo": "bar",
999 "x": [],
1000 "y": ["hi", "there", 1, 2, null, false, true, 63.5],
1001 "z": [false, {
1002 "a": null
1003 }, {}]
1004 });
1005 let y: IValue = serde_json::from_str(
1006 r#"{
1007 "foo": "bar",
1008 "x": [],
1009 "y": ["hi", "there", 1, 2, null, false, true, 63.5],
1010 "z": [false, {
1011 "a": null
1012 }, {}]
1013 }"#,
1014 )
1015 .unwrap();
1016 assert_eq!(x, y);
1017 }
1018
1019 #[test]
1020 #[allow(clippy::redundant_clone)]
1021 fn test_null() {
1022 let x: IValue = IValue::NULL;
1023 assert!(x.is_null());
1024 assert_eq!(x.type_(), ValueType::Null);
1025 assert!(matches!(x.clone().destructure(), Destructured::Null));
1026 assert!(matches!(x.clone().destructure_ref(), DestructuredRef::Null));
1027 assert!(matches!(x.clone().destructure_mut(), DestructuredMut::Null));
1028 }
1029
1030 #[test]
1031 fn test_bool() {
1032 for v in [true, false].iter().copied() {
1033 let mut x = IValue::from(v);
1034 assert!(x.is_bool());
1035 assert_eq!(x.type_(), ValueType::Bool);
1036 assert_eq!(x.to_bool(), Some(v));
1037 assert!(matches!(x.clone().destructure(), Destructured::Bool(u) if u == v));
1038 assert!(matches!(x.clone().destructure_ref(), DestructuredRef::Bool(u) if u == v));
1039 assert!(
1040 matches!(x.clone().destructure_mut(), DestructuredMut::Bool(u) if u.get() == v)
1041 );
1042
1043 if let DestructuredMut::Bool(mut b) = x.destructure_mut() {
1044 b.set(!v);
1045 }
1046
1047 assert_eq!(x.to_bool(), Some(!v));
1048 }
1049 }
1050
1051 #[mockalloc::test]
1052 fn test_number() {
1053 for v in 300..400 {
1054 let mut x = IValue::from(v);
1055 assert!(x.is_number());
1056 assert_eq!(x.type_(), ValueType::Number);
1057 assert_eq!(x.to_i32(), Some(v));
1058 assert_eq!(x.to_u32(), Some(v as u32));
1059 assert_eq!(x.to_i64(), Some(i64::from(v)));
1060 assert_eq!(x.to_u64(), Some(v as u64));
1061 assert_eq!(x.to_isize(), Some(v as isize));
1062 assert_eq!(x.to_usize(), Some(v as usize));
1063 assert_eq!(x.as_number(), Some(&v.into()));
1064 assert_eq!(x.as_number_mut(), Some(&mut v.into()));
1065 assert!(matches!(x.clone().destructure(), Destructured::Number(u) if u == v.into()));
1066 assert!(
1067 matches!(x.clone().destructure_ref(), DestructuredRef::Number(u) if *u == v.into())
1068 );
1069 assert!(
1070 matches!(x.clone().destructure_mut(), DestructuredMut::Number(u) if *u == v.into())
1071 );
1072 }
1073 }
1074
1075 #[mockalloc::test]
1076 fn test_string() {
1077 for v in 0..10 {
1078 let s = v.to_string();
1079 let mut x = IValue::from(&s);
1080 assert!(x.is_string());
1081 assert_eq!(x.type_(), ValueType::String);
1082 assert_eq!(x.as_string(), Some(&IString::intern(&s)));
1083 assert_eq!(x.as_string_mut(), Some(&mut IString::intern(&s)));
1084 assert!(matches!(x.clone().destructure(), Destructured::String(u) if u == s));
1085 assert!(matches!(x.clone().destructure_ref(), DestructuredRef::String(u) if *u == s));
1086 assert!(matches!(x.clone().destructure_mut(), DestructuredMut::String(u) if *u == s));
1087 }
1088 }
1089
1090 #[mockalloc::test]
1091 fn test_array() {
1092 for v in 0..10 {
1093 let mut a: IArray = (0..v).collect();
1094 let mut x = IValue::from(a.clone());
1095 assert!(x.is_array());
1096 assert_eq!(x.type_(), ValueType::Array);
1097 assert_eq!(x.as_array(), Some(&a));
1098 assert_eq!(x.as_array_mut(), Some(&mut a));
1099 assert!(matches!(x.clone().destructure(), Destructured::Array(u) if u == a));
1100 assert!(matches!(x.clone().destructure_ref(), DestructuredRef::Array(u) if *u == a));
1101 assert!(matches!(x.clone().destructure_mut(), DestructuredMut::Array(u) if *u == a));
1102 }
1103 }
1104
1105 #[mockalloc::test]
1106 fn test_object() {
1107 for v in 0..10 {
1108 let mut o: IObject = (0..v).map(|i| (i.to_string(), i)).collect();
1109 let mut x = IValue::from(o.clone());
1110 assert!(x.is_object());
1111 assert_eq!(x.type_(), ValueType::Object);
1112 assert_eq!(x.as_object(), Some(&o));
1113 assert_eq!(x.as_object_mut(), Some(&mut o));
1114 assert!(matches!(x.clone().destructure(), Destructured::Object(u) if u == o));
1115 assert!(matches!(x.clone().destructure_ref(), DestructuredRef::Object(u) if *u == o));
1116 assert!(matches!(x.clone().destructure_mut(), DestructuredMut::Object(u) if *u == o));
1117 }
1118 }
1119
1120 #[mockalloc::test]
1121 fn test_into_object_for_object() {
1122 let o: IObject = (0..10).map(|i| (i.to_string(), i)).collect();
1123 let x = IValue::from(o.clone());
1124
1125 assert_eq!(x.into_object(), Ok(o));
1126 }
1127}