toml_spanned_value/
spanned_value.rs

1//! Definition of a TOML spanned value
2
3use std::fmt;
4use std::mem::discriminant;
5use std::ops;
6use std::str::FromStr;
7
8use serde::de;
9use serde::ser;
10
11pub use toml::value::{Datetime, DatetimeParseError};
12use toml::Spanned;
13
14pub use crate::map::Map;
15
16/// Type representing a value with a span
17pub type SpannedValue = Spanned<ValueKind>;
18
19/// Representation of a TOML value.
20#[derive(PartialEq, Clone, Debug)]
21pub enum ValueKind {
22    /// Represents a TOML string
23    String(String),
24    /// Represents a TOML integer
25    Integer(i64),
26    /// Represents a TOML float
27    Float(f64),
28    /// Represents a TOML boolean
29    Boolean(bool),
30    /// Represents a TOML datetime
31    Datetime(Datetime),
32    /// Represents a TOML array
33    Array(Array),
34    /// Represents a TOML table
35    Table(Table),
36}
37
38/// Type representing a TOML array, payload of the `ValueKind::Array` variant
39pub type Array = Vec<SpannedValue>;
40
41/// Type representing a TOML table, payload of the `ValueKind::Table` variant.
42/// By default it is backed by a BTreeMap, enable the `preserve_order` feature
43/// to use a LinkedHashMap instead.
44pub type Table = Map<Spanned<String>, SpannedValue>;
45
46impl ValueKind {
47    /* /// Interpret a `toml::ValueKind` as an instance of type `T`.
48    ///
49    /// This conversion can fail if the structure of the `ValueKind` does not match the
50    /// structure expected by `T`, for example if `T` is a struct type but the
51    /// `ValueKind` contains something other than a TOML table. It can also fail if the
52    /// structure is correct but `T`'s implementation of `Deserialize` decides that
53    /// something is wrong with the data, for example required struct fields are
54    /// missing from the TOML map or some number is too big to fit in the expected
55    /// primitive type.
56    pub fn try_into<'de, T>(self) -> Result<T, crate::de::Error>
57    where
58        T: de::Deserialize<'de>,
59    {
60        de::Deserialize::deserialize(self)
61    }*/
62
63    /// Index into a TOML array or map. A string index can be used to access a
64    /// value in a map, and a usize index can be used to access an element of an
65    /// array.
66    ///
67    /// Returns `None` if the type of `self` does not match the type of the
68    /// index, for example if the index is a string and `self` is an array or a
69    /// number. Also returns `None` if the given key does not exist in the map
70    /// or the given index is not within the bounds of the array.
71    pub fn get<I: Index>(&self, index: I) -> Option<&SpannedValue> {
72        index.index(self)
73    }
74
75    /// Mutably index into a TOML array or map. A string index can be used to
76    /// access a value in a map, and a usize index can be used to access an
77    /// element of an array.
78    ///
79    /// Returns `None` if the type of `self` does not match the type of the
80    /// index, for example if the index is a string and `self` is an array or a
81    /// number. Also returns `None` if the given key does not exist in the map
82    /// or the given index is not within the bounds of the array.
83    pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut SpannedValue> {
84        index.index_mut(self)
85    }
86
87    /// Extracts the integer value if it is an integer.
88    pub fn as_integer(&self) -> Option<i64> {
89        match *self {
90            ValueKind::Integer(i) => Some(i),
91            _ => None,
92        }
93    }
94
95    /// Tests whether this value is an integer.
96    pub fn is_integer(&self) -> bool {
97        self.as_integer().is_some()
98    }
99
100    /// Extracts the float value if it is a float.
101    pub fn as_float(&self) -> Option<f64> {
102        match *self {
103            ValueKind::Float(f) => Some(f),
104            _ => None,
105        }
106    }
107
108    /// Tests whether this value is a float.
109    pub fn is_float(&self) -> bool {
110        self.as_float().is_some()
111    }
112
113    /// Extracts the boolean value if it is a boolean.
114    pub fn as_bool(&self) -> Option<bool> {
115        match *self {
116            ValueKind::Boolean(b) => Some(b),
117            _ => None,
118        }
119    }
120
121    /// Tests whether this value is a boolean.
122    pub fn is_bool(&self) -> bool {
123        self.as_bool().is_some()
124    }
125
126    /// Extracts the string of this value if it is a string.
127    pub fn as_str(&self) -> Option<&str> {
128        match *self {
129            ValueKind::String(ref s) => Some(&**s),
130            _ => None,
131        }
132    }
133
134    /// Tests if this value is a string.
135    pub fn is_str(&self) -> bool {
136        self.as_str().is_some()
137    }
138
139    /// Extracts the datetime value if it is a datetime.
140    ///
141    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
142    /// example date is:
143    ///
144    /// ```notrust
145    /// 1979-05-27T07:32:00Z
146    /// ```
147    pub fn as_datetime(&self) -> Option<&Datetime> {
148        match *self {
149            ValueKind::Datetime(ref s) => Some(s),
150            _ => None,
151        }
152    }
153
154    /// Tests whether this value is a datetime.
155    pub fn is_datetime(&self) -> bool {
156        self.as_datetime().is_some()
157    }
158
159    /// Extracts the array value if it is an array.
160    pub fn as_array(&self) -> Option<&Vec<SpannedValue>> {
161        match *self {
162            ValueKind::Array(ref s) => Some(s),
163            _ => None,
164        }
165    }
166
167    /// Extracts the array value if it is an array.
168    pub fn as_array_mut(&mut self) -> Option<&mut Vec<SpannedValue>> {
169        match *self {
170            ValueKind::Array(ref mut s) => Some(s),
171            _ => None,
172        }
173    }
174
175    /// Tests whether this value is an array.
176    pub fn is_array(&self) -> bool {
177        self.as_array().is_some()
178    }
179
180    /// Extracts the table value if it is a table.
181    pub fn as_table(&self) -> Option<&Table> {
182        match *self {
183            ValueKind::Table(ref s) => Some(s),
184            _ => None,
185        }
186    }
187
188    /// Extracts the table value if it is a table.
189    pub fn as_table_mut(&mut self) -> Option<&mut Table> {
190        match *self {
191            ValueKind::Table(ref mut s) => Some(s),
192            _ => None,
193        }
194    }
195
196    /// Tests whether this value is a table.
197    pub fn is_table(&self) -> bool {
198        self.as_table().is_some()
199    }
200
201    /// Tests whether this and another value have the same type.
202    pub fn same_type(&self, other: &ValueKind) -> bool {
203        discriminant(self) == discriminant(other)
204    }
205
206    /// Returns a human-readable representation of the type of this value.
207    pub fn type_str(&self) -> &'static str {
208        match *self {
209            ValueKind::String(..) => "string",
210            ValueKind::Integer(..) => "integer",
211            ValueKind::Float(..) => "float",
212            ValueKind::Boolean(..) => "boolean",
213            ValueKind::Datetime(..) => "datetime",
214            ValueKind::Array(..) => "array",
215            ValueKind::Table(..) => "table",
216        }
217    }
218}
219
220impl<I> ops::Index<I> for ValueKind
221where
222    I: Index,
223{
224    type Output = SpannedValue;
225
226    fn index(&self, index: I) -> &SpannedValue {
227        self.get(index).expect("index not found")
228    }
229}
230
231impl<I> ops::IndexMut<I> for ValueKind
232where
233    I: Index,
234{
235    fn index_mut(&mut self, index: I) -> &mut SpannedValue {
236        self.get_mut(index).expect("index not found")
237    }
238}
239
240impl<'a> From<&'a str> for ValueKind {
241    #[inline]
242    fn from(val: &'a str) -> ValueKind {
243        ValueKind::String(val.to_string())
244    }
245}
246
247impl<V: Into<SpannedValue>> From<Vec<V>> for ValueKind {
248    fn from(val: Vec<V>) -> ValueKind {
249        ValueKind::Array(val.into_iter().map(|v| v.into()).collect())
250    }
251}
252
253macro_rules! impl_into_value {
254    ($variant:ident : $T:ty) => {
255        impl From<$T> for ValueKind {
256            #[inline]
257            fn from(val: $T) -> ValueKind {
258                ValueKind::$variant(val.into())
259            }
260        }
261    };
262}
263
264impl_into_value!(String: String);
265impl_into_value!(Integer: i64);
266impl_into_value!(Integer: i32);
267impl_into_value!(Integer: i8);
268impl_into_value!(Integer: u8);
269impl_into_value!(Integer: u32);
270impl_into_value!(Float: f64);
271impl_into_value!(Float: f32);
272impl_into_value!(Boolean: bool);
273impl_into_value!(Datetime: Datetime);
274impl_into_value!(Table: Table);
275
276/// Types that can be used to index a `toml::ValueKind`
277///
278/// Currently this is implemented for `usize` to index arrays and `str` to index
279/// tables.
280///
281/// This trait is sealed and not intended for implementation outside of the
282/// `toml` crate.
283pub trait Index: Sealed {
284    #[doc(hidden)]
285    fn index<'a>(&self, val: &'a ValueKind) -> Option<&'a SpannedValue>;
286    #[doc(hidden)]
287    fn index_mut<'a>(&self, val: &'a mut ValueKind) -> Option<&'a mut SpannedValue>;
288}
289
290/// An implementation detail that should not be implemented, this will change in
291/// the future and break code otherwise.
292#[doc(hidden)]
293pub trait Sealed {}
294impl Sealed for usize {}
295impl Sealed for str {}
296impl Sealed for String {}
297impl<'a, T: Sealed + ?Sized> Sealed for &'a T {}
298
299impl Index for usize {
300    fn index<'a>(&self, val: &'a ValueKind) -> Option<&'a SpannedValue> {
301        match *val {
302            ValueKind::Array(ref a) => a.get(*self),
303            _ => None,
304        }
305    }
306
307    fn index_mut<'a>(&self, val: &'a mut ValueKind) -> Option<&'a mut SpannedValue> {
308        match *val {
309            ValueKind::Array(ref mut a) => a.get_mut(*self),
310            _ => None,
311        }
312    }
313}
314
315impl Index for str {
316    fn index<'a>(&self, val: &'a ValueKind) -> Option<&'a SpannedValue> {
317        match *val {
318            ValueKind::Table(ref a) => a.get(self),
319            _ => None,
320        }
321    }
322
323    fn index_mut<'a>(&self, val: &'a mut ValueKind) -> Option<&'a mut SpannedValue> {
324        match *val {
325            ValueKind::Table(ref mut a) => a.get_mut(self),
326            _ => None,
327        }
328    }
329}
330
331impl Index for String {
332    fn index<'a>(&self, val: &'a ValueKind) -> Option<&'a SpannedValue> {
333        self[..].index(val)
334    }
335
336    fn index_mut<'a>(&self, val: &'a mut ValueKind) -> Option<&'a mut SpannedValue> {
337        self[..].index_mut(val)
338    }
339}
340
341impl<'s, T: ?Sized> Index for &'s T
342where
343    T: Index,
344{
345    fn index<'a>(&self, val: &'a ValueKind) -> Option<&'a SpannedValue> {
346        (**self).index(val)
347    }
348
349    fn index_mut<'a>(&self, val: &'a mut ValueKind) -> Option<&'a mut SpannedValue> {
350        (**self).index_mut(val)
351    }
352}
353
354impl fmt::Display for ValueKind {
355    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356        toml::ser::to_string(self)
357            .expect("Unable to represent value as string")
358            .fmt(f)
359    }
360}
361
362impl FromStr for ValueKind {
363    type Err = toml::de::Error;
364    fn from_str(s: &str) -> Result<ValueKind, Self::Err> {
365        toml::from_str(s)
366    }
367}
368
369impl ser::Serialize for ValueKind {
370    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
371    where
372        S: ser::Serializer,
373    {
374        use serde::ser::SerializeMap;
375
376        match *self {
377            ValueKind::String(ref s) => serializer.serialize_str(s),
378            ValueKind::Integer(i) => serializer.serialize_i64(i),
379            ValueKind::Float(f) => serializer.serialize_f64(f),
380            ValueKind::Boolean(b) => serializer.serialize_bool(b),
381            ValueKind::Datetime(ref s) => s.serialize(serializer),
382            ValueKind::Array(ref a) => a.serialize(serializer),
383            ValueKind::Table(ref t) => {
384                let mut map = serializer.serialize_map(Some(t.len()))?;
385                // Be sure to visit non-tables first (and also non
386                // array-of-tables) as all keys must be emitted first.
387                for (k, v) in t {
388                    if !v.get_ref().is_table() && !v.get_ref().is_array()
389                        || (v
390                            .get_ref()
391                            .as_array()
392                            .map(|a| !a.iter().any(|v| v.get_ref().is_table()))
393                            .unwrap_or(false))
394                    {
395                        map.serialize_entry(k, v)?;
396                    }
397                }
398                for (k, v) in t {
399                    if v.get_ref()
400                        .as_array()
401                        .map(|a| a.iter().any(|v| v.get_ref().is_table()))
402                        .unwrap_or(false)
403                    {
404                        map.serialize_entry(k, v)?;
405                    }
406                }
407                for (k, v) in t {
408                    if v.get_ref().is_table() {
409                        map.serialize_entry(k, v)?;
410                    }
411                }
412                map.end()
413            }
414        }
415    }
416}
417
418impl<'de> de::Deserialize<'de> for ValueKind {
419    fn deserialize<D>(deserializer: D) -> Result<ValueKind, D::Error>
420    where
421        D: de::Deserializer<'de>,
422    {
423        struct ValueKindVisitor;
424
425        impl<'de> de::Visitor<'de> for ValueKindVisitor {
426            type Value = ValueKind;
427
428            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
429                formatter.write_str("any valid TOML value")
430            }
431
432            fn visit_bool<E>(self, value: bool) -> Result<ValueKind, E> {
433                Ok(ValueKind::Boolean(value))
434            }
435
436            fn visit_i64<E>(self, value: i64) -> Result<ValueKind, E> {
437                Ok(ValueKind::Integer(value))
438            }
439
440            fn visit_u64<E: de::Error>(self, value: u64) -> Result<ValueKind, E> {
441                if value <= i64::max_value() as u64 {
442                    Ok(ValueKind::Integer(value as i64))
443                } else {
444                    Err(de::Error::custom("u64 value was too large"))
445                }
446            }
447
448            fn visit_u32<E>(self, value: u32) -> Result<ValueKind, E> {
449                Ok(ValueKind::Integer(value.into()))
450            }
451
452            fn visit_i32<E>(self, value: i32) -> Result<ValueKind, E> {
453                Ok(ValueKind::Integer(value.into()))
454            }
455
456            fn visit_f64<E>(self, value: f64) -> Result<ValueKind, E> {
457                Ok(ValueKind::Float(value))
458            }
459
460            fn visit_str<E>(self, value: &str) -> Result<ValueKind, E> {
461                Ok(ValueKind::String(value.into()))
462            }
463
464            fn visit_string<E>(self, value: String) -> Result<ValueKind, E> {
465                Ok(ValueKind::String(value))
466            }
467
468            fn visit_some<D>(self, deserializer: D) -> Result<ValueKind, D::Error>
469            where
470                D: de::Deserializer<'de>,
471            {
472                de::Deserialize::deserialize(deserializer)
473            }
474
475            fn visit_seq<V>(self, mut visitor: V) -> Result<ValueKind, V::Error>
476            where
477                V: de::SeqAccess<'de>,
478            {
479                let mut vec = Vec::new();
480                while let Some(elem) = visitor.next_element()? {
481                    vec.push(elem);
482                }
483                Ok(ValueKind::Array(vec))
484            }
485
486            fn visit_map<V>(self, mut visitor: V) -> Result<ValueKind, V::Error>
487            where
488                V: de::MapAccess<'de>,
489            {
490                let key = visitor.next_key_seed(DatetimeOrTable)?;
491                let key = match key {
492                    Some(Some(key)) => key,
493                    Some(None) => {
494                        let date: DatetimeFromString = visitor.next_value()?;
495                        return Ok(ValueKind::Datetime(date.value));
496                    }
497                    None => return Ok(ValueKind::Table(Map::new())),
498                };
499                let mut map = Map::new();
500                map.insert(key, visitor.next_value()?);
501                while let Some(key) = visitor.next_key()? {
502                    if map.contains_key(&key) {
503                        let key: Spanned<String> = key;
504                        let msg = format!("duplicate key: `{}`", key.get_ref());
505                        return Err(de::Error::custom(msg));
506                    }
507                    map.insert(key, visitor.next_value()?);
508                }
509                Ok(ValueKind::Table(map))
510            }
511        }
512
513        deserializer.deserialize_any(ValueKindVisitor)
514    }
515}
516
517struct DatetimeFromString {
518    pub value: Datetime,
519}
520
521impl<'de> de::Deserialize<'de> for DatetimeFromString {
522    fn deserialize<D>(deserializer: D) -> Result<DatetimeFromString, D::Error>
523    where
524        D: de::Deserializer<'de>,
525    {
526        struct Visitor;
527
528        impl<'de> de::Visitor<'de> for Visitor {
529            type Value = DatetimeFromString;
530
531            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
532                formatter.write_str("string containing a datetime")
533            }
534
535            fn visit_str<E>(self, s: &str) -> Result<DatetimeFromString, E>
536            where
537                E: de::Error,
538            {
539                match s.parse() {
540                    Ok(date) => Ok(DatetimeFromString { value: date }),
541                    Err(e) => Err(de::Error::custom(e)),
542                }
543            }
544        }
545
546        deserializer.deserialize_str(Visitor)
547    }
548}
549
550#[derive(Debug)]
551struct OptError<E: de::Error>(Option<E>);
552
553impl<E: de::Error> std::error::Error for OptError<E> {}
554
555impl<E: de::Error> core::fmt::Display for OptError<E> {
556    fn fmt(&self, _fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
557        // The error is never meant to be displayed.
558        // Our code is expected to unwrap the error before
559        // it is propagated to places that may display it.
560        unreachable!()
561    }
562}
563
564impl<E: de::Error> de::Error for OptError<E> {
565    fn custom<T: core::fmt::Display>(msg: T) -> Self {
566        Self(Some(<E as de::Error>::custom(msg)))
567    }
568}
569
570struct LayerDeserializer<'de, D: de::Deserializer<'de>>(D, std::marker::PhantomData<&'de()>);
571
572impl<'de, D: de::Deserializer<'de>> de::Deserializer<'de> for LayerDeserializer<'de, D> {
573    type Error = OptError<D::Error>;
574    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
575    where
576        V: de::Visitor<'de>
577    {
578        self.0.deserialize_any(visitor).map_err(|e| OptError(Some(e)))
579    }
580    fn deserialize_struct<V>(
581        self,
582        name: &'static str,
583        fields: &'static [&'static str],
584        visitor: V
585    ) -> Result<V::Value, Self::Error>
586    where
587        V: de::Visitor<'de>
588    {
589        let wrapped_visitor = DatetimeOrTableWrapper(visitor);
590        match self.0.deserialize_struct(name, fields, wrapped_visitor) {
591            Ok(Some(v)) => Ok(v),
592            Ok(None) => Err(OptError(None)),
593            Err(v) => Err(OptError(Some(v))),
594        }
595    }
596    serde::forward_to_deserialize_any! {
597        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
598        bytes byte_buf option unit unit_struct newtype_struct seq tuple
599        tuple_struct map enum identifier ignored_any
600    }
601}
602
603struct DatetimeOrTable;
604
605impl<'de> de::DeserializeSeed<'de> for DatetimeOrTable {
606    type Value = Option<Spanned<String>>;
607
608    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
609    where
610        D: de::Deserializer<'de>,
611    {
612        let deserializer = LayerDeserializer(deserializer, std::marker::PhantomData);
613        let res = <Spanned::<String> as de::Deserialize<'_>>::deserialize(deserializer);
614        match res {
615            Ok(v) => Ok(Some(v)),
616            Err(OptError(None)) => Ok(None),
617            Err(OptError(Some(e))) => Err(e),
618        }
619    }
620}
621
622struct DatetimeOrTableWrapper<V>(V);
623
624impl<'de, V: de::Visitor<'de>> de::Visitor<'de> for DatetimeOrTableWrapper<V> {
625    type Value = Option<V::Value>;
626
627    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
628        formatter.write_str("a string key")
629    }
630
631    fn visit_map<W>(self, visitor: W) -> Result<Self::Value, W::Error>
632    where
633        W: de::MapAccess<'de>,
634    {
635        let key = self.0.visit_map(visitor)?;
636        Ok(Some(key))
637    }
638
639    fn visit_str<E>(self, _s: &str) -> Result<Self::Value, E>
640    where
641        E: de::Error,
642    {
643        //assert_eq!(s, toml::datetime::FIELD);
644        Ok(None)
645    }
646
647    fn visit_string<E>(self, _s: String) -> Result<Self::Value, E>
648    where
649        E: de::Error,
650    {
651        //assert_eq!(s, toml::datetime::FIELD);
652        Ok(None)
653    }
654}