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}