sonic_rs/value/
from.rs

1use std::{borrow::Cow, fmt::Debug, str::FromStr};
2
3use faststr::FastStr;
4
5use super::{array::Array, node::ValueMut, object::Object};
6use crate::{serde::number::N, value::node::Value, Number};
7
8impl From<Number> for Value {
9    /// Convert `Number` to a `Value`.
10    ///
11    /// # Examples
12    ///
13    /// ```
14    /// use sonic_rs::{json, Number, Value};
15    ///
16    /// let x = Value::from(Number::from(7));
17    /// assert_eq!(x, json!(7));
18    /// ```
19    #[inline]
20    fn from(val: Number) -> Self {
21        match val.n {
22            N::PosInt(u) => Value::new_u64(u),
23            N::NegInt(i) => Value::new_i64(i),
24            N::Float(f) => unsafe { Value::new_f64_unchecked(f) },
25        }
26    }
27}
28
29macro_rules! impl_from_integer {
30    ($($ty:ident),*) => {
31        $(
32            impl From<$ty> for Value {
33                fn from(val: $ty) -> Self {
34                    Into::<Number>::into(val).into()
35                }
36            }
37        )*
38    };
39    () => {};
40}
41
42impl_from_integer!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
43
44impl From<bool> for Value {
45    /// Convert `bool` to a boolean `Value`.
46    ///
47    /// # Examples
48    ///
49    /// ```
50    /// use sonic_rs::{JsonValueTrait, Value};
51    ///
52    /// let x: Value = true.into();
53    /// assert!(x.is_true());
54    /// ```
55    #[inline]
56    fn from(val: bool) -> Self {
57        Value::new_bool(val)
58    }
59}
60
61macro_rules! impl_from_str {
62    () => {};
63    ($($ty:ident),*) => {
64        $(
65            impl From<&$ty> for Value {
66                /// Convert a string type into a string `Value`. The string will be copied into the `Value`.
67                ///
68                /// # Performance
69                ///
70                /// If it is `&'static str`, recommend to use [`Value::from_static_str`] and it is zero-copy.
71                ///
72                #[inline]
73                fn from(val: &$ty) -> Self {
74                    Value::copy_str(val)
75                }
76            }
77        )*
78    };
79}
80
81impl_from_str!(String, str);
82
83impl From<FastStr> for Value {
84    #[inline]
85    fn from(val: FastStr) -> Self {
86        Value::new_faststr(val)
87    }
88}
89
90impl From<&FastStr> for Value {
91    #[inline]
92    fn from(val: &FastStr) -> Self {
93        Value::new_faststr(val.clone())
94    }
95}
96
97impl<'a> From<Cow<'a, str>> for Value {
98    /// Convert copy-on-write string to a string `Value`.
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// use std::borrow::Cow;
104    ///
105    /// use sonic_rs::Value;
106    ///
107    /// let s1: Cow<str> = Cow::Borrowed("hello");
108    /// let x1 = Value::from(s1);
109    ///
110    /// let s2: Cow<str> = Cow::Owned("hello".to_string());
111    /// let x2 = Value::from(s2);
112    ///
113    /// assert_eq!(x1, x2);
114    /// ```
115    #[inline]
116    fn from(value: Cow<'a, str>) -> Self {
117        Into::<Self>::into(value.as_ref())
118    }
119}
120
121impl From<char> for Value {
122    /// Convert `char` to a string `Value`.
123    ///
124    /// # Examples
125    ///
126    /// ```
127    /// use sonic_rs::{json, Value};
128    ///
129    /// let c: char = '😁';
130    /// let x: Value = c.into();
131    /// assert_eq!(x, json!("😁"));
132    /// ```
133    #[inline]
134    fn from(val: char) -> Self {
135        Into::<Self>::into(&val.to_string())
136    }
137}
138
139impl<T: Into<Value>> From<Vec<T>> for Value {
140    /// Convert a `Vec` to a `Value`.
141    ///
142    /// # Examples
143    ///
144    /// ```
145    /// use sonic_rs::{json, Value};
146    ///
147    /// assert_eq!(Value::from(vec!["hi", "hello"]), json!(["hi", "hello"]));
148    ///
149    /// assert_eq!(Value::from(Vec::<i32>::new()), json!([]));
150    ///
151    /// assert_eq!(
152    ///     Value::from(vec![json!(null), json!("hi")]),
153    ///     json!([null, "hi"])
154    /// );
155    /// ```
156    #[inline]
157    fn from(val: Vec<T>) -> Self {
158        let mut arr = Array::with_capacity(val.len()).0;
159        for v in val {
160            arr.append_value(v.into());
161        }
162        arr
163    }
164}
165
166impl<T: Clone + Into<Value>, const N: usize> From<&[T; N]> for Value {
167    /// Convert a array reference `&[T; N]` to a `Value`.
168    ///
169    /// # Examples
170    ///
171    /// ```
172    /// use sonic_rs::{Value, json};
173    ///
174    /// let x  = Value::from(&["hi", "hello"]);
175    ///
176    /// assert_eq!(x, json!(["hi", "hello"]));
177    #[inline]
178    fn from(val: &[T; N]) -> Self {
179        Into::<Value>::into(val.as_ref())
180    }
181}
182
183impl<T: Clone + Into<Value>> From<&[T]> for Value {
184    /// Convert a slice `&[T]` to a `Value`.
185    ///
186    /// # Examples
187    ///
188    /// ```
189    /// use sonic_rs::{json, Value};
190    ///
191    /// let x = Value::from(&["hi", "hello"][..]);
192    ///
193    /// assert_eq!(x, json!(["hi", "hello"]));
194    ///
195    /// let x: &[i32] = &[];
196    /// assert_eq!(Value::from(x), json!([]));
197    /// ```
198    fn from(val: &[T]) -> Self {
199        let mut arr = Array::with_capacity(val.len()).0;
200        for v in val {
201            arr.append_value(v.clone().into());
202        }
203        arr
204    }
205}
206
207impl From<()> for Value {
208    /// Convert `()` to `Value::Null`.
209    ///
210    /// # Examples
211    ///
212    /// ```
213    /// use sonic_rs::{JsonValueTrait, Value};
214    ///
215    /// assert!(Value::from(()).is_null());
216    /// ```
217    #[inline]
218    fn from(_: ()) -> Self {
219        Value::new_null()
220    }
221}
222
223impl<T> From<Option<T>> for Value
224where
225    T: Into<Value>,
226{
227    /// Convert `Option` to `Value::Null`.
228    ///
229    /// # Examples
230    ///
231    /// ```
232    /// use sonic_rs::{JsonValueTrait, Value};
233    ///
234    /// let u = Some(123);
235    /// let x = Value::from(u);
236    /// assert_eq!(x.as_i64(), u);
237    ///
238    /// let u = None;
239    /// let x: Value = u.into();
240    /// assert_eq!(x.as_i64(), u);
241    /// ```
242    #[inline]
243    fn from(opt: Option<T>) -> Self {
244        match opt {
245            None => Into::into(()),
246            Some(value) => Into::into(value),
247        }
248    }
249}
250
251impl FromStr for Value {
252    type Err = crate::Error;
253    /// Convert `&str` to `Value`. The `&str` will be copied into the `Value`.
254    ///
255    /// # Examples
256    ///
257    /// ```
258    /// use std::str::FromStr;
259    ///
260    /// use sonic_rs::{JsonValueTrait, Value};
261    ///
262    /// let x = Value::from_str("string").unwrap();
263    /// assert_eq!(x.as_str().unwrap(), "string");
264    /// ```
265    /// # Performance
266    ///
267    /// If it is `&'static str`, recommend to use [`Value::from_static_str`].
268    fn from_str(s: &str) -> Result<Self, Self::Err> {
269        Ok(Value::copy_str(s))
270    }
271}
272
273impl<'a, K: AsRef<str>, V: Clone + Into<Value>> FromIterator<(K, &'a V)> for Value {
274    /// Create a `Value` by collecting an iterator of key-value pairs.
275    /// The key will be copied into the `Value`.
276    ///
277    /// # Examples
278    ///
279    /// ```
280    /// use sonic_rs::{Value, json, object};
281    /// use std::collections::HashMap;
282    ///
283    /// let mut map = HashMap::new();
284    /// map.insert("sonic_rs", 40);
285    /// map.insert("json", 2);
286    ///
287    /// let x: Value = map.iter().collect();
288    /// assert_eq!(x, json!({"sonic_rs": 40, "json": 2}));
289    ///
290    /// let x: Value = Value::from_iter(&object!{"sonic_rs": 40, "json": 2});
291    /// assert_eq!(x, json!({"sonic_rs": 40, "json": 2}));
292    /// ```
293    fn from_iter<T: IntoIterator<Item = (K, &'a V)>>(iter: T) -> Self {
294        let mut obj = Object::with_capacity(0);
295        for (k, v) in iter.into_iter() {
296            obj.insert(&k, v.clone().into());
297        }
298        obj.0
299    }
300}
301
302impl<T: Into<Value>> FromIterator<T> for Value {
303    /// Create a `Value` by collecting an iterator of array elements.
304    ///
305    /// # Examples
306    ///
307    /// ```
308    /// use std::iter::FromIterator;
309    ///
310    /// use sonic_rs::{json, Value};
311    ///
312    /// let v = std::iter::repeat(6).take(3);
313    /// let x: Value = v.collect();
314    /// assert_eq!(x, json!([6, 6, 6]));
315    ///
316    /// let x = Value::from_iter(vec!["sonic_rs", "json", "serde"]);
317    /// assert_eq!(x, json!(["sonic_rs", "json", "serde"]));
318    /// ```
319    #[inline]
320    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
321        let mut arr = Array::with_capacity(0);
322        for v in iter.into_iter() {
323            arr.0.append_value(v.into());
324        }
325        arr.into()
326    }
327}
328
329//////////////////////////////////////////////////////////////////////////////
330
331impl<T: Into<Value>> From<Vec<T>> for Array {
332    /// Convert a `Vec` to a `Array`.
333    ///
334    /// # Examples
335    ///
336    /// ```
337    /// use sonic_rs::{array, value::Array};
338    ///
339    /// let v = vec!["hi", "hello"];
340    /// let x: Array = v.into();
341    /// assert_eq!(x, array!["hi", "hello"]);
342    /// ```
343    #[inline]
344    fn from(val: Vec<T>) -> Self {
345        Array(val.into())
346    }
347}
348
349impl<T: Clone + Into<Value>, const N: usize> From<&[T; N]> for Array {
350    /// Convert a array `&[T; N]` to a `Array`.
351    ///
352    /// # Examples
353    ///
354    /// ```
355    /// use sonic_rs::{array, Array};
356    ///
357    /// let v = &["hi", "hello"];
358    /// let x: Array = v.into();
359    /// assert_eq!(x, array!["hi", "hello"]);
360    /// ```
361    fn from(val: &[T; N]) -> Self {
362        Array(val.into())
363    }
364}
365
366impl<T: Into<Value>> FromIterator<T> for Array {
367    /// Create a `Array` by collecting an iterator of array elements.
368    ///
369    /// # Examples
370    ///
371    /// ```
372    /// use std::iter::FromIterator;
373    ///
374    /// use sonic_rs::{array, json, Array};
375    ///
376    /// let v = std::iter::repeat(6).take(3);
377    /// let x: Array = v.collect();
378    /// assert_eq!(x, json!([6, 6, 6]));
379    ///
380    /// let x = Array::from_iter(vec!["sonic_rs", "json", "serde"]);
381    /// assert_eq!(x, array!["sonic_rs", "json", "serde"]);
382    /// ```
383    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
384        let value = Value::from_iter(iter);
385        Array(value)
386    }
387}
388
389impl<T: Clone + Into<Value>> From<&[T]> for Array {
390    /// Convert a slice `&[T]` to a `Array`.
391    ///
392    /// # Examples
393    ///
394    /// ```
395    /// use sonic_rs::{array, value::Array};
396    ///
397    /// let v = &["hi", "hello"];
398    /// let x: Array = v.into();
399    /// assert_eq!(x, array!["hi", "hello"]);
400    /// ```
401    fn from(val: &[T]) -> Self {
402        let value = Into::<Value>::into(val);
403        Array(value)
404    }
405}
406
407//////////////////////////////////////////////////////////////////////////////
408
409impl<'a, K: AsRef<str>, V: Clone + Into<Value> + 'a> FromIterator<(K, &'a V)> for Object {
410    /// Create a `Object` by collecting an iterator of key-value pairs.
411    ///
412    /// # Examples
413    ///
414    /// ```
415    /// use std::collections::HashMap;
416    ///
417    /// use sonic_rs::{object, Object, Value};
418    ///
419    /// let mut map = HashMap::new();
420    /// map.insert("sonic_rs", 40);
421    /// map.insert("json", 2);
422    ///
423    /// let x: Object = map.iter().collect();
424    /// assert_eq!(x, object! {"sonic_rs": 40, "json": 2});
425    ///
426    /// let x = Object::from_iter(&object! {"sonic_rs": 40, "json": 2});
427    /// assert_eq!(x, object! {"sonic_rs": 40, "json": 2});
428    /// ```
429    #[inline]
430    fn from_iter<T: IntoIterator<Item = (K, &'a V)>>(iter: T) -> Self {
431        let value = Value::from_iter(iter);
432        Object(value)
433    }
434}
435
436impl<'a, T: Clone + Into<Value> + 'a> Extend<&'a T> for Array {
437    /// Extend a `Array` with the contents of an iterator.
438    ///
439    /// # Examples
440    ///
441    /// ```
442    /// use sonic_rs::{array, json, Array};
443    /// let mut arr = array![];
444    ///
445    /// // array extend from a slice &[i32]
446    /// arr.extend(&[1, 2, 3]);
447    /// assert_eq!(arr, array![1, 2, 3]);
448    ///
449    /// arr.extend(&Array::default());
450    /// assert_eq!(arr, array![1, 2, 3]);
451    ///
452    /// // array extend from other array
453    /// arr.extend(&array![4, 5, 6]);
454    /// assert_eq!(arr, array![1, 2, 3, 4, 5, 6]);
455    /// ```
456    #[inline]
457    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
458        if let ValueMut::Array(value) = self.0.as_mut() {
459            for v in iter.into_iter() {
460                value.push(v.clone().into());
461            }
462        } else {
463            unreachable!("should not happened")
464        }
465    }
466}
467
468impl<'a, K: AsRef<str> + ?Sized, V: Clone + Debug + Into<Value> + 'a> Extend<(&'a K, &'a V)>
469    for Object
470{
471    /// Extend a `Object` with the contents of an iterator.
472    ///
473    /// # Examples
474    ///
475    /// ```
476    /// use std::collections::HashMap;
477    ///
478    /// use sonic_rs::{json, object, Object, Value};
479    ///
480    /// let mut obj = object![];
481    /// let mut map: HashMap<&str, Value> = {
482    ///     let mut map = HashMap::new();
483    ///     map.insert("sonic", json!(40));
484    ///     map.insert("rs", json!(null));
485    ///     map
486    /// };
487    ///
488    /// obj.extend(&map);
489    /// assert_eq!(obj, object! {"sonic": 40, "rs": null});
490    ///
491    /// obj.extend(&object! {"object": [1, 2, 3]});
492    /// assert_eq!(obj, object! {"sonic": 40, "rs": null, "object": [1, 2, 3]});
493    /// ```
494    fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
495        for (k, v) in iter.into_iter() {
496            self.insert(k.as_ref(), v.clone().into());
497        }
498    }
499}
500
501impl From<Array> for Value {
502    #[inline]
503    fn from(val: Array) -> Self {
504        val.0
505    }
506}
507
508impl From<Object> for Value {
509    #[inline]
510    fn from(val: Object) -> Self {
511        val.0
512    }
513}
514
515#[cfg(test)]
516mod test {
517
518    use std::collections::HashMap;
519
520    use crate::{array, json, object, value::node::Value};
521
522    #[test]
523    fn test_from() {
524        let a1 = json!([1, 2, 3]);
525        let a2: Value = vec![1, 2, 3].into();
526        assert_eq!(a1, a2);
527        let v = Value::from(vec![json!("hi")]);
528        assert_eq!(v, json!(["hi"]));
529    }
530
531    #[test]
532    fn test_extend_array() {
533        let mut a1 = array![1, 2, 3];
534        let mut b1 = a1.clone();
535
536        let a2 = vec![4, 5, 6];
537        let a3 = array![4, 5, 6];
538        a1.extend(&a2);
539        b1.extend(&a3);
540        assert_eq!(a1, b1);
541    }
542
543    #[test]
544    fn test_extend_object() {
545        let mut obj = object![];
546        let mut map: HashMap<&str, Value> = HashMap::new();
547
548        map.insert("sonic_rs", json!(40));
549        map.insert("json", "hi".into());
550        obj.extend(map.iter());
551    }
552
553    #[test]
554    fn test_from_iter() {
555        use std::{collections::HashMap, iter::FromIterator};
556
557        use crate::{json, Value};
558
559        let mut map = HashMap::new();
560        map.insert("sonic_rs", 40);
561        map.insert("json", 2);
562
563        let x: Value = map.iter().collect();
564        assert_eq!(x, json!({"sonic_rs": 40, "json": 2}));
565
566        let v = std::iter::repeat_n(6, 3);
567        let x1: Vec<_> = v.collect();
568        dbg!(x1);
569        let v = std::iter::repeat_n(6, 3);
570        let x: Value = v.collect();
571        assert_eq!(x, json!([6, 6, 6]));
572
573        let x = Value::from_iter(vec!["sonic_rs", "json", "serde"]);
574        assert_eq!(x, json!(["sonic_rs", "json", "serde"]));
575    }
576}