path_value/value/
mod.rs

1use std::collections::HashMap;
2use std::convert::{TryFrom, TryInto};
3use std::fmt;
4use std::fmt::Display;
5
6use num_bigint::BigInt;
7use num_traits::{ToPrimitive, Zero};
8use serde::Serialize;
9
10use crate::error::{Error, Result, Unexpected};
11use crate::path::{Path, PathNode};
12use crate::value::ser::ValueSerializer;
13
14mod de;
15mod ser;
16
17#[derive(Debug, Clone, PartialEq)]
18pub enum Value {
19    Nil,
20    Integer(BigInt),
21    Float(f64),
22    Boolean(bool),
23    String(String),
24    Map(HashMap<String, Value>),
25    Array(Vec<Value>),
26}
27
28impl Default for Value {
29    fn default() -> Self {
30        Value::Nil
31    }
32}
33
34impl Display for Value {
35    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36        match *self {
37            Value::String(ref value) => write!(f, "{}", value),
38            Value::Boolean(value) => write!(f, "{}", value),
39            Value::Integer(ref value) => write!(f, "{}", value),
40            Value::Float(value) => write!(f, "{}", value),
41            Value::Nil => write!(f, "nil"),
42            Value::Map(ref map) => write!(f, "{:?}", map),
43            Value::Array(ref array) => write!(f, "{:?}", array),
44        }
45    }
46}
47
48impl<T> From<Option<T>> for Value
49where
50    T: Into<Value>,
51{
52    fn from(value: Option<T>) -> Self {
53        match value {
54            Some(value) => value.into(),
55            None => Value::Nil,
56        }
57    }
58}
59
60impl From<String> for Value {
61    fn from(value: String) -> Self {
62        Value::String(value)
63    }
64}
65
66impl<'a> From<&'a str> for Value {
67    fn from(value: &'a str) -> Self {
68        Value::String(value.into())
69    }
70}
71
72macro_rules! impl_from_int_to_value {
73    ($ty:ty) => {
74        impl From<$ty> for Value {
75            fn from(value: $ty) -> Self {
76                Value::Integer(BigInt::from(value))
77            }
78        }
79    };
80}
81
82impl_from_int_to_value!(i8);
83impl_from_int_to_value!(i16);
84impl_from_int_to_value!(i32);
85impl_from_int_to_value!(i64);
86impl_from_int_to_value!(isize);
87
88impl_from_int_to_value!(u8);
89impl_from_int_to_value!(u16);
90impl_from_int_to_value!(u32);
91impl_from_int_to_value!(u64);
92impl_from_int_to_value!(usize);
93
94impl From<f64> for Value {
95    fn from(value: f64) -> Self {
96        Value::Float(value)
97    }
98}
99
100impl From<f32> for Value {
101    fn from(value: f32) -> Self {
102        Value::Float(value as f64)
103    }
104}
105
106impl From<bool> for Value {
107    fn from(value: bool) -> Self {
108        Value::Boolean(value)
109    }
110}
111
112impl<T> From<HashMap<String, T>> for Value
113where
114    T: Into<Value>,
115{
116    fn from(values: HashMap<String, T>) -> Self {
117        let mut r = HashMap::new();
118
119        for (k, v) in values {
120            r.insert(k.clone(), v.into());
121        }
122
123        Value::Map(r)
124    }
125}
126
127impl<T> From<Vec<T>> for Value
128where
129    T: Into<Value>,
130{
131    fn from(values: Vec<T>) -> Self {
132        let mut l = Vec::new();
133
134        for v in values {
135            l.push(v.into());
136        }
137
138        Value::Array(l)
139    }
140}
141
142impl TryFrom<Value> for bool {
143    type Error = Error;
144
145    fn try_from(value: Value) -> Result<Self> {
146        match value {
147            Value::Boolean(value) => Ok(value),
148            Value::Integer(value) => Ok(value.ne(&Zero::zero())),
149            Value::Float(value) => Ok(value != 0.0),
150
151            Value::String(ref value) => {
152                match value.to_lowercase().as_ref() {
153                    "1" | "true" | "on" | "yes" => Ok(true),
154                    "0" | "false" | "off" | "no" => Ok(false),
155
156                    // Unexpected string value
157                    s => Err(Error::invalid_type(Unexpected::Str(s.into()), "a boolean")),
158                }
159            }
160
161            // Unexpected type
162            Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "a boolean")),
163            Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a boolean")),
164            Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a boolean")),
165        }
166    }
167}
168
169macro_rules! impl_try_from_value_to_int {
170    ($ty:ty, $ident:ident) => {
171        impl TryFrom<Value> for $ty {
172            type Error = Error;
173
174            fn try_from(value: Value) -> Result<Self> {
175                match value {
176                    Value::Integer(value) => match value.$ident() {
177                        Some(v) => Ok(v),
178                        None => Err(Error::too_large(value)),
179                    },
180                    Value::String(ref s) => {
181                        match s.to_lowercase().as_ref() {
182                            "true" | "on" | "yes" => Ok(1),
183                            "false" | "off" | "no" => Ok(0),
184                            _ => {
185                                s.parse().map_err(|_| {
186                                    // Unexpected string
187                                    Error::invalid_type(Unexpected::Str(s.clone()), "an integer")
188                                })
189                            }
190                        }
191                    }
192                    Value::Boolean(value) => Ok(if value { 1 } else { 0 }),
193                    Value::Float(value) => Ok(value.round() as $ty),
194
195                    // Unexpected type
196                    Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "an integer")),
197                    Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "an integer")),
198                    Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "an integer")),
199                }
200            }
201        }
202    };
203}
204
205impl_try_from_value_to_int!(i8, to_i8);
206impl_try_from_value_to_int!(i16, to_i16);
207impl_try_from_value_to_int!(i32, to_i32);
208impl_try_from_value_to_int!(i64, to_i64);
209impl_try_from_value_to_int!(isize, to_isize);
210impl_try_from_value_to_int!(u8, to_u8);
211impl_try_from_value_to_int!(u16, to_u16);
212impl_try_from_value_to_int!(u32, to_u32);
213impl_try_from_value_to_int!(u64, to_u64);
214impl_try_from_value_to_int!(usize, to_usize);
215
216macro_rules! impl_try_from_value_to_float {
217    ($ty:ty, $ident:ident) => {
218        impl TryFrom<Value> for $ty {
219            type Error = Error;
220
221            fn try_from(value: Value) -> Result<Self> {
222                match value {
223                    Value::Float(value) => Ok(value as $ty),
224
225                    Value::String(ref s) => {
226                        match s.to_lowercase().as_ref() {
227                            "true" | "on" | "yes" => Ok(1.0),
228                            "false" | "off" | "no" => Ok(0.0),
229                            _ => {
230                                s.parse().map_err(|_| {
231                                    // Unexpected string
232                                    Error::invalid_type(
233                                        Unexpected::Str(s.clone()),
234                                        "a floating point",
235                                    )
236                                })
237                            }
238                        }
239                    }
240
241                    Value::Integer(value) => match value.$ident() {
242                        Some(v) => Ok(v),
243                        None => Err(Error::too_large(value)),
244                    },
245                    Value::Boolean(value) => Ok(if value { 1.0 } else { 0.0 }),
246
247                    // Unexpected type
248                    Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "a floating point")),
249                    Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a floating point")),
250                    Value::Array(_) => {
251                        Err(Error::invalid_type(Unexpected::Array, "a floating point"))
252                    }
253                }
254            }
255        }
256    };
257}
258
259impl_try_from_value_to_float!(f32, to_f32);
260impl_try_from_value_to_float!(f64, to_f64);
261
262impl TryFrom<Value> for String {
263    type Error = Error;
264
265    fn try_from(value: Value) -> Result<Self> {
266        match value {
267            Value::String(value) => Ok(value),
268
269            Value::Boolean(value) => Ok(value.to_string()),
270            Value::Integer(value) => Ok(value.to_string()),
271            Value::Float(value) => Ok(value.to_string()),
272
273            // Cannot convert
274            Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "a string")),
275            Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a string")),
276            Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a string")),
277        }
278    }
279}
280
281impl TryFrom<Value> for Vec<Value> {
282    type Error = Error;
283
284    fn try_from(value: Value) -> Result<Self> {
285        match value {
286            Value::Array(value) => Ok(value),
287
288            // Cannot convert
289            Value::Float(value) => Err(Error::invalid_type(Unexpected::Float(value), "an array")),
290            Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "an array")),
291            Value::Integer(value) => {
292                Err(Error::invalid_type(Unexpected::Integer(value), "an array"))
293            }
294            Value::Boolean(value) => Err(Error::invalid_type(Unexpected::Bool(value), "an array")),
295            Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "an array")),
296            Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "an array")),
297        }
298    }
299}
300
301impl TryFrom<Value> for HashMap<String, Value> {
302    type Error = Error;
303
304    fn try_from(value: Value) -> Result<Self> {
305        match value {
306            Value::Map(value) => Ok(value),
307
308            // Cannot convert
309            Value::Float(value) => Err(Error::invalid_type(Unexpected::Float(value), "a map")),
310            Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a map")),
311            Value::Integer(value) => Err(Error::invalid_type(Unexpected::Integer(value), "a map")),
312            Value::Boolean(value) => Err(Error::invalid_type(Unexpected::Bool(value), "a map")),
313            Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "a map")),
314            Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a map")),
315        }
316    }
317}
318
319impl TryFrom<Value> for () {
320    type Error = Error;
321
322    fn try_from(value: Value) -> Result<Self> {
323        Ok(())
324    }
325}
326
327impl Value {
328    pub fn merge(&mut self, source: Value) -> Result<()> {
329        match self {
330            Value::Boolean(v_t) => match source {
331                Value::Boolean(v_s) => {
332                    *v_t = v_s;
333                    Ok(())
334                }
335
336                // Cannot convert
337                Value::Float(value) => Err(Error::invalid_type(Unexpected::Float(value), "a bool")),
338                Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a bool")),
339                Value::Integer(value) => {
340                    Err(Error::invalid_type(Unexpected::Integer(value), "a bool"))
341                }
342                Value::Nil => Ok(()),
343                Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a bool")),
344                Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a bool")),
345            },
346            Value::Integer(v_t) => match source {
347                Value::Integer(v_s) => {
348                    *v_t = v_s;
349                    Ok(())
350                }
351
352                // Cannot convert
353                Value::Float(value) => {
354                    Err(Error::invalid_type(Unexpected::Float(value), "a integer"))
355                }
356                Value::String(value) => {
357                    Err(Error::invalid_type(Unexpected::Str(value), "a integer"))
358                }
359                Value::Boolean(value) => {
360                    Err(Error::invalid_type(Unexpected::Bool(value), "a integer"))
361                }
362                Value::Nil => Ok(()),
363                Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a integer")),
364                Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a integer")),
365            },
366            Value::Float(v_t) => match source {
367                Value::Float(v_s) => {
368                    *v_t = v_s;
369                    Ok(())
370                }
371
372                // Cannot convert
373                Value::Integer(value) => {
374                    Err(Error::invalid_type(Unexpected::Integer(value), "a float"))
375                }
376                Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a float")),
377                Value::Boolean(value) => {
378                    Err(Error::invalid_type(Unexpected::Bool(value), "a float"))
379                }
380                Value::Nil => Ok(()),
381                Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a float")),
382                Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a float")),
383            },
384            Value::String(v_t) => match source {
385                Value::String(v_s) => {
386                    *v_t = v_s;
387                    Ok(())
388                }
389
390                // Cannot convert
391                Value::Integer(value) => {
392                    Err(Error::invalid_type(Unexpected::Integer(value), "a string"))
393                }
394                Value::Float(value) => {
395                    Err(Error::invalid_type(Unexpected::Float(value), "a string"))
396                }
397                Value::Boolean(value) => {
398                    Err(Error::invalid_type(Unexpected::Bool(value), "a string"))
399                }
400                Value::Nil => Ok(()),
401                Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a string")),
402                Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a string")),
403            },
404            Value::Nil => match source {
405                Value::Nil => Ok(()),
406                _ => {
407                    *self = source;
408                    Ok(())
409                }
410            },
411            Value::Map(v_t) => match source {
412                Value::Map(v_s) => {
413                    for (k, v) in v_s {
414                        match v_t.get_mut(&k) {
415                            Some(j) => Value::merge(j, v)?,
416                            None => {
417                                v_t.insert(k, v);
418                            }
419                        }
420                    }
421                    Ok(())
422                }
423                // Cannot convert
424                Value::Integer(value) => {
425                    Err(Error::invalid_type(Unexpected::Integer(value), "a map"))
426                }
427                Value::Float(value) => Err(Error::invalid_type(Unexpected::Float(value), "a map")),
428                Value::Boolean(value) => Err(Error::invalid_type(Unexpected::Bool(value), "a map")),
429                Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a map")),
430                Value::Nil => Ok(()),
431                Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a map")),
432            },
433            Value::Array(v_t) => match source {
434                Value::Array(v_s) => {
435                    for (index, v) in v_s.into_iter().enumerate() {
436                        match v_t.get_mut(index) {
437                            Some(j) => Value::merge(j, v)?,
438                            None => {
439                                v_t.push(v);
440                            }
441                        }
442                    }
443                    Ok(())
444                }
445                // Cannot convert
446                Value::Integer(value) => {
447                    Err(Error::invalid_type(Unexpected::Integer(value), "a array"))
448                }
449                Value::Float(value) => {
450                    Err(Error::invalid_type(Unexpected::Float(value), "a array"))
451                }
452                Value::Boolean(value) => {
453                    Err(Error::invalid_type(Unexpected::Bool(value), "a array"))
454                }
455                Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a array")),
456                Value::Nil => Ok(()),
457                Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a array")),
458            },
459        }
460    }
461
462    pub fn set<P, IntoValue, IntoErr>(
463        &mut self,
464        path: P,
465        input_value: IntoValue,
466    ) -> Result<Value, Error>
467    where
468        P: TryInto<Path, Error = IntoErr>,
469        IntoValue: Into<Value>,
470        IntoErr: Into<Error>,
471    {
472        let input_value = input_value.into();
473        let path = path.try_into().map_err(|err| err.into())?;
474        unsafe {
475            let mut parent = self as *mut Value;
476            let mut target = self as *mut Value;
477            let v = vec![1];
478            for sub_path in path.iter() {
479                match *sub_path {
480                    PathNode::Identifier(ref ident) => match &mut *parent {
481                        Value::Map(parent_map) => {
482                            target = parent_map.entry(ident.clone()).or_default();
483                            parent = target;
484                        }
485
486                        _ => {
487                            *parent = HashMap::<String, Value>::new().into();
488                            if let Value::Map(parent_map) = &mut *parent {
489                                target = parent_map.entry(ident.clone()).or_default();
490                                parent = target;
491                            } else {
492                                unreachable!()
493                            }
494                        }
495                    },
496                    PathNode::Index(index) => match &mut *parent {
497                        Value::Array(parent_array) => {
498                            target = Value::get_array_slot(parent_array, index);
499                            parent = target;
500                        }
501
502                        _ => {
503                            *parent = vec![Value::default()].into();
504                            if let Value::Array(parent_array) = &mut *parent {
505                                target = Value::get_array_slot(parent_array, index);
506                                parent = target;
507                            } else {
508                                unreachable!()
509                            }
510                        }
511                    },
512                }
513            }
514
515            let result = (*target).clone();
516            *target = input_value;
517            Ok(result)
518        }
519    }
520
521    pub fn get<T, P, IntoErr>(&self, path: P) -> Result<Option<T>, Error>
522    where
523        T: std::convert::TryFrom<Value, Error = IntoErr>,
524        P: TryInto<Path, Error = IntoErr>,
525        IntoErr: Into<Error>,
526    {
527        let path = path.try_into().map_err(|err| err.into())?;
528        let value = path
529            .iter()
530            .scan(self, |value, child_path| {
531                let result = match *child_path {
532                    PathNode::Identifier(ref id) => match **value {
533                        Value::Map(ref map) => map.get(id),
534                        _ => None,
535                    },
536
537                    PathNode::Index(index) => match **value {
538                        Value::Array(ref array) => {
539                            let index = Value::map_index(index, array.len());
540
541                            if index >= array.len() {
542                                None
543                            } else {
544                                Some(&array[index])
545                            }
546                        }
547                        _ => None,
548                    },
549                };
550                if let Some(v) = result {
551                    *value = v;
552                }
553                result
554            })
555            .last();
556        match value {
557            None => Ok(None),
558            Some(value) => Ok(Some(
559                Value::try_into(value.clone()).map_err(|err: IntoErr| err.into())?,
560            )),
561        }
562    }
563
564    fn map_index(index: isize, len: usize) -> usize {
565        if index >= 0 {
566            index as usize
567        } else {
568            len - (index.abs() as usize)
569        }
570    }
571
572    unsafe fn get_array_slot(array: &mut Vec<Value>, index: isize) -> *mut Value {
573        let index = Value::map_index(index, array.len());
574        match array.get_mut(index) {
575            Some(v) => v,
576            None => {
577                array.insert(index, Value::default());
578                match array.get_mut(index) {
579                    Some(v) => v,
580                    None => unreachable!(),
581                }
582            }
583        }
584    }
585}
586
587pub fn to_value<T>(from: T) -> Result<Value>
588where
589    T: Serialize,
590{
591    let mut serializer = ValueSerializer::default();
592    from.serialize(&mut serializer)?;
593    Ok(serializer.output)
594}