diff options
Diffstat (limited to 'vendor/toml/src/de.rs')
-rw-r--r-- | vendor/toml/src/de.rs | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/vendor/toml/src/de.rs b/vendor/toml/src/de.rs new file mode 100644 index 000000000..9eb4c4188 --- /dev/null +++ b/vendor/toml/src/de.rs @@ -0,0 +1,322 @@ +//! Deserializing TOML into Rust structures. +//! +//! This module contains all the Serde support for deserializing TOML documents +//! into Rust structures. Note that some top-level functions here are also +//! provided at the top of the crate. + +/// Deserializes a string into a type. +/// +/// This function will attempt to interpret `s` as a TOML document and +/// deserialize `T` from the document. +/// +/// To deserializes TOML values, instead of documents, see [`ValueDeserializer`]. +/// +/// # Examples +/// +/// ``` +/// use serde::Deserialize; +/// +/// #[derive(Deserialize)] +/// struct Config { +/// title: String, +/// owner: Owner, +/// } +/// +/// #[derive(Deserialize)] +/// struct Owner { +/// name: String, +/// } +/// +/// let config: Config = toml::from_str(r#" +/// title = 'TOML Example' +/// +/// [owner] +/// name = 'Lisa' +/// "#).unwrap(); +/// +/// assert_eq!(config.title, "TOML Example"); +/// assert_eq!(config.owner.name, "Lisa"); +/// ``` +#[cfg(feature = "parse")] +pub fn from_str<T>(s: &'_ str) -> Result<T, Error> +where + T: serde::de::DeserializeOwned, +{ + T::deserialize(Deserializer::new(s)) +} + +/// Errors that can occur when deserializing a type. +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Error { + inner: crate::edit::de::Error, +} + +impl Error { + fn new(inner: crate::edit::de::Error) -> Self { + Self { inner } + } + + pub(crate) 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 + #[cfg(feature = "parse")] + pub fn span(&self) -> Option<std::ops::Range<usize>> { + self.inner.span() + } +} + +impl serde::de::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::new(crate::edit::de::Error::custom(msg)) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.inner.fmt(f) + } +} + +impl std::error::Error for Error {} + +/// Deserialization TOML document +/// +/// To deserializes TOML values, instead of documents, see [`ValueDeserializer`]. +#[cfg(feature = "parse")] +pub struct Deserializer<'a> { + input: &'a str, +} + +#[cfg(feature = "parse")] +impl<'a> Deserializer<'a> { + /// Deserialization implementation for TOML. + pub fn new(input: &'a str) -> Self { + Self { input } + } +} + +#[cfg(feature = "parse")] +impl<'de, 'a> serde::Deserializer<'de> for Deserializer<'a> { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner.deserialize_any(visitor).map_err(Error::new) + } + + // `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 inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner.deserialize_option(visitor).map_err(Error::new) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner + .deserialize_newtype_struct(name, visitor) + .map_err(Error::new) + } + + 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 inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner + .deserialize_struct(name, fields, visitor) + .map_err(Error::new) + } + + // 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 inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner + .deserialize_enum(name, variants, visitor) + .map_err(Error::new) + } + + 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 + } +} + +/// Deserialization TOML [value][crate::Value] +/// +/// # Example +/// +/// ``` +/// use serde::Deserialize; +/// +/// #[derive(Deserialize)] +/// struct Config { +/// title: String, +/// owner: Owner, +/// } +/// +/// #[derive(Deserialize)] +/// struct Owner { +/// name: String, +/// } +/// +/// let config = Config::deserialize(toml::de::ValueDeserializer::new( +/// r#"{ title = 'TOML Example', owner = { name = 'Lisa' } }"# +/// )).unwrap(); +/// +/// assert_eq!(config.title, "TOML Example"); +/// assert_eq!(config.owner.name, "Lisa"); +/// ``` +#[cfg(feature = "parse")] +pub struct ValueDeserializer<'a> { + input: &'a str, +} + +#[cfg(feature = "parse")] +impl<'a> ValueDeserializer<'a> { + /// Deserialization implementation for TOML. + pub fn new(input: &'a str) -> Self { + Self { input } + } +} + +#[cfg(feature = "parse")] +impl<'de, 'a> serde::Deserializer<'de> for ValueDeserializer<'a> { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner.deserialize_any(visitor).map_err(Error::new) + } + + // `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 inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner.deserialize_option(visitor).map_err(Error::new) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner + .deserialize_newtype_struct(name, visitor) + .map_err(Error::new) + } + + 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 inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner + .deserialize_struct(name, fields, visitor) + .map_err(Error::new) + } + + // 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 inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner + .deserialize_enum(name, variants, visitor) + .map_err(Error::new) + } + + 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 + } +} |