simd_json/value/
borrowed.rs

1/// A dom object that references the raw input data to avoid allocations
2/// it trades having lifetimes for a gain in performance.
3///
4/// Access via array indexes is possible:
5/// ```rust
6/// use simd_json::{BorrowedValue, json};
7/// use simd_json::prelude::*;
8/// let mut a = json!([1, 2, 3]);
9/// assert_eq!(a[1], 2);
10/// a[1] = 42.into();
11/// assert_eq!(a[1], 42);
12/// ```
13///
14/// Access via object keys is possible as well:
15/// ```rust
16/// use simd_json::{BorrowedValue, json};
17/// use simd_json::prelude::*;
18/// let mut a = json!({"key": "not the value"});
19/// assert_eq!(a["key"], "not the value");
20/// a["key"] = "value".into();
21/// assert_eq!(a["key"], "value");
22/// ```
23mod cmp;
24mod from;
25mod serialize;
26
27use super::ObjectHasher;
28use crate::{cow::Cow, safer_unchecked::GetSaferUnchecked as _};
29use crate::{prelude::*, Buffers};
30use crate::{Deserializer, Node, Result};
31use halfbrown::HashMap;
32use std::fmt;
33use std::ops::{Index, IndexMut};
34
35/// Representation of a JSON object
36pub type Object<'value> = HashMap<Cow<'value, str>, Value<'value>, ObjectHasher>;
37/// Representation of a JSON array
38pub type Array<'value> = Vec<Value<'value>>;
39
40/// Parses a slice of bytes into a Value dom.
41///
42/// This function will rewrite the slice to de-escape strings.
43/// As we reference parts of the input slice the resulting dom
44/// has the same lifetime as the slice it was created from.
45///
46/// # Errors
47///
48/// Will return `Err` if `s` is invalid JSON.
49pub fn to_value(s: &mut [u8]) -> Result<Value> {
50    match Deserializer::from_slice(s) {
51        Ok(de) => Ok(BorrowDeserializer::from_deserializer(de).parse()),
52        Err(e) => Err(e),
53    }
54}
55
56/// Parses a slice of bytes into a Value dom.
57///
58/// This function will rewrite the slice to de-escape strings.
59/// As we reference parts of the input slice the resulting dom
60/// has the same lifetime as the slice it was created from.
61///
62/// Passes in reusable buffers to reduce allocations.
63///
64///  # Errors
65///
66/// Will return `Err` if `s` is invalid JSON.
67pub fn to_value_with_buffers<'value>(
68    s: &'value mut [u8],
69    buffers: &mut Buffers,
70) -> Result<Value<'value>> {
71    match Deserializer::from_slice_with_buffers(s, buffers) {
72        Ok(de) => Ok(BorrowDeserializer::from_deserializer(de).parse()),
73        Err(e) => Err(e),
74    }
75}
76
77/// Borrowed JSON-DOM Value, consider using the `ValueTrait`
78/// to access its content
79#[derive(Debug, Clone)]
80#[cfg_attr(feature = "ordered-float", derive(Eq))]
81pub enum Value<'value> {
82    /// Static values
83    Static(StaticNode),
84    /// string type
85    String(Cow<'value, str>),
86    /// array type
87    Array(Box<Vec<Value<'value>>>),
88    /// object type
89    Object(Box<Object<'value>>),
90}
91
92impl<'value> Value<'value> {
93    fn as_static(&self) -> Option<StaticNode> {
94        match self {
95            Self::Static(s) => Some(*s),
96            _ => None,
97        }
98    }
99
100    /// Enforces static lifetime on a borrowed value, this will
101    /// force all strings to become owned COW's, the same applies for
102    /// Object keys.
103    #[cfg_attr(not(feature = "no-inline"), inline)]
104    #[must_use]
105    pub fn into_static(self) -> Value<'static> {
106        match self {
107            // Ensure strings are static by turing the cow into a 'static
108            // This cow has static lifetime as it's owned, this information however is lost
109            // by the borrow checker so we need to transmute it to static.
110            // This invariant is guaranteed by the implementation of the cow, cloning an owned
111            // value will produce a owned value again see:
112            // https://docs.rs/beef/0.4.4/src/beef/generic.rs.html#379-391
113            Self::String(s) => unsafe {
114                std::mem::transmute::<Value<'value>, Value<'static>>(Self::String(Cow::from(
115                    s.into_owned(),
116                )))
117            },
118            // For an array we turn every value into a static
119            Self::Array(arr) => arr.into_iter().map(Value::into_static).collect(),
120            // For an object, we turn all keys into owned Cows and all values into 'static Values
121            Self::Object(obj) => obj
122                .into_iter()
123                .map(|(k, v)| (Cow::from(k.into_owned()), v.into_static()))
124                .collect(),
125
126            // Static nodes are always static
127            Value::Static(s) => Value::Static(s),
128        }
129    }
130
131    /// Clones the current value and enforces a static lifetime, it works the same
132    /// as `into_static` but includes cloning logic
133    #[cfg_attr(not(feature = "no-inline"), inline)]
134    #[must_use]
135    pub fn clone_static(&self) -> Value<'static> {
136        match self {
137            // Ensure strings are static by turing the cow into a 'static
138            // This cow has static lifetime as it's owned, this information however is lost
139            // by the borrow checker so we need to transmute it to static.
140            // This invariant is guaranteed by the implementation of the cow, cloning an owned
141            // value will produce a owned value again see:
142            // https://docs.rs/beef/0.4.4/src/beef/generic.rs.html#379-391
143            Self::String(s) => unsafe {
144                std::mem::transmute::<Value<'value>, Value<'static>>(Self::String(Cow::from(
145                    s.to_string(),
146                )))
147            },
148            // For an array we turn every value into a static
149            Self::Array(arr) => arr.iter().cloned().map(Value::into_static).collect(),
150            // For an object, we turn all keys into owned Cows and all values into 'static Values
151            Self::Object(obj) => obj
152                .iter()
153                .map(|(k, v)| (Cow::from(k.to_string()), v.clone_static()))
154                .collect(),
155
156            // Static nodes are always static
157            Value::Static(s) => Value::Static(*s),
158        }
159    }
160}
161
162impl<'value> ValueBuilder<'value> for Value<'value> {
163    #[cfg_attr(not(feature = "no-inline"), inline)]
164    #[must_use]
165    fn null() -> Self {
166        Self::Static(StaticNode::Null)
167    }
168    #[cfg_attr(not(feature = "no-inline"), inline)]
169    #[must_use]
170    fn array_with_capacity(capacity: usize) -> Self {
171        Self::Array(Box::new(Vec::with_capacity(capacity)))
172    }
173    #[cfg_attr(not(feature = "no-inline"), inline)]
174    #[must_use]
175    fn object_with_capacity(capacity: usize) -> Self {
176        Self::Object(Box::new(Object::with_capacity_and_hasher(
177            capacity,
178            ObjectHasher::default(),
179        )))
180    }
181}
182
183impl<'value> ValueAsMutArray for Value<'value> {
184    type Array = Array<'value>;
185    #[cfg_attr(not(feature = "no-inline"), inline)]
186    #[must_use]
187    fn as_array_mut(&mut self) -> Option<&mut Vec<Value<'value>>> {
188        match self {
189            Self::Array(a) => Some(a),
190            _ => None,
191        }
192    }
193}
194impl<'value> ValueAsMutObject for Value<'value> {
195    type Object = Object<'value>;
196    /// Get mutable access to a map.
197    ///
198    /// ```rust
199    /// use simd_json::*;
200    /// use value_trait::prelude::*;
201    ///
202    /// let mut object: BorrowedValue = json!({
203    ///   "answer": 23,
204    ///   "key": 7
205    /// }).into();
206    /// assert_eq!(object["answer"], 23);
207    ///
208    /// if let Some(inner) = object.as_object_mut() {
209    ///   inner.insert("value".into(), BorrowedValue::from(json!({"nested": 42})));
210    /// }
211    /// assert_eq!(object["value"], json!({"nested": 42}));
212    ///
213    /// ```
214    #[cfg_attr(not(feature = "no-inline"), inline)]
215    #[must_use]
216    fn as_object_mut(&mut self) -> Option<&mut Object<'value>> {
217        match self {
218            Self::Object(m) => Some(m),
219            _ => None,
220        }
221    }
222}
223
224impl<'value> TypedValue for Value<'value> {
225    #[cfg_attr(not(feature = "no-inline"), inline)]
226    #[must_use]
227    fn value_type(&self) -> ValueType {
228        match self {
229            Self::Static(s) => s.value_type(),
230            Self::String(_) => ValueType::String,
231            Self::Array(_) => ValueType::Array,
232            Self::Object(_) => ValueType::Object,
233        }
234    }
235}
236impl<'value> ValueAsScalar for Value<'value> {
237    #[cfg_attr(not(feature = "no-inline"), inline)]
238    #[must_use]
239    fn as_null(&self) -> Option<()> {
240        self.as_static()?.as_null()
241    }
242
243    #[cfg_attr(not(feature = "no-inline"), inline)]
244    #[must_use]
245    fn as_bool(&self) -> Option<bool> {
246        self.as_static()?.as_bool()
247    }
248
249    #[cfg_attr(not(feature = "no-inline"), inline)]
250    #[must_use]
251    fn as_i64(&self) -> Option<i64> {
252        self.as_static()?.as_i64()
253    }
254
255    #[cfg_attr(not(feature = "no-inline"), inline)]
256    #[must_use]
257    fn as_i128(&self) -> Option<i128> {
258        self.as_static()?.as_i128()
259    }
260
261    #[cfg_attr(not(feature = "no-inline"), inline)]
262    #[must_use]
263    fn as_u64(&self) -> Option<u64> {
264        self.as_static()?.as_u64()
265    }
266
267    #[cfg_attr(not(feature = "no-inline"), inline)]
268    #[must_use]
269    fn as_u128(&self) -> Option<u128> {
270        self.as_static()?.as_u128()
271    }
272
273    #[cfg_attr(not(feature = "no-inline"), inline)]
274    #[must_use]
275    fn as_f64(&self) -> Option<f64> {
276        self.as_static()?.as_f64()
277    }
278
279    #[cfg_attr(not(feature = "no-inline"), inline)]
280    #[must_use]
281    fn cast_f64(&self) -> Option<f64> {
282        self.as_static()?.cast_f64()
283    }
284
285    #[cfg_attr(not(feature = "no-inline"), inline)]
286    #[must_use]
287    fn as_str(&self) -> Option<&str> {
288        use std::borrow::Borrow;
289        match self {
290            Self::String(s) => Some(s.borrow()),
291            _ => None,
292        }
293    }
294}
295impl<'value> ValueAsArray for Value<'value> {
296    type Array = Array<'value>;
297
298    #[cfg_attr(not(feature = "no-inline"), inline)]
299    #[must_use]
300    fn as_array(&self) -> Option<&Vec<Value<'value>>> {
301        match self {
302            Self::Array(a) => Some(a),
303            _ => None,
304        }
305    }
306}
307
308impl<'value> ValueAsObject for Value<'value> {
309    type Object = Object<'value>;
310
311    #[cfg_attr(not(feature = "no-inline"), inline)]
312    #[must_use]
313    fn as_object(&self) -> Option<&Object<'value>> {
314        match self {
315            Self::Object(m) => Some(m),
316            _ => None,
317        }
318    }
319}
320
321impl<'value> ValueIntoString for Value<'value> {
322    type String = Cow<'value, str>;
323
324    fn into_string(self) -> Option<<Self as ValueIntoString>::String> {
325        match self {
326            Self::String(s) => Some(s),
327            _ => None,
328        }
329    }
330}
331
332impl<'value> ValueIntoArray for Value<'value> {
333    type Array = Array<'value>;
334
335    fn into_array(self) -> Option<<Self as ValueIntoArray>::Array> {
336        match self {
337            Self::Array(a) => Some(*a),
338            _ => None,
339        }
340    }
341}
342
343impl<'value> ValueIntoObject for Value<'value> {
344    type Object = Object<'value>;
345
346    fn into_object(self) -> Option<<Self as ValueIntoObject>::Object> {
347        match self {
348            Self::Object(a) => Some(*a),
349            _ => None,
350        }
351    }
352}
353
354#[cfg(not(tarpaulin_include))]
355impl<'value> fmt::Display for Value<'value> {
356    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
357        match self {
358            Self::Static(s) => write!(f, "{s}"),
359            Self::String(s) => write!(f, "{s}"),
360            Self::Array(a) => write!(f, "{a:?}"),
361            Self::Object(o) => write!(f, "{o:?}"),
362        }
363    }
364}
365
366impl<'value> Index<&str> for Value<'value> {
367    type Output = Value<'value>;
368    #[cfg_attr(not(feature = "no-inline"), inline)]
369    #[must_use]
370    fn index(&self, index: &str) -> &Self::Output {
371        self.get(index).expect("index out of bounds")
372    }
373}
374
375impl<'value> Index<usize> for Value<'value> {
376    type Output = Value<'value>;
377    #[cfg_attr(not(feature = "no-inline"), inline)]
378    #[must_use]
379    fn index(&self, index: usize) -> &Self::Output {
380        self.get_idx(index).expect("index out of bounds")
381    }
382}
383
384impl<'value> IndexMut<&str> for Value<'value> {
385    #[cfg_attr(not(feature = "no-inline"), inline)]
386    #[must_use]
387    fn index_mut(&mut self, index: &str) -> &mut Self::Output {
388        self.get_mut(index).expect("index out of bounds")
389    }
390}
391
392impl<'value> IndexMut<usize> for Value<'value> {
393    #[cfg_attr(not(feature = "no-inline"), inline)]
394    #[must_use]
395    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
396        self.get_idx_mut(index).expect("index out of bounds")
397    }
398}
399
400impl<'value> Default for Value<'value> {
401    #[cfg_attr(not(feature = "no-inline"), inline)]
402    #[must_use]
403    fn default() -> Self {
404        Self::Static(StaticNode::Null)
405    }
406}
407
408pub(super) struct BorrowDeserializer<'de>(Deserializer<'de>);
409
410impl<'de> BorrowDeserializer<'de> {
411    pub fn from_deserializer(de: Deserializer<'de>) -> Self {
412        Self(de)
413    }
414
415    #[cfg_attr(not(feature = "no-inline"), inline)]
416    pub fn parse(&mut self) -> Value<'de> {
417        match unsafe { self.0.next_() } {
418            Node::Static(s) => Value::Static(s),
419            Node::String(s) => Value::from(s),
420            Node::Array { len, count: _ } => self.parse_array(len),
421            Node::Object { len, count: _ } => self.parse_map(len),
422        }
423    }
424
425    #[cfg_attr(not(feature = "no-inline"), inline)]
426    fn parse_array(&mut self, len: usize) -> Value<'de> {
427        // Rust doesn't optimize the normal loop away here
428        // so we write our own avoiding the length
429        // checks during push
430        let mut res: Vec<Value<'de>> = Vec::with_capacity(len);
431        let res_ptr = res.as_mut_ptr();
432        unsafe {
433            for i in 0..len {
434                res_ptr.add(i).write(self.parse());
435            }
436            res.set_len(len);
437        }
438        Value::Array(Box::new(res))
439    }
440
441    #[cfg_attr(not(feature = "no-inline"), inline)]
442    fn parse_map(&mut self, len: usize) -> Value<'de> {
443        let mut res = Object::with_capacity_and_hasher(len, ObjectHasher::default());
444
445        // Since we checked if it's empty we know that we at least have one
446        // element so we eat this
447        for _ in 0..len {
448            if let Node::String(key) = unsafe { self.0.next_() } {
449                #[cfg(not(feature = "value-no-dup-keys"))]
450                res.insert_nocheck(key.into(), self.parse());
451                #[cfg(feature = "value-no-dup-keys")]
452                res.insert(key.into(), self.parse());
453            } else {
454                unreachable!();
455            }
456        }
457        Value::from(res)
458    }
459}
460pub(super) struct BorrowSliceDeserializer<'tape, 'de> {
461    tape: &'tape [Node<'de>],
462    idx: usize,
463}
464impl<'tape, 'de> BorrowSliceDeserializer<'tape, 'de> {
465    pub fn from_tape(de: &'tape [Node<'de>]) -> Self {
466        Self { tape: de, idx: 0 }
467    }
468    #[cfg_attr(not(feature = "no-inline"), inline)]
469    pub unsafe fn next_(&mut self) -> Node<'de> {
470        let r = unsafe { *self.tape.get_kinda_unchecked(self.idx) };
471        self.idx += 1;
472        r
473    }
474
475    #[cfg_attr(not(feature = "no-inline"), inline)]
476    pub fn parse(&mut self) -> Value<'de> {
477        match unsafe { self.next_() } {
478            Node::Static(s) => Value::Static(s),
479            Node::String(s) => Value::from(s),
480            Node::Array { len, count: _ } => self.parse_array(len),
481            Node::Object { len, count: _ } => self.parse_map(len),
482        }
483    }
484
485    #[cfg_attr(not(feature = "no-inline"), inline)]
486    fn parse_array(&mut self, len: usize) -> Value<'de> {
487        // Rust doesn't optimize the normal loop away here
488        // so we write our own avoiding the length
489        // checks during push
490        let mut res: Vec<Value<'de>> = Vec::with_capacity(len);
491        let res_ptr = res.as_mut_ptr();
492        unsafe {
493            for i in 0..len {
494                res_ptr.add(i).write(self.parse());
495            }
496            res.set_len(len);
497        }
498        Value::Array(Box::new(res))
499    }
500
501    #[cfg_attr(not(feature = "no-inline"), inline)]
502    fn parse_map(&mut self, len: usize) -> Value<'de> {
503        let mut res = Object::with_capacity_and_hasher(len, ObjectHasher::default());
504
505        // Since we checked if it's empty we know that we at least have one
506        // element so we eat this
507        for _ in 0..len {
508            if let Node::String(key) = unsafe { self.next_() } {
509                #[cfg(not(feature = "value-no-dup-keys"))]
510                res.insert_nocheck(key.into(), self.parse());
511                #[cfg(feature = "value-no-dup-keys")]
512                res.insert(key.into(), self.parse());
513            } else {
514                unreachable!();
515            }
516        }
517        Value::from(res)
518    }
519}
520
521#[cfg(test)]
522mod test {
523    #![allow(clippy::ignored_unit_patterns)]
524    #![allow(clippy::cognitive_complexity)]
525    use super::*;
526
527    #[test]
528    fn object_access() {
529        let mut v = Value::null();
530        assert_eq!(v.insert("key", ()), Err(AccessError::NotAnObject));
531        assert_eq!(v.remove("key"), Err(AccessError::NotAnObject));
532        let mut v = Value::object();
533        assert_eq!(v.insert("key", 1), Ok(None));
534        assert_eq!(v["key"], 1);
535        assert_eq!(v.insert("key", 2), Ok(Some(Value::from(1))));
536        v["key"] = 3.into();
537        assert_eq!(v.remove("key"), Ok(Some(Value::from(3))));
538    }
539
540    #[test]
541    fn array_access() {
542        let mut v = Value::null();
543        assert_eq!(v.push("key"), Err(AccessError::NotAnArray));
544        assert_eq!(v.pop(), Err(AccessError::NotAnArray));
545        let mut v = Value::array();
546        assert_eq!(v.push(1), Ok(()));
547        assert_eq!(v.push(2), Ok(()));
548        assert_eq!(v[0], 1);
549        v[0] = 0.into();
550        v[1] = 1.into();
551        assert_eq!(v.pop(), Ok(Some(Value::from(1))));
552        assert_eq!(v.pop(), Ok(Some(Value::from(0))));
553        assert_eq!(v.pop(), Ok(None));
554    }
555
556    #[cfg(feature = "128bit")]
557    #[test]
558    fn conversions_i128() {
559        let v = Value::from(i128::MAX);
560        assert!(v.is_i128());
561        assert!(v.is_u128());
562        assert!(!v.is_i64());
563        assert!(!v.is_u64());
564        assert!(!v.is_i32());
565        assert!(!v.is_u32());
566        assert!(!v.is_i16());
567        assert!(!v.is_u16());
568        assert!(!v.is_i8());
569        assert!(!v.is_u8());
570        assert!(!v.is_f64());
571        assert!(!v.is_f32());
572        assert!(v.is_f64_castable());
573        let v = Value::from(i128::MIN);
574        assert!(v.is_i128());
575        assert!(!v.is_u128());
576        assert!(!v.is_i64());
577        assert!(!v.is_u64());
578        assert!(!v.is_i32());
579        assert!(!v.is_u32());
580        assert!(!v.is_i16());
581        assert!(!v.is_u16());
582        assert!(!v.is_i8());
583        assert!(!v.is_u8());
584        assert!(!v.is_f64());
585        assert!(!v.is_f32());
586        assert!(v.is_f64_castable());
587    }
588
589    #[test]
590    fn conversions_i64() {
591        let v = Value::from(i64::MAX);
592        assert!(v.is_i128());
593        assert!(v.is_u128());
594        assert!(v.is_i64());
595        assert!(v.is_u64());
596        assert!(!v.is_i32());
597        assert!(!v.is_u32());
598        assert!(!v.is_i16());
599        assert!(!v.is_u16());
600        assert!(!v.is_i8());
601        assert!(!v.is_u8());
602        assert!(!v.is_f64());
603        assert!(!v.is_f32());
604        assert!(v.is_f64_castable());
605        let v = Value::from(i64::MIN);
606        assert!(v.is_i128());
607        assert!(!v.is_u128());
608        assert!(v.is_i64());
609        assert!(!v.is_u64());
610        assert!(!v.is_i32());
611        assert!(!v.is_u32());
612        assert!(!v.is_i16());
613        assert!(!v.is_u16());
614        assert!(!v.is_i8());
615        assert!(!v.is_u8());
616        assert!(!v.is_f64());
617        assert!(!v.is_f32());
618        assert!(v.is_f64_castable());
619    }
620
621    #[test]
622    fn conversions_i32() {
623        let v = Value::from(i32::MAX);
624        assert!(v.is_i128());
625        assert!(v.is_u128());
626        assert!(v.is_i64());
627        assert!(v.is_u64());
628        assert!(v.is_i32());
629        assert!(v.is_u32());
630        assert!(!v.is_i16());
631        assert!(!v.is_u16());
632        assert!(!v.is_i8());
633        assert!(!v.is_u8());
634        assert!(!v.is_f64());
635        assert!(!v.is_f32());
636        assert!(v.is_f64_castable());
637        let v = Value::from(i32::MIN);
638        assert!(v.is_i128());
639        assert!(!v.is_u128());
640        assert!(v.is_i64());
641        assert!(!v.is_u64());
642        assert!(v.is_i32());
643        assert!(!v.is_u32());
644        assert!(!v.is_i16());
645        assert!(!v.is_u16());
646        assert!(!v.is_i8());
647        assert!(!v.is_u8());
648        assert!(!v.is_f64());
649        assert!(!v.is_f32());
650        assert!(v.is_f64_castable());
651    }
652
653    #[test]
654    fn conversions_i16() {
655        let v = Value::from(i16::MAX);
656        assert!(v.is_i128());
657        assert!(v.is_u128());
658        assert!(v.is_i64());
659        assert!(v.is_u64());
660        assert!(v.is_i32());
661        assert!(v.is_u32());
662        assert!(v.is_i16());
663        assert!(v.is_u16());
664        assert!(!v.is_i8());
665        assert!(!v.is_u8());
666        assert!(!v.is_f64());
667        assert!(!v.is_f32());
668        assert!(v.is_f64_castable());
669        let v = Value::from(i16::MIN);
670        assert!(v.is_i128());
671        assert!(!v.is_u128());
672        assert!(v.is_i64());
673        assert!(!v.is_u64());
674        assert!(v.is_i32());
675        assert!(!v.is_u32());
676        assert!(v.is_i16());
677        assert!(!v.is_u16());
678        assert!(!v.is_i8());
679        assert!(!v.is_u8());
680        assert!(!v.is_f64());
681        assert!(!v.is_f32());
682        assert!(v.is_f64_castable());
683        assert!(v.is_f64_castable());
684    }
685
686    #[test]
687    fn conversions_i8() {
688        let v = Value::from(i8::MAX);
689        assert!(v.is_i128());
690        assert!(v.is_u128());
691        assert!(v.is_i64());
692        assert!(v.is_u64());
693        assert!(v.is_i32());
694        assert!(v.is_u32());
695        assert!(v.is_i16());
696        assert!(v.is_u16());
697        assert!(v.is_i8());
698        assert!(v.is_u8());
699        assert!(!v.is_f64());
700        assert!(!v.is_f32());
701        assert!(v.is_f64_castable());
702        let v = Value::from(i8::MIN);
703        assert!(v.is_i128());
704        assert!(!v.is_u128());
705        assert!(v.is_i64());
706        assert!(!v.is_u64());
707        assert!(v.is_i32());
708        assert!(!v.is_u32());
709        assert!(v.is_i16());
710        assert!(!v.is_u16());
711        assert!(v.is_i8());
712        assert!(!v.is_u8());
713        assert!(!v.is_f64());
714        assert!(!v.is_f32());
715        assert!(v.is_f64_castable());
716    }
717
718    #[test]
719    fn conversions_usize() {
720        let v = Value::from(usize::MIN as u64);
721        assert!(v.is_i128());
722        assert!(v.is_u128());
723        assert!(v.is_i64());
724        assert!(v.is_u64());
725        assert!(v.is_usize());
726        assert!(v.is_i32());
727        assert!(v.is_u32());
728        assert!(v.is_i16());
729        assert!(v.is_u16());
730        assert!(v.is_i8());
731        assert!(v.is_u8());
732        assert!(!v.is_f64());
733        assert!(!v.is_f32());
734        assert!(!v.is_f64());
735        assert!(!v.is_f32());
736        assert!(v.is_f64_castable());
737    }
738
739    #[cfg(feature = "128bit")]
740    #[test]
741    fn conversions_u128() {
742        let v = Value::from(u128::MIN);
743        assert!(v.is_i128());
744        assert!(v.is_u128());
745        assert!(v.is_i64());
746        assert!(v.is_u64());
747        assert!(v.is_i32());
748        assert!(v.is_u32());
749        assert!(v.is_i16());
750        assert!(v.is_u16());
751        assert!(v.is_i8());
752        assert!(v.is_u8());
753        assert!(!v.is_f64());
754        assert!(!v.is_f32());
755        assert!(v.is_f64_castable());
756    }
757
758    #[test]
759    fn conversions_u64() {
760        let v = Value::from(u64::MIN);
761        assert!(v.is_i128());
762        assert!(v.is_u128());
763        assert!(v.is_i64());
764        assert!(v.is_u64());
765        assert!(v.is_i32());
766        assert!(v.is_u32());
767        assert!(v.is_i16());
768        assert!(v.is_u16());
769        assert!(v.is_i8());
770        assert!(v.is_u8());
771        assert!(!v.is_f64());
772        assert!(!v.is_f32());
773        assert!(v.is_f64_castable());
774    }
775
776    #[test]
777    fn conversions_u32() {
778        let v = Value::from(u32::MAX);
779        assert!(v.is_i128());
780        assert!(v.is_u128());
781        assert!(v.is_i64());
782        assert!(v.is_u64());
783        assert!(!v.is_i32());
784        assert!(v.is_u32());
785        assert!(!v.is_i16());
786        assert!(!v.is_u16());
787        assert!(!v.is_i8());
788        assert!(!v.is_u8());
789        assert!(!v.is_f64());
790        assert!(!v.is_f32());
791        assert!(v.is_f64_castable());
792    }
793
794    #[test]
795    fn conversions_u16() {
796        let v = Value::from(u16::MAX);
797        assert!(v.is_i128());
798        assert!(v.is_u128());
799        assert!(v.is_i64());
800        assert!(v.is_u64());
801        assert!(v.is_i32());
802        assert!(v.is_u32());
803        assert!(!v.is_i16());
804        assert!(v.is_u16());
805        assert!(!v.is_i8());
806        assert!(!v.is_u8());
807        assert!(!v.is_f64());
808        assert!(!v.is_f32());
809        assert!(v.is_f64_castable());
810    }
811
812    #[test]
813    fn conversions_u8() {
814        let v = Value::from(u8::MAX);
815        assert!(v.is_i128());
816        assert!(v.is_u128());
817        assert!(v.is_i64());
818        assert!(v.is_u64());
819        assert!(v.is_i32());
820        assert!(v.is_u32());
821        assert!(v.is_i16());
822        assert!(v.is_u16());
823        assert!(!v.is_i8());
824        assert!(v.is_u8());
825        assert!(!v.is_f64());
826        assert!(!v.is_f32());
827        assert!(v.is_f64_castable());
828    }
829
830    #[test]
831    fn conversions_f64() {
832        let v = Value::from(f64::MAX);
833        assert!(!v.is_i64());
834        assert!(!v.is_u64());
835        assert!(v.is_f64());
836        assert!(!v.is_f32());
837        assert!(v.is_f64_castable());
838        let v = Value::from(f64::MIN);
839        assert!(!v.is_i64());
840        assert!(!v.is_u64());
841        assert!(v.is_f64());
842        assert!(!v.is_f32());
843        assert!(v.is_f64_castable());
844        let v = Value::from("not a f64");
845        assert!(!v.is_f64_castable());
846    }
847
848    #[test]
849    fn conversions_f32() {
850        let v = Value::from(f32::MAX);
851        assert!(!v.is_i64());
852        assert!(!v.is_u64());
853        assert!(v.is_f64());
854        assert!(v.is_f32());
855        assert!(v.is_f64_castable());
856        let v = Value::from(f32::MIN);
857        assert!(!v.is_i64());
858        assert!(!v.is_u64());
859        assert!(v.is_f64());
860        assert!(v.is_f32());
861        assert!(v.is_f64_castable());
862    }
863
864    #[test]
865    fn conversions_array() {
866        let v = Value::from(vec![true]);
867        assert!(v.is_array());
868        assert_eq!(v.value_type(), ValueType::Array);
869        let v = Value::from("no array");
870        assert!(!v.is_array());
871    }
872
873    #[test]
874    fn conversions_bool() {
875        let v = Value::from(true);
876        assert!(v.is_bool());
877        assert_eq!(v.value_type(), ValueType::Bool);
878        let v = Value::from("no bool");
879        assert!(!v.is_bool());
880    }
881
882    #[test]
883    fn conversions_float() {
884        let v = Value::from(42.0);
885        assert!(v.is_f64());
886        assert_eq!(v.value_type(), ValueType::F64);
887        let v = Value::from("no float");
888        assert!(!v.is_f64());
889    }
890
891    #[test]
892    fn conversions_int() {
893        let v = Value::from(-42);
894        assert!(v.is_i64());
895        assert_eq!(v.value_type(), ValueType::I64);
896        #[cfg(feature = "128bit")]
897        {
898            let v = Value::from(-42_i128);
899            assert!(v.is_i64());
900            assert!(v.is_i128());
901            assert_eq!(v.value_type(), ValueType::I128);
902        }
903        let v = Value::from("no i64");
904        assert!(!v.is_i64());
905        assert!(!v.is_i128());
906    }
907
908    #[test]
909    fn conversions_uint() {
910        let v = Value::from(42_u64);
911        assert!(v.is_u64());
912        assert_eq!(v.value_type(), ValueType::U64);
913        #[cfg(feature = "128bit")]
914        {
915            let v = Value::from(42_u128);
916            assert!(v.is_u64());
917            assert!(v.is_u128());
918            assert_eq!(v.value_type(), ValueType::U128);
919        }
920        let v = Value::from("no u64");
921        assert!(!v.is_u64());
922        #[cfg(feature = "128bit")]
923        assert!(!v.is_u128());
924    }
925
926    #[test]
927    fn conversions_null() {
928        let v = Value::from(());
929        assert!(v.is_null());
930        assert_eq!(v.value_type(), ValueType::Null);
931        let v = Value::from("no null");
932        assert!(!v.is_null());
933    }
934
935    #[test]
936    fn conversions_object() {
937        let v = Value::from(Object::with_capacity_and_hasher(1, ObjectHasher::default()));
938        assert!(v.is_object());
939        assert_eq!(v.value_type(), ValueType::Object);
940        let v = Value::from("no object");
941        assert!(!v.is_object());
942    }
943
944    #[test]
945    fn conversions_str() {
946        let v = Value::from("bla");
947        assert!(v.is_str());
948        assert_eq!(v.value_type(), ValueType::String);
949        let v = Value::from(42);
950        assert!(!v.is_str());
951    }
952
953    #[test]
954    fn default() {
955        assert_eq!(Value::default(), Value::null());
956    }
957
958    #[cfg(not(target_arch = "wasm32"))]
959    use proptest::prelude::*;
960
961    #[cfg(not(target_arch = "wasm32"))]
962    fn arb_value() -> BoxedStrategy<Value<'static>> {
963        let leaf = prop_oneof![
964            Just(Value::Static(StaticNode::Null)),
965            any::<bool>()
966                .prop_map(StaticNode::Bool)
967                .prop_map(Value::Static),
968            any::<i64>()
969                .prop_map(StaticNode::I64)
970                .prop_map(Value::Static),
971            any::<u64>()
972                .prop_map(StaticNode::U64)
973                .prop_map(Value::Static),
974            any::<f64>()
975                .prop_map(StaticNode::from)
976                .prop_map(Value::Static),
977            ".*".prop_map(Value::from),
978        ];
979        leaf.prop_recursive(
980            8,   // 8 levels deep
981            256, // Shoot for maximum size of 256 nodes
982            10,  // We put up to 10 items per collection
983            |inner| {
984                prop_oneof![
985                    // Take the inner strategy and make the two recursive cases.
986                    prop::collection::vec(inner.clone(), 0..10).prop_map(Value::from),
987                    prop::collection::hash_map(".*".prop_map(Cow::from), inner, 0..10)
988                        .prop_map(|m| m.into_iter().collect()),
989                ]
990            },
991        )
992        .boxed()
993    }
994
995    #[cfg(not(target_arch = "wasm32"))]
996    proptest! {
997        #![proptest_config(ProptestConfig {
998            .. ProptestConfig::default()
999        })]
1000
1001        #[test]
1002        fn prop_to_owned(borrowed in arb_value()) {
1003            use crate::OwnedValue;
1004            let owned: OwnedValue = borrowed.clone().into();
1005            prop_assert_eq!(borrowed, owned);
1006        }
1007        #[test]
1008        fn prop_into_static(borrowed in arb_value()) {
1009            let static_borrowed = borrowed.clone().into_static();
1010            assert_eq!(borrowed, static_borrowed);
1011        }
1012        #[test]
1013        fn prop_clone_static(borrowed in arb_value()) {
1014            let static_borrowed = borrowed.clone_static();
1015            assert_eq!(borrowed, static_borrowed);
1016        }
1017        #[test]
1018        fn prop_serialize_deserialize(borrowed in arb_value()) {
1019            let mut string = borrowed.encode();
1020            let bytes = unsafe{ string.as_bytes_mut()};
1021            let decoded = to_value(bytes).expect("Failed to decode");
1022            prop_assert_eq!(borrowed, decoded);
1023        }
1024        #[test]
1025        #[allow(clippy::float_cmp)]
1026        fn prop_f64_cmp(f in proptest::num::f64::NORMAL) {
1027            let v: Value = f.into();
1028            prop_assert_eq!(v, f);
1029
1030        }
1031
1032        #[test]
1033        #[allow(clippy::float_cmp)]
1034        fn prop_f32_cmp(f in proptest::num::f32::NORMAL) {
1035            let v: Value = f.into();
1036            prop_assert_eq!(v, f);
1037
1038        }
1039        #[test]
1040        fn prop_i64_cmp(f in proptest::num::i64::ANY) {
1041            let v: Value = f.into();
1042            prop_assert_eq!(v, f);
1043        }
1044        #[test]
1045        fn prop_i32_cmp(f in proptest::num::i32::ANY) {
1046            let v: Value = f.into();
1047            prop_assert_eq!(v, f);
1048        }
1049        #[test]
1050        fn prop_i16_cmp(f in proptest::num::i16::ANY) {
1051            let v: Value = f.into();
1052            prop_assert_eq!(v, f);
1053        }
1054        #[test]
1055        fn prop_i8_cmp(f in proptest::num::i8::ANY) {
1056            let v: Value = f.into();
1057            prop_assert_eq!(v, f);
1058        }
1059        #[test]
1060        fn prop_u64_cmp(f in proptest::num::u64::ANY) {
1061            let v: Value = f.into();
1062            prop_assert_eq!(v, f);
1063        }
1064
1065        #[test]
1066        fn prop_usize_cmp(f in proptest::num::usize::ANY) {
1067            let v: Value = f.into();
1068            prop_assert_eq!(v, f);
1069        }
1070         #[test]
1071        fn prop_u32_cmp(f in proptest::num::u32::ANY) {
1072            let v: Value = f.into();
1073            prop_assert_eq!(v, f);
1074        }
1075        #[test]
1076        fn prop_u16_cmp(f in proptest::num::u16::ANY) {
1077            let v: Value = f.into();
1078            prop_assert_eq!(v, f);
1079        }
1080        #[test]
1081        fn prop_u8_cmp(f in proptest::num::u8::ANY) {
1082            let v: Value = f.into();
1083            assert_eq!(v, &f);
1084            prop_assert_eq!(v, f);
1085        }
1086        #[test]
1087        fn prop_string_cmp(f in ".*") {
1088            let v: Value = f.clone().into();
1089            prop_assert_eq!(v.clone(), f.as_str());
1090            prop_assert_eq!(v, f);
1091        }
1092
1093    }
1094    #[test]
1095    fn test_union_cmp() {
1096        let v: Value = ().into();
1097        assert_eq!(v, ());
1098    }
1099    #[test]
1100    #[allow(clippy::bool_assert_comparison)]
1101    fn test_bool_cmp() {
1102        let v: Value = true.into();
1103        assert_eq!(v, true);
1104        let v: Value = false.into();
1105        assert_eq!(v, false);
1106    }
1107    #[test]
1108    fn test_slice_cmp() {
1109        use std::iter::FromIterator;
1110        let v: Value = Value::from_iter(vec!["a", "b"]);
1111        assert_eq!(v, &["a", "b"][..]);
1112    }
1113    #[test]
1114    fn test_hashmap_cmp() {
1115        use std::iter::FromIterator;
1116        let v: Value = Value::from_iter(vec![("a", 1)]);
1117        assert_eq!(
1118            v,
1119            [("a", 1)]
1120                .iter()
1121                .copied()
1122                .collect::<std::collections::HashMap<&str, i32>>()
1123        );
1124    }
1125
1126    #[test]
1127    fn test_option_from() {
1128        let v: Option<u8> = None;
1129        let v: Value = v.into();
1130        assert_eq!(v, ());
1131        let v: Option<u8> = Some(42);
1132        let v: Value = v.into();
1133        assert_eq!(v, 42);
1134    }
1135
1136    // #[test]
1137    // fn size() {
1138    //     assert_eq!(std::mem::size_of::<Value>(), 24);
1139    // }
1140}