diff options
Diffstat (limited to 'vendor/toml_edit/src/de/mod.rs')
-rw-r--r-- | vendor/toml_edit/src/de/mod.rs | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/vendor/toml_edit/src/de/mod.rs b/vendor/toml_edit/src/de/mod.rs new file mode 100644 index 000000000..09ea12096 --- /dev/null +++ b/vendor/toml_edit/src/de/mod.rs @@ -0,0 +1,289 @@ +//! Deserializing TOML into Rust structures. +//! +//! This module contains all the Serde support for deserializing TOML documents into Rust structures. + +use serde::de::DeserializeOwned; + +mod array; +mod datetime; +mod key; +mod spanned; +mod table; +mod table_enum; +mod value; + +use array::ArrayDeserializer; +use datetime::DatetimeDeserializer; +use key::KeyDeserializer; +use spanned::SpannedDeserializer; +use table::TableMapAccess; +use table_enum::TableEnumDeserializer; + +pub use value::ValueDeserializer; + +/// Errors that can occur when deserializing a type. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Error { + inner: crate::TomlError, +} + +impl Error { + pub(crate) fn custom<T>(msg: T, span: Option<std::ops::Range<usize>>) -> Self + where + T: std::fmt::Display, + { + Error { + inner: crate::TomlError::custom(msg.to_string(), span), + } + } + + /// Add key while unwinding + pub fn add_key(&mut self, key: String) { + self.inner.add_key(key) + } + + /// What went wrong + pub fn message(&self) -> &str { + self.inner.message() + } + + /// The start/end index into the original document where the error occurred + pub fn span(&self) -> Option<std::ops::Range<usize>> { + self.inner.span() + } + + pub(crate) fn set_span(&mut self, span: Option<std::ops::Range<usize>>) { + self.inner.set_span(span); + } +} + +impl serde::de::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::custom(msg, None) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + self.inner.fmt(f) + } +} + +impl From<crate::TomlError> for Error { + fn from(e: crate::TomlError) -> Error { + Self { inner: e } + } +} + +impl From<Error> for crate::TomlError { + fn from(e: Error) -> crate::TomlError { + e.inner + } +} + +impl std::error::Error for Error {} + +/// Convert a value into `T`. +pub fn from_str<T>(s: &'_ str) -> Result<T, Error> +where + T: DeserializeOwned, +{ + let de = s.parse::<Deserializer>()?; + T::deserialize(de) +} + +/// Convert a value into `T`. +pub fn from_slice<T>(s: &'_ [u8]) -> Result<T, Error> +where + T: DeserializeOwned, +{ + let s = std::str::from_utf8(s).map_err(|e| Error::custom(e, None))?; + from_str(s) +} + +/// Convert a document into `T`. +pub fn from_document<T>(d: crate::Document) -> Result<T, Error> +where + T: DeserializeOwned, +{ + let deserializer = Deserializer::new(d); + T::deserialize(deserializer) +} + +/// Deserialization for TOML [documents][crate::Document]. +pub struct Deserializer { + input: crate::Document, +} + +impl Deserializer { + /// Deserialization implementation for TOML. + pub fn new(input: crate::Document) -> Self { + Self { input } + } +} + +impl std::str::FromStr for Deserializer { + type Err = Error; + + /// Parses a document from a &str + fn from_str(s: &str) -> Result<Self, Self::Err> { + let d = crate::parser::parse_document(s).map_err(Error::from)?; + Ok(Self::new(d)) + } +} + +// Note: this is wrapped by `toml::de::Deserializer` and any trait methods +// implemented here need to be wrapped there +impl<'de> serde::Deserializer<'de> for Deserializer { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_any(visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + // `None` is interpreted as a missing field so be sure to implement `Some` + // as a present field. + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_option(visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_newtype_struct(name, visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_struct(name, fields, visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + // Called when the type to deserialize is an enum, as opposed to a field in the type. + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_enum(name, variants, visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + serde::forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq + bytes byte_buf map unit + ignored_any unit_struct tuple_struct tuple identifier + } +} + +impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for Deserializer { + type Deserializer = Deserializer; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + +impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for crate::Document { + type Deserializer = Deserializer; + + fn into_deserializer(self) -> Self::Deserializer { + Deserializer::new(self) + } +} + +pub(crate) fn validate_struct_keys( + table: &crate::table::KeyValuePairs, + fields: &'static [&'static str], +) -> Result<(), Error> { + let extra_fields = table + .iter() + .filter_map(|(key, val)| { + if !fields.contains(&key.as_str()) { + Some(val.clone()) + } else { + None + } + }) + .collect::<Vec<_>>(); + + if extra_fields.is_empty() { + Ok(()) + } else { + Err(Error::custom( + format!( + "unexpected keys in table: {}, available keys: {}", + extra_fields + .iter() + .map(|k| k.key.get()) + .collect::<Vec<_>>() + .join(", "), + fields.join(", "), + ), + extra_fields[0].key.span(), + )) + } +} |