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::{Buffers, prelude::*};
29use crate::{Deserializer, Node, Result};
30use crate::{cow::Cow, safer_unchecked::GetSaferUnchecked as _};
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    fn null() -> Self {
165        Self::Static(StaticNode::Null)
166    }
167    #[cfg_attr(not(feature = "no-inline"), inline)]
168    fn array_with_capacity(capacity: usize) -> Self {
169        Self::Array(Box::new(Vec::with_capacity(capacity)))
170    }
171    #[cfg_attr(not(feature = "no-inline"), inline)]
172    fn object_with_capacity(capacity: usize) -> Self {
173        Self::Object(Box::new(Object::with_capacity_and_hasher(
174            capacity,
175            ObjectHasher::default(),
176        )))
177    }
178}
179
180impl<'value> ValueAsMutArray for Value<'value> {
181    type Array = Array<'value>;
182    #[cfg_attr(not(feature = "no-inline"), inline)]
183    fn as_array_mut(&mut self) -> Option<&mut Vec<Value<'value>>> {
184        match self {
185            Self::Array(a) => Some(a),
186            _ => None,
187        }
188    }
189}
190impl<'value> ValueAsMutObject for Value<'value> {
191    type Object = Object<'value>;
192    /// Get mutable access to a map.
193    ///
194    /// ```rust
195    /// use simd_json::*;
196    /// use value_trait::prelude::*;
197    ///
198    /// let mut object: BorrowedValue = json!({
199    ///   "answer": 23,
200    ///   "key": 7
201    /// }).into();
202    /// assert_eq!(object["answer"], 23);
203    ///
204    /// if let Some(inner) = object.as_object_mut() {
205    ///   inner.insert("value".into(), BorrowedValue::from(json!({"nested": 42})));
206    /// }
207    /// assert_eq!(object["value"], json!({"nested": 42}));
208    ///
209    /// ```
210    #[cfg_attr(not(feature = "no-inline"), inline)]
211    fn as_object_mut(&mut self) -> Option<&mut Object<'value>> {
212        match self {
213            Self::Object(m) => Some(m),
214            _ => None,
215        }
216    }
217}
218
219impl TypedValue for Value<'_> {
220    #[cfg_attr(not(feature = "no-inline"), inline)]
221    fn value_type(&self) -> ValueType {
222        match self {
223            Self::Static(s) => s.value_type(),
224            Self::String(_) => ValueType::String,
225            Self::Array(_) => ValueType::Array,
226            Self::Object(_) => ValueType::Object,
227        }
228    }
229}
230impl ValueAsScalar for Value<'_> {
231    #[cfg_attr(not(feature = "no-inline"), inline)]
232    fn as_null(&self) -> Option<()> {
233        self.as_static()?.as_null()
234    }
235
236    #[cfg_attr(not(feature = "no-inline"), inline)]
237    fn as_bool(&self) -> Option<bool> {
238        self.as_static()?.as_bool()
239    }
240
241    #[cfg_attr(not(feature = "no-inline"), inline)]
242    fn as_i64(&self) -> Option<i64> {
243        self.as_static()?.as_i64()
244    }
245
246    #[cfg_attr(not(feature = "no-inline"), inline)]
247    fn as_i128(&self) -> Option<i128> {
248        self.as_static()?.as_i128()
249    }
250
251    #[cfg_attr(not(feature = "no-inline"), inline)]
252    fn as_u64(&self) -> Option<u64> {
253        self.as_static()?.as_u64()
254    }
255
256    #[cfg_attr(not(feature = "no-inline"), inline)]
257    fn as_u128(&self) -> Option<u128> {
258        self.as_static()?.as_u128()
259    }
260
261    #[cfg_attr(not(feature = "no-inline"), inline)]
262    fn as_f64(&self) -> Option<f64> {
263        self.as_static()?.as_f64()
264    }
265
266    #[cfg_attr(not(feature = "no-inline"), inline)]
267    fn cast_f64(&self) -> Option<f64> {
268        self.as_static()?.cast_f64()
269    }
270
271    #[cfg_attr(not(feature = "no-inline"), inline)]
272    fn as_str(&self) -> Option<&str> {
273        use std::borrow::Borrow;
274        match self {
275            Self::String(s) => Some(s.borrow()),
276            _ => None,
277        }
278    }
279}
280impl<'value> ValueAsArray for Value<'value> {
281    type Array = Array<'value>;
282
283    #[cfg_attr(not(feature = "no-inline"), inline)]
284    fn as_array(&self) -> Option<&Vec<Value<'value>>> {
285        match self {
286            Self::Array(a) => Some(a),
287            _ => None,
288        }
289    }
290}
291
292impl<'value> ValueAsObject for Value<'value> {
293    type Object = Object<'value>;
294
295    #[cfg_attr(not(feature = "no-inline"), inline)]
296    fn as_object(&self) -> Option<&Object<'value>> {
297        match self {
298            Self::Object(m) => Some(m),
299            _ => None,
300        }
301    }
302}
303
304impl<'value> ValueIntoString for Value<'value> {
305    type String = Cow<'value, str>;
306
307    fn into_string(self) -> Option<<Self as ValueIntoString>::String> {
308        match self {
309            Self::String(s) => Some(s),
310            _ => None,
311        }
312    }
313}
314
315impl<'value> ValueIntoArray for Value<'value> {
316    type Array = Array<'value>;
317
318    fn into_array(self) -> Option<<Self as ValueIntoArray>::Array> {
319        match self {
320            Self::Array(a) => Some(*a),
321            _ => None,
322        }
323    }
324}
325
326impl<'value> ValueIntoObject for Value<'value> {
327    type Object = Object<'value>;
328
329    fn into_object(self) -> Option<<Self as ValueIntoObject>::Object> {
330        match self {
331            Self::Object(a) => Some(*a),
332            _ => None,
333        }
334    }
335}
336
337#[cfg(not(tarpaulin_include))]
338impl fmt::Display for Value<'_> {
339    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
340        match self {
341            Self::Static(s) => write!(f, "{s}"),
342            Self::String(s) => write!(f, "{s}"),
343            Self::Array(a) => write!(f, "{a:?}"),
344            Self::Object(o) => write!(f, "{o:?}"),
345        }
346    }
347}
348
349impl<'value> Index<&str> for Value<'value> {
350    type Output = Value<'value>;
351    #[cfg_attr(not(feature = "no-inline"), inline)]
352    fn index(&self, index: &str) -> &Self::Output {
353        self.get(index).expect("index out of bounds")
354    }
355}
356
357impl<'value> Index<usize> for Value<'value> {
358    type Output = Value<'value>;
359    #[cfg_attr(not(feature = "no-inline"), inline)]
360    fn index(&self, index: usize) -> &Self::Output {
361        self.get_idx(index).expect("index out of bounds")
362    }
363}
364
365impl IndexMut<&str> for Value<'_> {
366    #[cfg_attr(not(feature = "no-inline"), inline)]
367    fn index_mut(&mut self, index: &str) -> &mut Self::Output {
368        self.get_mut(index).expect("index out of bounds")
369    }
370}
371
372impl IndexMut<usize> for Value<'_> {
373    #[cfg_attr(not(feature = "no-inline"), inline)]
374    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
375        self.get_idx_mut(index).expect("index out of bounds")
376    }
377}
378
379impl Default for Value<'_> {
380    #[cfg_attr(not(feature = "no-inline"), inline)]
381    fn default() -> Self {
382        Self::Static(StaticNode::Null)
383    }
384}
385
386pub(super) struct BorrowDeserializer<'de>(Deserializer<'de>);
387
388impl<'de> BorrowDeserializer<'de> {
389    pub fn from_deserializer(de: Deserializer<'de>) -> Self {
390        Self(de)
391    }
392
393    #[cfg_attr(not(feature = "no-inline"), inline)]
394    pub fn parse(&mut self) -> Value<'de> {
395        match unsafe { self.0.next_() } {
396            Node::Static(s) => Value::Static(s),
397            Node::String(s) => Value::from(s),
398            Node::Array { len, count: _ } => self.parse_array(len),
399            Node::Object { len, count: _ } => self.parse_map(len),
400        }
401    }
402
403    #[cfg_attr(not(feature = "no-inline"), inline)]
404    fn parse_array(&mut self, len: usize) -> Value<'de> {
405        // Rust doesn't optimize the normal loop away here
406        // so we write our own avoiding the length
407        // checks during push
408        let mut res: Vec<Value<'de>> = Vec::with_capacity(len);
409        let res_ptr = res.as_mut_ptr();
410        unsafe {
411            for i in 0..len {
412                res_ptr.add(i).write(self.parse());
413            }
414            res.set_len(len);
415        }
416        Value::Array(Box::new(res))
417    }
418
419    #[cfg_attr(not(feature = "no-inline"), inline)]
420    fn parse_map(&mut self, len: usize) -> Value<'de> {
421        let mut res = Object::with_capacity_and_hasher(len, ObjectHasher::default());
422
423        // Since we checked if it's empty we know that we at least have one
424        // element so we eat this
425        for _ in 0..len {
426            if let Node::String(key) = unsafe { self.0.next_() } {
427                #[cfg(not(feature = "value-no-dup-keys"))]
428                unsafe {
429                    res.insert_nocheck(key.into(), self.parse());
430                };
431                #[cfg(feature = "value-no-dup-keys")]
432                res.insert(key.into(), self.parse());
433            } else {
434                unreachable!("parse_map: key not a string");
435            }
436        }
437        Value::from(res)
438    }
439}
440pub(super) struct BorrowSliceDeserializer<'tape, 'de> {
441    tape: &'tape [Node<'de>],
442    idx: usize,
443}
444impl<'tape, 'de> BorrowSliceDeserializer<'tape, 'de> {
445    pub fn from_tape(de: &'tape [Node<'de>]) -> Self {
446        Self { tape: de, idx: 0 }
447    }
448    #[cfg_attr(not(feature = "no-inline"), inline)]
449    pub unsafe fn next_(&mut self) -> Node<'de> {
450        let r = unsafe { *self.tape.get_kinda_unchecked(self.idx) };
451        self.idx += 1;
452        r
453    }
454
455    #[cfg_attr(not(feature = "no-inline"), inline)]
456    pub fn parse(&mut self) -> Value<'de> {
457        match unsafe { self.next_() } {
458            Node::Static(s) => Value::Static(s),
459            Node::String(s) => Value::from(s),
460            Node::Array { len, count: _ } => self.parse_array(len),
461            Node::Object { len, count: _ } => self.parse_map(len),
462        }
463    }
464
465    #[cfg_attr(not(feature = "no-inline"), inline)]
466    fn parse_array(&mut self, len: usize) -> Value<'de> {
467        // Rust doesn't optimize the normal loop away here
468        // so we write our own avoiding the length
469        // checks during push
470        let mut res: Vec<Value<'de>> = Vec::with_capacity(len);
471        let res_ptr = res.as_mut_ptr();
472        unsafe {
473            for i in 0..len {
474                res_ptr.add(i).write(self.parse());
475            }
476            res.set_len(len);
477        }
478        Value::Array(Box::new(res))
479    }
480
481    #[cfg_attr(not(feature = "no-inline"), inline)]
482    fn parse_map(&mut self, len: usize) -> Value<'de> {
483        let mut res = Object::with_capacity_and_hasher(len, ObjectHasher::default());
484
485        // Since we checked if it's empty we know that we at least have one
486        // element so we eat this
487        for _ in 0..len {
488            if let Node::String(key) = unsafe { self.next_() } {
489                #[cfg(not(feature = "value-no-dup-keys"))]
490                unsafe {
491                    res.insert_nocheck(key.into(), self.parse());
492                };
493                #[cfg(feature = "value-no-dup-keys")]
494                res.insert(key.into(), self.parse());
495            } else {
496                unreachable!("parse_map: key needs to be a string");
497            }
498        }
499        Value::from(res)
500    }
501}
502
503#[cfg(test)]
504mod test {
505    #![allow(clippy::ignored_unit_patterns)]
506    #![allow(clippy::cognitive_complexity)]
507    use super::*;
508
509    #[test]
510    fn object_access() {
511        let mut v = Value::null();
512        assert_eq!(v.insert("key", ()), Err(AccessError::NotAnObject));
513        assert_eq!(v.remove("key"), Err(AccessError::NotAnObject));
514        let mut v = Value::object();
515        assert_eq!(v.insert("key", 1), Ok(None));
516        assert_eq!(v["key"], 1);
517        assert_eq!(v.insert("key", 2), Ok(Some(Value::from(1))));
518        v["key"] = 3.into();
519        assert_eq!(v.remove("key"), Ok(Some(Value::from(3))));
520    }
521
522    #[test]
523    fn array_access() {
524        let mut v = Value::null();
525        assert_eq!(v.push("key"), Err(AccessError::NotAnArray));
526        assert_eq!(v.pop(), Err(AccessError::NotAnArray));
527        let mut v = Value::array();
528        assert_eq!(v.push(1), Ok(()));
529        assert_eq!(v.push(2), Ok(()));
530        assert_eq!(v[0], 1);
531        v[0] = 0.into();
532        v[1] = 1.into();
533        assert_eq!(v.pop(), Ok(Some(Value::from(1))));
534        assert_eq!(v.pop(), Ok(Some(Value::from(0))));
535        assert_eq!(v.pop(), Ok(None));
536    }
537
538    #[cfg(feature = "128bit")]
539    #[test]
540    fn conversions_i128() {
541        let v = Value::from(i128::MAX);
542        assert!(v.is_i128());
543        assert!(v.is_u128());
544        assert!(!v.is_i64());
545        assert!(!v.is_u64());
546        assert!(!v.is_i32());
547        assert!(!v.is_u32());
548        assert!(!v.is_i16());
549        assert!(!v.is_u16());
550        assert!(!v.is_i8());
551        assert!(!v.is_u8());
552        assert!(!v.is_f64());
553        assert!(!v.is_f32());
554        assert!(v.is_f64_castable());
555        let v = Value::from(i128::MIN);
556        assert!(v.is_i128());
557        assert!(!v.is_u128());
558        assert!(!v.is_i64());
559        assert!(!v.is_u64());
560        assert!(!v.is_i32());
561        assert!(!v.is_u32());
562        assert!(!v.is_i16());
563        assert!(!v.is_u16());
564        assert!(!v.is_i8());
565        assert!(!v.is_u8());
566        assert!(!v.is_f64());
567        assert!(!v.is_f32());
568        assert!(v.is_f64_castable());
569    }
570
571    #[test]
572    fn conversions_i64() {
573        let v = Value::from(i64::MAX);
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        let v = Value::from(i64::MIN);
588        assert!(v.is_i128());
589        assert!(!v.is_u128());
590        assert!(v.is_i64());
591        assert!(!v.is_u64());
592        assert!(!v.is_i32());
593        assert!(!v.is_u32());
594        assert!(!v.is_i16());
595        assert!(!v.is_u16());
596        assert!(!v.is_i8());
597        assert!(!v.is_u8());
598        assert!(!v.is_f64());
599        assert!(!v.is_f32());
600        assert!(v.is_f64_castable());
601    }
602
603    #[test]
604    fn conversions_i32() {
605        let v = Value::from(i32::MAX);
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        let v = Value::from(i32::MIN);
620        assert!(v.is_i128());
621        assert!(!v.is_u128());
622        assert!(v.is_i64());
623        assert!(!v.is_u64());
624        assert!(v.is_i32());
625        assert!(!v.is_u32());
626        assert!(!v.is_i16());
627        assert!(!v.is_u16());
628        assert!(!v.is_i8());
629        assert!(!v.is_u8());
630        assert!(!v.is_f64());
631        assert!(!v.is_f32());
632        assert!(v.is_f64_castable());
633    }
634
635    #[test]
636    fn conversions_i16() {
637        let v = Value::from(i16::MAX);
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        let v = Value::from(i16::MIN);
652        assert!(v.is_i128());
653        assert!(!v.is_u128());
654        assert!(v.is_i64());
655        assert!(!v.is_u64());
656        assert!(v.is_i32());
657        assert!(!v.is_u32());
658        assert!(v.is_i16());
659        assert!(!v.is_u16());
660        assert!(!v.is_i8());
661        assert!(!v.is_u8());
662        assert!(!v.is_f64());
663        assert!(!v.is_f32());
664        assert!(v.is_f64_castable());
665        assert!(v.is_f64_castable());
666    }
667
668    #[test]
669    fn conversions_i8() {
670        let v = Value::from(i8::MAX);
671        assert!(v.is_i128());
672        assert!(v.is_u128());
673        assert!(v.is_i64());
674        assert!(v.is_u64());
675        assert!(v.is_i32());
676        assert!(v.is_u32());
677        assert!(v.is_i16());
678        assert!(v.is_u16());
679        assert!(v.is_i8());
680        assert!(v.is_u8());
681        assert!(!v.is_f64());
682        assert!(!v.is_f32());
683        assert!(v.is_f64_castable());
684        let v = Value::from(i8::MIN);
685        assert!(v.is_i128());
686        assert!(!v.is_u128());
687        assert!(v.is_i64());
688        assert!(!v.is_u64());
689        assert!(v.is_i32());
690        assert!(!v.is_u32());
691        assert!(v.is_i16());
692        assert!(!v.is_u16());
693        assert!(v.is_i8());
694        assert!(!v.is_u8());
695        assert!(!v.is_f64());
696        assert!(!v.is_f32());
697        assert!(v.is_f64_castable());
698    }
699
700    #[test]
701    fn conversions_usize() {
702        let v = Value::from(usize::MIN as u64);
703        assert!(v.is_i128());
704        assert!(v.is_u128());
705        assert!(v.is_i64());
706        assert!(v.is_u64());
707        assert!(v.is_usize());
708        assert!(v.is_i32());
709        assert!(v.is_u32());
710        assert!(v.is_i16());
711        assert!(v.is_u16());
712        assert!(v.is_i8());
713        assert!(v.is_u8());
714        assert!(!v.is_f64());
715        assert!(!v.is_f32());
716        assert!(!v.is_f64());
717        assert!(!v.is_f32());
718        assert!(v.is_f64_castable());
719    }
720
721    #[cfg(feature = "128bit")]
722    #[test]
723    fn conversions_u128() {
724        let v = Value::from(u128::MIN);
725        assert!(v.is_i128());
726        assert!(v.is_u128());
727        assert!(v.is_i64());
728        assert!(v.is_u64());
729        assert!(v.is_i32());
730        assert!(v.is_u32());
731        assert!(v.is_i16());
732        assert!(v.is_u16());
733        assert!(v.is_i8());
734        assert!(v.is_u8());
735        assert!(!v.is_f64());
736        assert!(!v.is_f32());
737        assert!(v.is_f64_castable());
738    }
739
740    #[test]
741    fn conversions_u64() {
742        let v = Value::from(u64::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_u32() {
760        let v = Value::from(u32::MAX);
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_u16() {
778        let v = Value::from(u16::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_u8() {
796        let v = Value::from(u8::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_f64() {
814        let v = Value::from(f64::MAX);
815        assert!(!v.is_i64());
816        assert!(!v.is_u64());
817        assert!(v.is_f64());
818        assert!(!v.is_f32());
819        assert!(v.is_f64_castable());
820        let v = Value::from(f64::MIN);
821        assert!(!v.is_i64());
822        assert!(!v.is_u64());
823        assert!(v.is_f64());
824        assert!(!v.is_f32());
825        assert!(v.is_f64_castable());
826        let v = Value::from("not a f64");
827        assert!(!v.is_f64_castable());
828    }
829
830    #[test]
831    fn conversions_f32() {
832        let v = Value::from(f32::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(f32::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    }
845
846    #[test]
847    fn conversions_array() {
848        let v = Value::from(vec![true]);
849        assert!(v.is_array());
850        assert_eq!(v.value_type(), ValueType::Array);
851        let v = Value::from("no array");
852        assert!(!v.is_array());
853    }
854
855    #[test]
856    fn conversions_bool() {
857        let v = Value::from(true);
858        assert!(v.is_bool());
859        assert_eq!(v.value_type(), ValueType::Bool);
860        let v = Value::from("no bool");
861        assert!(!v.is_bool());
862    }
863
864    #[test]
865    fn conversions_float() {
866        let v = Value::from(42.0);
867        assert!(v.is_f64());
868        assert_eq!(v.value_type(), ValueType::F64);
869        let v = Value::from("no float");
870        assert!(!v.is_f64());
871    }
872
873    #[test]
874    fn conversions_int() {
875        let v = Value::from(-42);
876        assert!(v.is_i64());
877        assert_eq!(v.value_type(), ValueType::I64);
878        #[cfg(feature = "128bit")]
879        {
880            let v = Value::from(-42_i128);
881            assert!(v.is_i64());
882            assert!(v.is_i128());
883            assert_eq!(v.value_type(), ValueType::I128);
884        }
885        let v = Value::from("no i64");
886        assert!(!v.is_i64());
887        assert!(!v.is_i128());
888    }
889
890    #[test]
891    fn conversions_uint() {
892        let v = Value::from(42_u64);
893        assert!(v.is_u64());
894        assert_eq!(v.value_type(), ValueType::U64);
895        #[cfg(feature = "128bit")]
896        {
897            let v = Value::from(42_u128);
898            assert!(v.is_u64());
899            assert!(v.is_u128());
900            assert_eq!(v.value_type(), ValueType::U128);
901        }
902        let v = Value::from("no u64");
903        assert!(!v.is_u64());
904        #[cfg(feature = "128bit")]
905        assert!(!v.is_u128());
906    }
907
908    #[test]
909    fn conversions_null() {
910        let v = Value::from(());
911        assert!(v.is_null());
912        assert_eq!(v.value_type(), ValueType::Null);
913        let v = Value::from("no null");
914        assert!(!v.is_null());
915    }
916
917    #[test]
918    fn conversions_object() {
919        let v = Value::from(Object::with_capacity_and_hasher(1, ObjectHasher::default()));
920        assert!(v.is_object());
921        assert_eq!(v.value_type(), ValueType::Object);
922        let v = Value::from("no object");
923        assert!(!v.is_object());
924    }
925
926    #[test]
927    fn conversions_str() {
928        let v = Value::from("bla");
929        assert!(v.is_str());
930        assert_eq!(v.value_type(), ValueType::String);
931        let v = Value::from(42);
932        assert!(!v.is_str());
933    }
934
935    #[test]
936    fn default() {
937        assert_eq!(Value::default(), Value::null());
938    }
939
940    #[cfg(not(target_arch = "wasm32"))]
941    use proptest::prelude::*;
942
943    #[cfg(not(target_arch = "wasm32"))]
944    fn arb_value() -> BoxedStrategy<Value<'static>> {
945        let leaf = prop_oneof![
946            Just(Value::Static(StaticNode::Null)),
947            any::<bool>()
948                .prop_map(StaticNode::Bool)
949                .prop_map(Value::Static),
950            any::<i64>()
951                .prop_map(StaticNode::I64)
952                .prop_map(Value::Static),
953            any::<u64>()
954                .prop_map(StaticNode::U64)
955                .prop_map(Value::Static),
956            any::<f64>()
957                .prop_map(StaticNode::from)
958                .prop_map(Value::Static),
959            ".*".prop_map(Value::from),
960        ];
961        leaf.prop_recursive(
962            8,   // 8 levels deep
963            256, // Shoot for maximum size of 256 nodes
964            10,  // We put up to 10 items per collection
965            |inner| {
966                prop_oneof![
967                    // Take the inner strategy and make the two recursive cases.
968                    prop::collection::vec(inner.clone(), 0..10).prop_map(Value::from),
969                    prop::collection::hash_map(".*".prop_map(Cow::from), inner, 0..10)
970                        .prop_map(|m| m.into_iter().collect()),
971                ]
972            },
973        )
974        .boxed()
975    }
976
977    #[cfg(not(target_arch = "wasm32"))]
978    proptest! {
979        #![proptest_config(ProptestConfig {
980            .. ProptestConfig::default()
981        })]
982
983        #[test]
984        fn prop_to_owned(borrowed in arb_value()) {
985            use crate::OwnedValue;
986            let owned: OwnedValue = borrowed.clone().into();
987            prop_assert_eq!(borrowed, owned);
988        }
989        #[test]
990        fn prop_into_static(borrowed in arb_value()) {
991            let static_borrowed = borrowed.clone().into_static();
992            assert_eq!(borrowed, static_borrowed);
993        }
994        #[test]
995        fn prop_clone_static(borrowed in arb_value()) {
996            let static_borrowed = borrowed.clone_static();
997            assert_eq!(borrowed, static_borrowed);
998        }
999        #[test]
1000        fn prop_serialize_deserialize(borrowed in arb_value()) {
1001            let mut string = borrowed.encode();
1002            let bytes = unsafe{ string.as_bytes_mut()};
1003            let decoded = to_value(bytes).expect("Failed to decode");
1004            prop_assert_eq!(borrowed, decoded);
1005        }
1006        #[test]
1007        #[allow(clippy::float_cmp)]
1008        fn prop_f64_cmp(f in proptest::num::f64::NORMAL) {
1009            let v: Value = f.into();
1010            prop_assert_eq!(v, f);
1011
1012        }
1013
1014        #[test]
1015        #[allow(clippy::float_cmp)]
1016        fn prop_f32_cmp(f in proptest::num::f32::NORMAL) {
1017            let v: Value = f.into();
1018            prop_assert_eq!(v, f);
1019
1020        }
1021        #[test]
1022        fn prop_i64_cmp(f in proptest::num::i64::ANY) {
1023            let v: Value = f.into();
1024            prop_assert_eq!(v, f);
1025        }
1026        #[test]
1027        fn prop_i32_cmp(f in proptest::num::i32::ANY) {
1028            let v: Value = f.into();
1029            prop_assert_eq!(v, f);
1030        }
1031        #[test]
1032        fn prop_i16_cmp(f in proptest::num::i16::ANY) {
1033            let v: Value = f.into();
1034            prop_assert_eq!(v, f);
1035        }
1036        #[test]
1037        fn prop_i8_cmp(f in proptest::num::i8::ANY) {
1038            let v: Value = f.into();
1039            prop_assert_eq!(v, f);
1040        }
1041        #[test]
1042        fn prop_u64_cmp(f in proptest::num::u64::ANY) {
1043            let v: Value = f.into();
1044            prop_assert_eq!(v, f);
1045        }
1046
1047        #[test]
1048        fn prop_usize_cmp(f in proptest::num::usize::ANY) {
1049            let v: Value = f.into();
1050            prop_assert_eq!(v, f);
1051        }
1052         #[test]
1053        fn prop_u32_cmp(f in proptest::num::u32::ANY) {
1054            let v: Value = f.into();
1055            prop_assert_eq!(v, f);
1056        }
1057        #[test]
1058        fn prop_u16_cmp(f in proptest::num::u16::ANY) {
1059            let v: Value = f.into();
1060            prop_assert_eq!(v, f);
1061        }
1062        #[test]
1063        fn prop_u8_cmp(f in proptest::num::u8::ANY) {
1064            let v: Value = f.into();
1065            assert_eq!(v, &f);
1066            prop_assert_eq!(v, f);
1067        }
1068        #[test]
1069        fn prop_string_cmp(f in ".*") {
1070            let v: Value = f.clone().into();
1071            prop_assert_eq!(v.clone(), f.as_str());
1072            prop_assert_eq!(v, f);
1073        }
1074
1075    }
1076    #[test]
1077    fn test_union_cmp() {
1078        let v: Value = ().into();
1079        assert_eq!(v, ());
1080    }
1081    #[test]
1082    #[allow(clippy::bool_assert_comparison)]
1083    fn test_bool_cmp() {
1084        let v: Value = true.into();
1085        assert_eq!(v, true);
1086        let v: Value = false.into();
1087        assert_eq!(v, false);
1088    }
1089    #[test]
1090    fn test_slice_cmp() {
1091        use std::iter::FromIterator;
1092        let v: Value = Value::from_iter(vec!["a", "b"]);
1093        assert_eq!(v, &["a", "b"][..]);
1094    }
1095    #[test]
1096    fn test_hashmap_cmp() {
1097        use std::iter::FromIterator;
1098        let v: Value = Value::from_iter(vec![("a", 1)]);
1099        assert_eq!(
1100            v,
1101            [("a", 1)]
1102                .iter()
1103                .copied()
1104                .collect::<std::collections::HashMap<&str, i32>>()
1105        );
1106    }
1107
1108    #[test]
1109    fn test_option_from() {
1110        let v: Option<u8> = None;
1111        let v: Value = v.into();
1112        assert_eq!(v, ());
1113        let v: Option<u8> = Some(42);
1114        let v: Value = v.into();
1115        assert_eq!(v, 42);
1116    }
1117
1118    // #[test]
1119    // fn size() {
1120    //     assert_eq!(std::mem::size_of::<Value>(), 24);
1121    // }
1122}