tower_sesh/value/
from.rs

1// Adapted from https://github.com/serde-rs/json.
2
3use std::borrow::Cow;
4
5use super::{error::ErrorImpl, Error, Map, Number, Value};
6
7impl From<()> for Value {
8    /// Convert [`()`] to [`Value::Null`].
9    ///
10    /// [`()`]: primitive@unit
11    ///
12    /// # Examples
13    ///
14    /// ```
15    /// # use tower_sesh::Value;
16    /// #
17    /// let u = ();
18    /// let x: Value = u.into();
19    /// ```
20    #[allow(clippy::let_unit_value)]
21    fn from(value: ()) -> Self {
22        let _ = value;
23        Value::Null
24    }
25}
26
27impl From<bool> for Value {
28    /// Convert [boolean] to [`Value::Bool`].
29    ///
30    /// [boolean]: bool
31    ///
32    /// # Examples
33    ///
34    /// ```
35    /// # use tower_sesh::Value;
36    /// #
37    /// let b = false;
38    /// let x: Value = b.into();
39    /// ```
40    fn from(value: bool) -> Self {
41        Value::Bool(value)
42    }
43}
44
45macro_rules! from_integer {
46    ($($ty:ident)*) => {
47        $(
48            impl From<$ty> for Value {
49                fn from(value: $ty) -> Self {
50                    Value::Number(value.into())
51                }
52            }
53        )*
54    };
55}
56
57from_integer! {
58    u8 u16 u32 u64 usize
59    i8 i16 i32 i64 isize
60}
61
62impl TryFrom<f32> for Value {
63    type Error = Error;
64
65    /// Convert a [32-bit floating point number] to [`Value::Number`], or return
66    /// an error if infinite or NaN.
67    ///
68    /// [32-bit floating point number]: f32
69    ///
70    /// # Examples
71    ///
72    /// ```
73    /// # use tower_sesh::Value;
74    /// #
75    /// let f: f32 = 13.37;
76    /// let x: Value = f.try_into().unwrap();
77    /// ```
78    fn try_from(value: f32) -> Result<Self, Self::Error> {
79        Number::from_f32(value)
80            .map(Value::Number)
81            .ok_or_else(|| Error::from(ErrorImpl::FloatMustBeFinite))
82    }
83}
84
85impl TryFrom<f64> for Value {
86    type Error = Error;
87
88    /// Convert a [64-bit floating point number] to [`Value::Number`], or return
89    /// an error if infinite or NaN.
90    ///
91    /// [64-bit floating point number]: f64
92    ///
93    /// # Examples
94    ///
95    /// ```
96    /// # use tower_sesh::Value;
97    /// #
98    /// let f: f64 = 13.37;
99    /// let x: Value = f.try_into().unwrap();
100    /// ```
101    fn try_from(value: f64) -> Result<Self, Self::Error> {
102        Number::from_f64(value)
103            .map(Value::Number)
104            .ok_or_else(|| Error::from(ErrorImpl::FloatMustBeFinite))
105    }
106}
107
108impl From<Number> for Value {
109    /// Convert [`Number`] to [`Value::Number`].
110    ///
111    /// # Examples
112    ///
113    /// ```
114    /// use tower_sesh::{value::Number, Value};
115    ///
116    /// let n = Number::from(7);
117    /// let x: Value = n.into();
118    /// ```
119    fn from(value: Number) -> Self {
120        Value::Number(value)
121    }
122}
123
124impl From<String> for Value {
125    /// Convert [`String`] to [`Value::String`].
126    ///
127    /// # Examples
128    ///
129    /// ```
130    /// # use tower_sesh::Value;
131    /// #
132    /// let s: String = "lorem".to_owned();
133    /// let x: Value = s.into();
134    /// ```
135    fn from(value: String) -> Self {
136        Value::String(value)
137    }
138}
139
140impl From<&str> for Value {
141    /// Convert [string slice] to [`Value::String`].
142    ///
143    /// [string slice]: str
144    ///
145    /// # Examples
146    ///
147    /// ```
148    /// # use tower_sesh::Value;
149    /// #
150    /// let s: &str = "lorem";
151    /// let x: Value = s.into();
152    /// ```
153    fn from(value: &str) -> Self {
154        Value::String(value.to_owned())
155    }
156}
157
158impl<'a> From<Cow<'a, str>> for Value {
159    /// Convert [clone-on-write] string to [`Value::String`].
160    ///
161    /// [clone-on-write]: std::borrow::Cow
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// use std::borrow::Cow;
167    /// use tower_sesh::Value;
168    ///
169    /// let s: Cow<str> = Cow::Borrowed("lorem");
170    /// let x: Value = s.into();
171    ///
172    /// let s: Cow<str> = Cow::Owned("lorem".to_owned());
173    /// let x: Value = s.into();
174    /// ```
175    fn from(value: Cow<'a, str>) -> Self {
176        Value::String(value.into_owned())
177    }
178}
179
180impl<T> From<Vec<T>> for Value
181where
182    T: Into<Value>,
183{
184    /// Convert a [`Vec`] to [`Value::Array`].
185    ///
186    /// # Examples
187    ///
188    /// ```
189    /// # use tower_sesh::Value;
190    /// #
191    /// let v = vec!["lorem", "ipsum", "dolor"];
192    /// let x: Value = v.into();
193    /// ```
194    fn from(value: Vec<T>) -> Self {
195        Value::Array(value.into_iter().map(Into::into).collect())
196    }
197}
198
199impl<T, const N: usize> From<[T; N]> for Value
200where
201    T: Into<Value>,
202{
203    /// Convert an [array] to [`Value::Array`].
204    ///
205    /// [array]: primitive@array
206    ///
207    /// # Examples
208    ///
209    /// ```
210    /// # use tower_sesh::Value;
211    /// #
212    /// let v: [&str; 3] = ["lorem", "ipsum", "dolor"];
213    /// let x: Value = v.into();
214    /// ```
215    fn from(value: [T; N]) -> Self {
216        Value::Array(value.into_iter().map(Into::into).collect())
217    }
218}
219
220impl<T> From<&[T]> for Value
221where
222    T: Into<Value> + Clone,
223{
224    /// Convert a [slice] to [`Value::Array`].
225    ///
226    /// [slice]: primitive@slice
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// # use tower_sesh::Value;
232    /// #
233    /// let v: &[&str] = &["lorem", "ipsum", "dolor"];
234    /// let x: Value = v.into();
235    /// ```
236    fn from(value: &[T]) -> Self {
237        Value::Array(value.iter().cloned().map(Into::into).collect())
238    }
239}
240
241impl<T> FromIterator<T> for Value
242where
243    T: Into<Value>,
244{
245    /// Create a [`Value::Array`] by collecting an iterator of array elements.
246    ///
247    /// # Examples
248    ///
249    /// ```
250    /// # use tower_sesh::Value;
251    /// #
252    /// let v = std::iter::repeat(42).take(5);
253    /// let x: Value = v.collect();
254    /// ```
255    ///
256    /// ```
257    /// # use tower_sesh::Value;
258    /// #
259    /// let v: Vec<_> = vec!["lorem", "ipsum", "dolor"];
260    /// let x: Value = v.into_iter().collect();
261    /// ```
262    ///
263    /// ```
264    /// # use tower_sesh::Value;
265    /// #
266    /// let x: Value = Value::from_iter(vec!["lorem", "ipsum", "dolor"]);
267    /// ```
268    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
269        Value::Array(iter.into_iter().map(Into::into).collect())
270    }
271}
272
273impl<K, V> FromIterator<(K, V)> for Value
274where
275    K: Into<String>,
276    V: Into<Value>,
277{
278    /// Create a [`Value::Map`] by collecting an iterator of key-value pairs.
279    ///
280    /// # Examples
281    ///
282    /// ```
283    /// # use tower_sesh::Value;
284    /// #
285    /// let v: Vec<_> = vec![("lorem", 40), ("ipsum", 2)];
286    /// let x: Value = v.into_iter().collect();
287    /// ```
288    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
289        Value::Map(
290            iter.into_iter()
291                .map(|(k, v)| (k.into(), v.into()))
292                .collect(),
293        )
294    }
295}
296
297impl From<Map<String, Value>> for Value {
298    /// Convert [`Map`] to [`Value::Map`].
299    ///
300    /// # Examples
301    ///
302    /// ```
303    /// use tower_sesh::{value::Map, Value};
304    ///
305    /// let mut m = Map::new();
306    /// m.insert("Lorem".to_owned(), "ipsum".into());
307    /// let x: Value = m.into();
308    /// ```
309    fn from(value: Map<String, Value>) -> Self {
310        Value::Map(value)
311    }
312}
313
314impl<T> From<Option<T>> for Value
315where
316    T: Into<Value>,
317{
318    /// Convert using `T`'s `Into<Value>` implementation if `Some`, or
319    /// [`Value::Null`] if `None`.
320    ///
321    /// # Examples
322    ///
323    /// ```
324    /// # use tower_sesh::Value;
325    /// #
326    /// let opt: Option<i32> = Some(3);
327    /// let x: Value = opt.into();
328    /// assert_eq!(x, Value::from(3));
329    ///
330    /// let opt: Option<i32> = None;
331    /// let x: Value = opt.into();
332    /// assert_eq!(x, Value::Null);
333    /// ```
334    fn from(opt: Option<T>) -> Self {
335        match opt {
336            None => Value::Null,
337            Some(value) => value.into(),
338        }
339    }
340}