diff options
Diffstat (limited to 'vendor/toml/src')
-rw-r--r-- | vendor/toml/src/de.rs | 322 | ||||
-rw-r--r-- | vendor/toml/src/edit.rs | 91 | ||||
-rw-r--r-- | vendor/toml/src/fmt.rs | 60 | ||||
-rw-r--r-- | vendor/toml/src/lib.rs | 182 | ||||
-rw-r--r-- | vendor/toml/src/macros.rs | 460 | ||||
-rw-r--r-- | vendor/toml/src/map.rs | 595 | ||||
-rw-r--r-- | vendor/toml/src/ser.rs | 1087 | ||||
-rw-r--r-- | vendor/toml/src/table.rs | 114 | ||||
-rw-r--r-- | vendor/toml/src/value.rs | 1308 |
9 files changed, 4219 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 + } +} diff --git a/vendor/toml/src/edit.rs b/vendor/toml/src/edit.rs new file mode 100644 index 000000000..90fb284ca --- /dev/null +++ b/vendor/toml/src/edit.rs @@ -0,0 +1,91 @@ +#[cfg(feature = "parse")] +pub(crate) mod de { + pub(crate) use toml_edit::de::Error; +} + +#[cfg(not(feature = "parse"))] +pub(crate) mod de { + /// Errors that can occur when deserializing a type. + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct Error { + inner: String, + } + + impl Error { + /// Add key while unwinding + pub fn add_key(&mut self, _key: String) {} + + /// What went wrong + pub fn message(&self) -> &str { + self.inner.as_str() + } + } + + impl serde::de::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error { + inner: msg.to_string(), + } + } + } + + 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 {} +} + +#[cfg(feature = "display")] +pub(crate) mod ser { + pub(crate) use toml_edit::ser::Error; +} + +#[cfg(not(feature = "display"))] +pub(crate) mod ser { + #[derive(Debug, Clone, PartialEq, Eq)] + #[non_exhaustive] + pub(crate) enum Error { + UnsupportedType(Option<&'static str>), + UnsupportedNone, + KeyNotString, + Custom(String), + } + + impl Error { + pub(crate) fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::Custom(msg.to_string()) + } + } + + impl serde::ser::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Self::custom(msg) + } + } + + impl std::fmt::Display for Error { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::UnsupportedType(Some(t)) => write!(formatter, "unsupported {t} type"), + Self::UnsupportedType(None) => write!(formatter, "unsupported rust type"), + Self::UnsupportedNone => "unsupported None value".fmt(formatter), + Self::KeyNotString => "map key was not a string".fmt(formatter), + Self::Custom(s) => s.fmt(formatter), + } + } + } + + impl std::error::Error for Error {} +} diff --git a/vendor/toml/src/fmt.rs b/vendor/toml/src/fmt.rs new file mode 100644 index 000000000..0e96bf050 --- /dev/null +++ b/vendor/toml/src/fmt.rs @@ -0,0 +1,60 @@ +#[derive(Copy, Clone, Default)] +pub(crate) struct DocumentFormatter { + pub(crate) multiline_array: bool, +} + +impl toml_edit::visit_mut::VisitMut for DocumentFormatter { + fn visit_document_mut(&mut self, node: &mut toml_edit::Document) { + toml_edit::visit_mut::visit_document_mut(self, node); + } + + fn visit_item_mut(&mut self, node: &mut toml_edit::Item) { + let other = std::mem::take(node); + let other = match other.into_table().map(toml_edit::Item::Table) { + Ok(i) => i, + Err(i) => i, + }; + let other = match other + .into_array_of_tables() + .map(toml_edit::Item::ArrayOfTables) + { + Ok(i) => i, + Err(i) => i, + }; + *node = other; + + toml_edit::visit_mut::visit_item_mut(self, node); + } + + fn visit_table_mut(&mut self, node: &mut toml_edit::Table) { + node.decor_mut().clear(); + + // Empty tables could be semantically meaningful, so make sure they are not implicit + if !node.is_empty() { + node.set_implicit(true); + } + + toml_edit::visit_mut::visit_table_mut(self, node); + } + + fn visit_value_mut(&mut self, node: &mut toml_edit::Value) { + node.decor_mut().clear(); + + toml_edit::visit_mut::visit_value_mut(self, node); + } + + fn visit_array_mut(&mut self, node: &mut toml_edit::Array) { + toml_edit::visit_mut::visit_array_mut(self, node); + + if !self.multiline_array || (0..=1).contains(&node.len()) { + node.set_trailing(""); + node.set_trailing_comma(false); + } else { + for item in node.iter_mut() { + item.decor_mut().set_prefix("\n "); + } + node.set_trailing("\n"); + node.set_trailing_comma(true); + } + } +} diff --git a/vendor/toml/src/lib.rs b/vendor/toml/src/lib.rs new file mode 100644 index 000000000..61e6a4c75 --- /dev/null +++ b/vendor/toml/src/lib.rs @@ -0,0 +1,182 @@ +//! A [serde]-compatible [TOML]-parsing library +//! +//! TOML itself is a simple, ergonomic, and readable configuration format: +//! +//! ```toml +//! [package] +//! name = "toml" +//! version = "0.4.2" +//! authors = ["Alex Crichton <alex@alexcrichton.com>"] +//! +//! [dependencies] +//! serde = "1.0" +//! ``` +//! +//! The TOML format tends to be relatively common throughout the Rust community +//! for configuration, notably being used by [Cargo], Rust's package manager. +//! +//! ## TOML values +//! +//! A TOML document is represented with the [`Table`] type which maps `String` to the [`Value`] enum: +//! +//! ```rust +//! # use toml::value::{Datetime, Array, Table}; +//! pub enum Value { +//! String(String), +//! Integer(i64), +//! Float(f64), +//! Boolean(bool), +//! Datetime(Datetime), +//! Array(Array), +//! Table(Table), +//! } +//! ``` +//! +//! ## Parsing TOML +//! +//! The easiest way to parse a TOML document is via the [`Table`] type: +//! +#![cfg_attr(not(feature = "parse"), doc = " ```ignore")] +#![cfg_attr(feature = "parse", doc = " ```")] +//! use toml::Table; +//! +//! let value = "foo = 'bar'".parse::<Table>().unwrap(); +//! +//! assert_eq!(value["foo"].as_str(), Some("bar")); +//! ``` +//! +//! The [`Table`] type implements a number of convenience methods and +//! traits; the example above uses [`FromStr`] to parse a [`str`] into a +//! [`Table`]. +//! +//! ## Deserialization and Serialization +//! +//! This crate supports [`serde`] 1.0 with a number of +//! implementations of the `Deserialize`, `Serialize`, `Deserializer`, and +//! `Serializer` traits. Namely, you'll find: +//! +//! * `Deserialize for Table` +//! * `Serialize for Table` +//! * `Deserialize for Value` +//! * `Serialize for Value` +//! * `Deserialize for Datetime` +//! * `Serialize for Datetime` +//! * `Deserializer for de::Deserializer` +//! * `Serializer for ser::Serializer` +//! * `Deserializer for Table` +//! * `Deserializer for Value` +//! +//! This means that you can use Serde to deserialize/serialize the +//! [`Table`] type as well as [`Value`] and [`Datetime`] type in this crate. You can also +//! use the [`Deserializer`], [`Serializer`], or [`Table`] type itself to act as +//! a deserializer/serializer for arbitrary types. +//! +//! An example of deserializing with TOML is: +//! +#![cfg_attr(not(feature = "parse"), doc = " ```ignore")] +#![cfg_attr(feature = "parse", doc = " ```")] +//! use serde::Deserialize; +//! +//! #[derive(Deserialize)] +//! struct Config { +//! ip: String, +//! port: Option<u16>, +//! keys: Keys, +//! } +//! +//! #[derive(Deserialize)] +//! struct Keys { +//! github: String, +//! travis: Option<String>, +//! } +//! +//! let config: Config = toml::from_str(r#" +//! ip = '127.0.0.1' +//! +//! [keys] +//! github = 'xxxxxxxxxxxxxxxxx' +//! travis = 'yyyyyyyyyyyyyyyyy' +//! "#).unwrap(); +//! +//! assert_eq!(config.ip, "127.0.0.1"); +//! assert_eq!(config.port, None); +//! assert_eq!(config.keys.github, "xxxxxxxxxxxxxxxxx"); +//! assert_eq!(config.keys.travis.as_ref().unwrap(), "yyyyyyyyyyyyyyyyy"); +//! ``` +//! +//! You can serialize types in a similar fashion: +//! +#![cfg_attr(not(feature = "display"), doc = " ```ignore")] +#![cfg_attr(feature = "display", doc = " ```")] +//! use serde::Serialize; +//! +//! #[derive(Serialize)] +//! struct Config { +//! ip: String, +//! port: Option<u16>, +//! keys: Keys, +//! } +//! +//! #[derive(Serialize)] +//! struct Keys { +//! github: String, +//! travis: Option<String>, +//! } +//! +//! let config = Config { +//! ip: "127.0.0.1".to_string(), +//! port: None, +//! keys: Keys { +//! github: "xxxxxxxxxxxxxxxxx".to_string(), +//! travis: Some("yyyyyyyyyyyyyyyyy".to_string()), +//! }, +//! }; +//! +//! let toml = toml::to_string(&config).unwrap(); +//! ``` +//! +//! [TOML]: https://github.com/toml-lang/toml +//! [Cargo]: https://crates.io/ +//! [`serde`]: https://serde.rs/ +//! [serde]: https://serde.rs/ + +#![deny(missing_docs)] +#![warn(rust_2018_idioms)] +// Makes rustc abort compilation if there are any unsafe blocks in the crate. +// Presence of this annotation is picked up by tools such as cargo-geiger +// and lets them ensure that there is indeed no unsafe code as opposed to +// something they couldn't detect (e.g. unsafe added via macro expansion, etc). +#![forbid(unsafe_code)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +pub mod map; +pub mod value; + +pub mod de; +pub mod ser; + +#[doc(hidden)] +pub mod macros; + +mod edit; +#[cfg(feature = "display")] +mod fmt; +mod table; + +#[cfg(feature = "parse")] +#[doc(inline)] +pub use crate::de::{from_str, Deserializer}; +#[cfg(feature = "display")] +#[doc(inline)] +pub use crate::ser::{to_string, to_string_pretty, Serializer}; +#[doc(inline)] +pub use crate::value::Value; + +pub use serde_spanned::Spanned; +pub use table::Table; + +// Shortcuts for the module doc-comment +#[allow(unused_imports)] +use core::str::FromStr; +#[allow(unused_imports)] +use toml_datetime::Datetime; diff --git a/vendor/toml/src/macros.rs b/vendor/toml/src/macros.rs new file mode 100644 index 000000000..d86cc52f5 --- /dev/null +++ b/vendor/toml/src/macros.rs @@ -0,0 +1,460 @@ +pub use serde::de::{Deserialize, IntoDeserializer}; + +use crate::value::{Array, Table, Value}; + +/// Construct a [`Table`] from TOML syntax. +/// +/// ```rust +/// let cargo_toml = toml::toml! { +/// [package] +/// name = "toml" +/// version = "0.4.5" +/// authors = ["Alex Crichton <alex@alexcrichton.com>"] +/// +/// [badges] +/// travis-ci = { repository = "alexcrichton/toml-rs" } +/// +/// [dependencies] +/// serde = "1.0" +/// +/// [dev-dependencies] +/// serde_derive = "1.0" +/// serde_json = "1.0" +/// }; +/// +/// println!("{:#?}", cargo_toml); +/// ``` +#[macro_export] +macro_rules! toml { + ($($toml:tt)+) => {{ + let table = $crate::value::Table::new(); + let mut root = $crate::Value::Table(table); + $crate::toml_internal!(@toplevel root [] $($toml)+); + match root { + $crate::Value::Table(table) => table, + _ => unreachable!(), + } + }}; +} + +// TT-muncher to parse TOML syntax into a toml::Value. +// +// @toplevel -- Parse tokens outside of an inline table or inline array. In +// this state, `[table headers]` and `[[array headers]]` are +// allowed and `key = value` pairs are not separated by commas. +// +// @topleveldatetime -- Helper to parse a Datetime from string and insert it +// into a table, continuing in the @toplevel state. +// +// @path -- Turn a path segment into a string. Segments that look like idents +// are stringified, while quoted segments like `"cfg(windows)"` +// are not. +// +// @value -- Parse the value part of a `key = value` pair, which may be a +// primitive or inline table or inline array. +// +// @table -- Parse the contents of an inline table, returning them as a +// toml::Value::Table. +// +// @tabledatetime -- Helper to parse a Datetime from string and insert it +// into a table, continuing in the @table state. +// +// @array -- Parse the contents of an inline array, returning them as a +// toml::Value::Array. +// +// @arraydatetime -- Helper to parse a Datetime from string and push it into +// an array, continuing in the @array state. +// +// @trailingcomma -- Helper to append a comma to a sequence of tokens if the +// sequence is non-empty and does not already end in a trailing +// comma. +// +#[macro_export] +#[doc(hidden)] +macro_rules! toml_internal { + // Base case, no elements remaining. + (@toplevel $root:ident [$($path:tt)*]) => {}; + + // Parse negative number `key = -value`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = - $v:tt $($rest:tt)*) => { + $crate::toml_internal!(@toplevel $root [$($path)*] $($($k)-+).+ = (-$v) $($rest)*); + }; + + // Parse positive number `key = +value`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = + $v:tt $($rest:tt)*) => { + $crate::toml_internal!(@toplevel $root [$($path)*] $($($k)-+).+ = ($v) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T00:32:00.999999-07:00`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T00:32:00-07:00`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + + // Parse local datetime `key = 1979-05-27T00:32:00.999999`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*); + }; + // Space instead of T. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T07:32:00Z` and local datetime `key = 1979-05-27T07:32:00`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*); + }; + // Space instead of T. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*); + }; + + // Parse local date `key = 1979-05-27`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day) $($rest)*); + }; + + // Parse local time `key = 00:32:00.999999`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse local time `key = 07:32:00`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec) $($rest)*); + }; + + // Parse any other `key = value` including string, inline array, inline + // table, number, and boolean. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $v:tt $($rest:tt)*) => {{ + $crate::macros::insert_toml( + &mut $root, + &[$($path)* $(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+], + $crate::toml_internal!(@value $v)); + $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*); + }}; + + // Parse array header `[[bin]]`. + (@toplevel $root:ident $oldpath:tt [[$($($path:tt)-+).+]] $($rest:tt)*) => { + $crate::macros::push_toml( + &mut $root, + &[$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+]); + $crate::toml_internal!(@toplevel $root [$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*); + }; + + // Parse table header `[patch.crates-io]`. + (@toplevel $root:ident $oldpath:tt [$($($path:tt)-+).+] $($rest:tt)*) => { + $crate::macros::insert_toml( + &mut $root, + &[$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+], + $crate::Value::Table($crate::value::Table::new())); + $crate::toml_internal!(@toplevel $root [$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*); + }; + + // Parse datetime from string and insert into table. + (@topleveldatetime $root:ident [$($path:tt)*] $($($k:tt)-+).+ = ($($datetime:tt)+) $($rest:tt)*) => { + $crate::macros::insert_toml( + &mut $root, + &[$($path)* $(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+], + $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap())); + $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*); + }; + + // Turn a path segment into a string. + (@path $ident:ident) => { + stringify!($ident) + }; + + // For a path segment that is not an ident, expect that it is already a + // quoted string, like in `[target."cfg(windows)".dependencies]`. + (@path $quoted:tt) => { + $quoted + }; + + // Construct a Value from an inline table. + (@value { $($inline:tt)* }) => {{ + let mut table = $crate::Value::Table($crate::value::Table::new()); + $crate::toml_internal!(@trailingcomma (@table table) $($inline)*); + table + }}; + + // Construct a Value from an inline array. + (@value [ $($inline:tt)* ]) => {{ + let mut array = $crate::value::Array::new(); + $crate::toml_internal!(@trailingcomma (@array array) $($inline)*); + $crate::Value::Array(array) + }}; + + (@value (-nan)) => { + $crate::Value::Float(-::std::f64::NAN) + }; + + (@value (nan)) => { + $crate::Value::Float(::std::f64::NAN) + }; + + (@value nan) => { + $crate::Value::Float(::std::f64::NAN) + }; + + (@value (-inf)) => { + $crate::Value::Float(::std::f64::NEG_INFINITY) + }; + + (@value (inf)) => { + $crate::Value::Float(::std::f64::INFINITY) + }; + + (@value inf) => { + $crate::Value::Float(::std::f64::INFINITY) + }; + + // Construct a Value from any other type, probably string or boolean or number. + (@value $v:tt) => {{ + // TODO: Implement this with something like serde_json::to_value instead. + let de = $crate::macros::IntoDeserializer::<$crate::de::Error>::into_deserializer($v); + <$crate::Value as $crate::macros::Deserialize>::deserialize(de).unwrap() + }}; + + // Base case of inline table. + (@table $root:ident) => {}; + + // Parse negative number `key = -value`. + (@table $root:ident $($($k:tt)-+).+ = - $v:tt , $($rest:tt)*) => { + $crate::toml_internal!(@table $root $($($k)-+).+ = (-$v) , $($rest)*); + }; + + // Parse positive number `key = +value`. + (@table $root:ident $($($k:tt)-+).+ = + $v:tt , $($rest:tt)*) => { + $crate::toml_internal!(@table $root $($($k)-+).+ = ($v) , $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T00:32:00.999999-07:00`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T00:32:00-07:00`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + + // Parse local datetime `key = 1979-05-27T00:32:00.999999`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*); + }; + // Space instead of T. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T07:32:00Z` and local datetime `key = 1979-05-27T07:32:00`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*); + }; + // Space instead of T. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*); + }; + + // Parse local date `key = 1979-05-27`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day) $($rest)*); + }; + + // Parse local time `key = 00:32:00.999999`. + (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse local time `key = 07:32:00`. + (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec) $($rest)*); + }; + + // Parse any other type, probably string or boolean or number. + (@table $root:ident $($($k:tt)-+).+ = $v:tt , $($rest:tt)*) => { + $crate::macros::insert_toml( + &mut $root, + &[$(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+], + $crate::toml_internal!(@value $v)); + $crate::toml_internal!(@table $root $($rest)*); + }; + + // Parse a Datetime from string and continue in @table state. + (@tabledatetime $root:ident $($($k:tt)-+).+ = ($($datetime:tt)*) $($rest:tt)*) => { + $crate::macros::insert_toml( + &mut $root, + &[$(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+], + $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap())); + $crate::toml_internal!(@table $root $($rest)*); + }; + + // Base case of inline array. + (@array $root:ident) => {}; + + // Parse negative number `-value`. + (@array $root:ident - $v:tt , $($rest:tt)*) => { + $crate::toml_internal!(@array $root (-$v) , $($rest)*); + }; + + // Parse positive number `+value`. + (@array $root:ident + $v:tt , $($rest:tt)*) => { + $crate::toml_internal!(@array $root ($v) , $($rest)*); + }; + + // Parse offset datetime `1979-05-27T00:32:00.999999-07:00`. + (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + + // Parse offset datetime `1979-05-27T00:32:00-07:00`. + (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + + // Parse local datetime `1979-05-27T00:32:00.999999`. + (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*); + }; + // Space instead of T. + (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse offset datetime `1979-05-27T07:32:00Z` and local datetime `1979-05-27T07:32:00`. + (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec) $($rest)*); + }; + // Space instead of T. + (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec) $($rest)*); + }; + + // Parse local date `1979-05-27`. + (@array $root:ident $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day) $($rest)*); + }; + + // Parse local time `00:32:00.999999`. + (@array $root:ident $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse local time `07:32:00`. + (@array $root:ident $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec) $($rest)*); + }; + + // Parse any other type, probably string or boolean or number. + (@array $root:ident $v:tt , $($rest:tt)*) => { + $root.push($crate::toml_internal!(@value $v)); + $crate::toml_internal!(@array $root $($rest)*); + }; + + // Parse a Datetime from string and continue in @array state. + (@arraydatetime $root:ident ($($datetime:tt)*) $($rest:tt)*) => { + $root.push($crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap())); + $crate::toml_internal!(@array $root $($rest)*); + }; + + // No trailing comma required if the tokens are empty. + (@trailingcomma ($($args:tt)*)) => { + $crate::toml_internal!($($args)*); + }; + + // Tokens end with a trailing comma, do not append another one. + (@trailingcomma ($($args:tt)*) ,) => { + $crate::toml_internal!($($args)* ,); + }; + + // Tokens end with something other than comma, append a trailing comma. + (@trailingcomma ($($args:tt)*) $last:tt) => { + $crate::toml_internal!($($args)* $last ,); + }; + + // Not yet at the last token. + (@trailingcomma ($($args:tt)*) $first:tt $($rest:tt)+) => { + $crate::toml_internal!(@trailingcomma ($($args)* $first) $($rest)+); + }; +} + +// Called when parsing a `key = value` pair. +// Inserts an entry into the table at the given path. +pub fn insert_toml(root: &mut Value, path: &[&str], value: Value) { + *traverse(root, path) = value; +} + +// Called when parsing an `[[array header]]`. +// Pushes an empty table onto the array at the given path. +pub fn push_toml(root: &mut Value, path: &[&str]) { + let target = traverse(root, path); + if !target.is_array() { + *target = Value::Array(Array::new()); + } + target + .as_array_mut() + .unwrap() + .push(Value::Table(Table::new())); +} + +fn traverse<'a>(root: &'a mut Value, path: &[&str]) -> &'a mut Value { + let mut cur = root; + for &key in path { + // Lexical lifetimes :D + let cur1 = cur; + + // From the TOML spec: + // + // > Each double-bracketed sub-table will belong to the most recently + // > defined table element above it. + let cur2 = if cur1.is_array() { + cur1.as_array_mut().unwrap().last_mut().unwrap() + } else { + cur1 + }; + + // We are about to index into this value, so it better be a table. + if !cur2.is_table() { + *cur2 = Value::Table(Table::new()); + } + + if !cur2.as_table().unwrap().contains_key(key) { + // Insert an empty table for the next loop iteration to point to. + let empty = Value::Table(Table::new()); + cur2.as_table_mut().unwrap().insert(key.to_owned(), empty); + } + + // Step into the current table. + cur = cur2.as_table_mut().unwrap().get_mut(key).unwrap(); + } + cur +} diff --git a/vendor/toml/src/map.rs b/vendor/toml/src/map.rs new file mode 100644 index 000000000..5b3ff19b4 --- /dev/null +++ b/vendor/toml/src/map.rs @@ -0,0 +1,595 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A map of `String` to [Value]. +//! +//! By default the map is backed by a [`BTreeMap`]. Enable the `preserve_order` +//! feature of toml-rs to use [`IndexMap`] instead. +//! +//! [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html +//! [`IndexMap`]: https://docs.rs/indexmap + +use crate::value::Value; +use serde::{de, ser}; +use std::borrow::Borrow; +use std::fmt::{self, Debug}; +use std::hash::Hash; +use std::iter::FromIterator; +use std::ops; + +#[cfg(not(feature = "preserve_order"))] +use std::collections::{btree_map, BTreeMap}; + +#[cfg(feature = "preserve_order")] +use indexmap::{self, IndexMap}; + +/// Represents a TOML key/value type. +pub struct Map<K, V> { + map: MapImpl<K, V>, +} + +#[cfg(not(feature = "preserve_order"))] +type MapImpl<K, V> = BTreeMap<K, V>; +#[cfg(feature = "preserve_order")] +type MapImpl<K, V> = IndexMap<K, V>; + +impl Map<String, Value> { + /// Makes a new empty Map. + #[inline] + pub fn new() -> Self { + Map { + map: MapImpl::new(), + } + } + + #[cfg(not(feature = "preserve_order"))] + /// Makes a new empty Map with the given initial capacity. + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + // does not support with_capacity + let _ = capacity; + Map { + map: BTreeMap::new(), + } + } + + #[cfg(feature = "preserve_order")] + /// Makes a new empty Map with the given initial capacity. + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + Map { + map: IndexMap::with_capacity(capacity), + } + } + + /// Clears the map, removing all values. + #[inline] + pub fn clear(&mut self) { + self.map.clear() + } + + /// Returns a reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + #[inline] + pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&Value> + where + String: Borrow<Q>, + Q: Ord + Eq + Hash, + { + self.map.get(key) + } + + /// Returns true if the map contains a value for the specified key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + #[inline] + pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool + where + String: Borrow<Q>, + Q: Ord + Eq + Hash, + { + self.map.contains_key(key) + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + #[inline] + pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut Value> + where + String: Borrow<Q>, + Q: Ord + Eq + Hash, + { + self.map.get_mut(key) + } + + /// Inserts a key-value pair into the map. + /// + /// If the map did not have this key present, `None` is returned. + /// + /// If the map did have this key present, the value is updated, and the old + /// value is returned. The key is not updated, though; this matters for + /// types that can be `==` without being identical. + #[inline] + pub fn insert(&mut self, k: String, v: Value) -> Option<Value> { + self.map.insert(k, v) + } + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + #[inline] + pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<Value> + where + String: Borrow<Q>, + Q: Ord + Eq + Hash, + { + self.map.remove(key) + } + + /// Gets the given key's corresponding entry in the map for in-place + /// manipulation. + pub fn entry<S>(&mut self, key: S) -> Entry<'_> + where + S: Into<String>, + { + #[cfg(feature = "preserve_order")] + use indexmap::map::Entry as EntryImpl; + #[cfg(not(feature = "preserve_order"))] + use std::collections::btree_map::Entry as EntryImpl; + + match self.map.entry(key.into()) { + EntryImpl::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant }), + EntryImpl::Occupied(occupied) => Entry::Occupied(OccupiedEntry { occupied }), + } + } + + /// Returns the number of elements in the map. + #[inline] + pub fn len(&self) -> usize { + self.map.len() + } + + /// Returns true if the map contains no elements. + #[inline] + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + + /// Gets an iterator over the entries of the map. + #[inline] + pub fn iter(&self) -> Iter<'_> { + Iter { + iter: self.map.iter(), + } + } + + /// Gets a mutable iterator over the entries of the map. + #[inline] + pub fn iter_mut(&mut self) -> IterMut<'_> { + IterMut { + iter: self.map.iter_mut(), + } + } + + /// Gets an iterator over the keys of the map. + #[inline] + pub fn keys(&self) -> Keys<'_> { + Keys { + iter: self.map.keys(), + } + } + + /// Gets an iterator over the values of the map. + #[inline] + pub fn values(&self) -> Values<'_> { + Values { + iter: self.map.values(), + } + } +} + +impl Default for Map<String, Value> { + #[inline] + fn default() -> Self { + Map { + map: MapImpl::new(), + } + } +} + +impl Clone for Map<String, Value> { + #[inline] + fn clone(&self) -> Self { + Map { + map: self.map.clone(), + } + } +} + +impl PartialEq for Map<String, Value> { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.map.eq(&other.map) + } +} + +/// Access an element of this map. Panics if the given key is not present in the +/// map. +impl<'a, Q: ?Sized> ops::Index<&'a Q> for Map<String, Value> +where + String: Borrow<Q>, + Q: Ord + Eq + Hash, +{ + type Output = Value; + + fn index(&self, index: &Q) -> &Value { + self.map.index(index) + } +} + +/// Mutably access an element of this map. Panics if the given key is not +/// present in the map. +impl<'a, Q: ?Sized> ops::IndexMut<&'a Q> for Map<String, Value> +where + String: Borrow<Q>, + Q: Ord + Eq + Hash, +{ + fn index_mut(&mut self, index: &Q) -> &mut Value { + self.map.get_mut(index).expect("no entry found for key") + } +} + +impl Debug for Map<String, Value> { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + self.map.fmt(formatter) + } +} + +impl ser::Serialize for Map<String, Value> { + #[inline] + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + use serde::ser::SerializeMap; + let mut map = serializer.serialize_map(Some(self.len()))?; + for (k, v) in self { + map.serialize_key(k)?; + map.serialize_value(v)?; + } + map.end() + } +} + +impl<'de> de::Deserialize<'de> for Map<String, Value> { + #[inline] + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + struct Visitor; + + impl<'de> de::Visitor<'de> for Visitor { + type Value = Map<String, Value>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a map") + } + + #[inline] + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(Map::new()) + } + + #[inline] + fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error> + where + V: de::MapAccess<'de>, + { + let mut values = Map::new(); + + while let Some((key, value)) = visitor.next_entry()? { + values.insert(key, value); + } + + Ok(values) + } + } + + deserializer.deserialize_map(Visitor) + } +} + +impl FromIterator<(String, Value)> for Map<String, Value> { + fn from_iter<T>(iter: T) -> Self + where + T: IntoIterator<Item = (String, Value)>, + { + Map { + map: FromIterator::from_iter(iter), + } + } +} + +impl Extend<(String, Value)> for Map<String, Value> { + fn extend<T>(&mut self, iter: T) + where + T: IntoIterator<Item = (String, Value)>, + { + self.map.extend(iter); + } +} + +macro_rules! delegate_iterator { + (($name:ident $($generics:tt)*) => $item:ty) => { + impl $($generics)* Iterator for $name $($generics)* { + type Item = $item; + #[inline] + fn next(&mut self) -> Option<Self::Item> { + self.iter.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } + } + + impl $($generics)* DoubleEndedIterator for $name $($generics)* { + #[inline] + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back() + } + } + + impl $($generics)* ExactSizeIterator for $name $($generics)* { + #[inline] + fn len(&self) -> usize { + self.iter.len() + } + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +/// A view into a single entry in a map, which may either be vacant or occupied. +/// This enum is constructed from the [`entry`] method on [`Map`]. +/// +/// [`entry`]: struct.Map.html#method.entry +/// [`Map`]: struct.Map.html +pub enum Entry<'a> { + /// A vacant Entry. + Vacant(VacantEntry<'a>), + /// An occupied Entry. + Occupied(OccupiedEntry<'a>), +} + +/// A vacant Entry. It is part of the [`Entry`] enum. +/// +/// [`Entry`]: enum.Entry.html +pub struct VacantEntry<'a> { + vacant: VacantEntryImpl<'a>, +} + +/// An occupied Entry. It is part of the [`Entry`] enum. +/// +/// [`Entry`]: enum.Entry.html +pub struct OccupiedEntry<'a> { + occupied: OccupiedEntryImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type VacantEntryImpl<'a> = btree_map::VacantEntry<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type VacantEntryImpl<'a> = indexmap::map::VacantEntry<'a, String, Value>; + +#[cfg(not(feature = "preserve_order"))] +type OccupiedEntryImpl<'a> = btree_map::OccupiedEntry<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type OccupiedEntryImpl<'a> = indexmap::map::OccupiedEntry<'a, String, Value>; + +impl<'a> Entry<'a> { + /// Returns a reference to this entry's key. + pub fn key(&self) -> &String { + match *self { + Entry::Vacant(ref e) => e.key(), + Entry::Occupied(ref e) => e.key(), + } + } + + /// Ensures a value is in the entry by inserting the default if empty, and + /// returns a mutable reference to the value in the entry. + pub fn or_insert(self, default: Value) -> &'a mut Value { + match self { + Entry::Vacant(entry) => entry.insert(default), + Entry::Occupied(entry) => entry.into_mut(), + } + } + + /// Ensures a value is in the entry by inserting the result of the default + /// function if empty, and returns a mutable reference to the value in the + /// entry. + pub fn or_insert_with<F>(self, default: F) -> &'a mut Value + where + F: FnOnce() -> Value, + { + match self { + Entry::Vacant(entry) => entry.insert(default()), + Entry::Occupied(entry) => entry.into_mut(), + } + } +} + +impl<'a> VacantEntry<'a> { + /// Gets a reference to the key that would be used when inserting a value + /// through the VacantEntry. + #[inline] + pub fn key(&self) -> &String { + self.vacant.key() + } + + /// Sets the value of the entry with the VacantEntry's key, and returns a + /// mutable reference to it. + #[inline] + pub fn insert(self, value: Value) -> &'a mut Value { + self.vacant.insert(value) + } +} + +impl<'a> OccupiedEntry<'a> { + /// Gets a reference to the key in the entry. + #[inline] + pub fn key(&self) -> &String { + self.occupied.key() + } + + /// Gets a reference to the value in the entry. + #[inline] + pub fn get(&self) -> &Value { + self.occupied.get() + } + + /// Gets a mutable reference to the value in the entry. + #[inline] + pub fn get_mut(&mut self) -> &mut Value { + self.occupied.get_mut() + } + + /// Converts the entry into a mutable reference to its value. + #[inline] + pub fn into_mut(self) -> &'a mut Value { + self.occupied.into_mut() + } + + /// Sets the value of the entry with the `OccupiedEntry`'s key, and returns + /// the entry's old value. + #[inline] + pub fn insert(&mut self, value: Value) -> Value { + self.occupied.insert(value) + } + + /// Takes the value of the entry out of the map, and returns it. + #[inline] + pub fn remove(self) -> Value { + self.occupied.remove() + } +} + +////////////////////////////////////////////////////////////////////////////// + +impl<'a> IntoIterator for &'a Map<String, Value> { + type Item = (&'a String, &'a Value); + type IntoIter = Iter<'a>; + #[inline] + fn into_iter(self) -> Self::IntoIter { + Iter { + iter: self.map.iter(), + } + } +} + +/// An iterator over a toml::Map's entries. +pub struct Iter<'a> { + iter: IterImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type IterImpl<'a> = btree_map::Iter<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type IterImpl<'a> = indexmap::map::Iter<'a, String, Value>; + +delegate_iterator!((Iter<'a>) => (&'a String, &'a Value)); + +////////////////////////////////////////////////////////////////////////////// + +impl<'a> IntoIterator for &'a mut Map<String, Value> { + type Item = (&'a String, &'a mut Value); + type IntoIter = IterMut<'a>; + #[inline] + fn into_iter(self) -> Self::IntoIter { + IterMut { + iter: self.map.iter_mut(), + } + } +} + +/// A mutable iterator over a toml::Map's entries. +pub struct IterMut<'a> { + iter: IterMutImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type IterMutImpl<'a> = btree_map::IterMut<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type IterMutImpl<'a> = indexmap::map::IterMut<'a, String, Value>; + +delegate_iterator!((IterMut<'a>) => (&'a String, &'a mut Value)); + +////////////////////////////////////////////////////////////////////////////// + +impl IntoIterator for Map<String, Value> { + type Item = (String, Value); + type IntoIter = IntoIter; + #[inline] + fn into_iter(self) -> Self::IntoIter { + IntoIter { + iter: self.map.into_iter(), + } + } +} + +/// An owning iterator over a toml::Map's entries. +pub struct IntoIter { + iter: IntoIterImpl, +} + +#[cfg(not(feature = "preserve_order"))] +type IntoIterImpl = btree_map::IntoIter<String, Value>; +#[cfg(feature = "preserve_order")] +type IntoIterImpl = indexmap::map::IntoIter<String, Value>; + +delegate_iterator!((IntoIter) => (String, Value)); + +////////////////////////////////////////////////////////////////////////////// + +/// An iterator over a toml::Map's keys. +pub struct Keys<'a> { + iter: KeysImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type KeysImpl<'a> = btree_map::Keys<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type KeysImpl<'a> = indexmap::map::Keys<'a, String, Value>; + +delegate_iterator!((Keys<'a>) => &'a String); + +////////////////////////////////////////////////////////////////////////////// + +/// An iterator over a toml::Map's values. +pub struct Values<'a> { + iter: ValuesImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type ValuesImpl<'a> = btree_map::Values<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type ValuesImpl<'a> = indexmap::map::Values<'a, String, Value>; + +delegate_iterator!((Values<'a>) => &'a Value); diff --git a/vendor/toml/src/ser.rs b/vendor/toml/src/ser.rs new file mode 100644 index 000000000..f1ab24bb8 --- /dev/null +++ b/vendor/toml/src/ser.rs @@ -0,0 +1,1087 @@ +//! Serializing Rust structures into TOML. +//! +//! This module contains all the Serde support for serializing Rust structures +//! into TOML documents (as strings). Note that some top-level functions here +//! are also provided at the top of the crate. + +/// Serialize the given data structure as a String of TOML. +/// +/// Serialization can fail if `T`'s implementation of `Serialize` decides to +/// fail, if `T` contains a map with non-string keys, or if `T` attempts to +/// serialize an unsupported datatype such as an enum, tuple, or tuple struct. +/// +/// To serialize TOML values, instead of documents, see [`ValueSerializer`]. +/// +/// # Examples +/// +/// ``` +/// use serde::Serialize; +/// +/// #[derive(Serialize)] +/// struct Config { +/// database: Database, +/// } +/// +/// #[derive(Serialize)] +/// struct Database { +/// ip: String, +/// port: Vec<u16>, +/// connection_max: u32, +/// enabled: bool, +/// } +/// +/// let config = Config { +/// database: Database { +/// ip: "192.168.1.1".to_string(), +/// port: vec![8001, 8002, 8003], +/// connection_max: 5000, +/// enabled: false, +/// }, +/// }; +/// +/// let toml = toml::to_string(&config).unwrap(); +/// println!("{}", toml) +/// ``` +#[cfg(feature = "display")] +pub fn to_string<T: ?Sized>(value: &T) -> Result<String, Error> +where + T: serde::ser::Serialize, +{ + let mut output = String::new(); + let serializer = Serializer::new(&mut output); + value.serialize(serializer)?; + Ok(output) +} + +/// Serialize the given data structure as a "pretty" String of TOML. +/// +/// This is identical to `to_string` except the output string has a more +/// "pretty" output. See `Serializer::pretty` for more details. +/// +/// To serialize TOML values, instead of documents, see [`ValueSerializer`]. +/// +/// For greater customization, instead serialize to a +/// [`toml_edit::Document`](https://docs.rs/toml_edit/latest/toml_edit/struct.Document.html). +#[cfg(feature = "display")] +pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error> +where + T: serde::ser::Serialize, +{ + let mut output = String::new(); + let serializer = Serializer::pretty(&mut output); + value.serialize(serializer)?; + Ok(output) +} + +/// Errors that can occur when serializing a type. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Error { + pub(crate) inner: crate::edit::ser::Error, +} + +impl Error { + pub(crate) fn new(inner: impl std::fmt::Display) -> Self { + Self { + inner: crate::edit::ser::Error::Custom(inner.to_string()), + } + } + + #[cfg(feature = "display")] + pub(crate) fn wrap(inner: crate::edit::ser::Error) -> Self { + Self { inner } + } + + pub(crate) fn unsupported_type(t: Option<&'static str>) -> Self { + Self { + inner: crate::edit::ser::Error::UnsupportedType(t), + } + } + + pub(crate) fn unsupported_none() -> Self { + Self { + inner: crate::edit::ser::Error::UnsupportedNone, + } + } + + pub(crate) fn key_not_string() -> Self { + Self { + inner: crate::edit::ser::Error::KeyNotString, + } + } +} + +impl serde::ser::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::new(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 {} + +/// Serialization for TOML documents. +/// +/// This structure implements serialization support for TOML to serialize an +/// arbitrary type to TOML. Note that the TOML format does not support all +/// datatypes in Rust, such as enums, tuples, and tuple structs. These types +/// will generate an error when serialized. +/// +/// Currently a serializer always writes its output to an in-memory `String`, +/// which is passed in when creating the serializer itself. +/// +/// To serialize TOML values, instead of documents, see [`ValueSerializer`]. +#[non_exhaustive] +#[cfg(feature = "display")] +pub struct Serializer<'d> { + dst: &'d mut String, + settings: crate::fmt::DocumentFormatter, +} + +#[cfg(feature = "display")] +impl<'d> Serializer<'d> { + /// Creates a new serializer which will emit TOML into the buffer provided. + /// + /// The serializer can then be used to serialize a type after which the data + /// will be present in `dst`. + pub fn new(dst: &'d mut String) -> Self { + Self { + dst, + settings: Default::default(), + } + } + + /// Apply a default "pretty" policy to the document + /// + /// For greater customization, instead serialize to a + /// [`toml_edit::Document`](https://docs.rs/toml_edit/latest/toml_edit/struct.Document.html). + pub fn pretty(dst: &'d mut String) -> Self { + let mut ser = Serializer::new(dst); + ser.settings.multiline_array = true; + ser + } +} + +#[cfg(feature = "display")] +impl<'d> serde::ser::Serializer for Serializer<'d> { + type Ok = (); + type Error = Error; + type SerializeSeq = SerializeDocumentArray<'d>; + type SerializeTuple = SerializeDocumentArray<'d>; + type SerializeTupleStruct = SerializeDocumentArray<'d>; + type SerializeTupleVariant = SerializeDocumentArray<'d>; + type SerializeMap = SerializeDocumentTable<'d>; + type SerializeStruct = SerializeDocumentTable<'d>; + type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>; + + fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_bool(v), + ) + } + + fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_i8(v), + ) + } + + fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_i16(v), + ) + } + + fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_i32(v), + ) + } + + fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_i64(v), + ) + } + + fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_u8(v), + ) + } + + fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_u16(v), + ) + } + + fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_u32(v), + ) + } + + fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_u64(v), + ) + } + + fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_f32(v), + ) + } + + fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_f64(v), + ) + } + + fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_char(v), + ) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_str(v), + ) + } + + fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_bytes(v), + ) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_none(), + ) + } + + fn serialize_some<T: ?Sized>(self, v: &T) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_some(v), + ) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_unit(), + ) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_unit_struct(name), + ) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_unit_variant( + name, + variant_index, + variant, + ), + ) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + name: &'static str, + v: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v), + ) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_newtype_variant( + name, + variant_index, + variant, + value, + ), + ) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + let ser = toml_edit::ser::ValueSerializer::new() + .serialize_seq(len) + .map_err(Error::wrap)?; + let ser = SerializeDocumentArray::new(self, ser); + Ok(ser) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + let ser = toml_edit::ser::ValueSerializer::new() + .serialize_map(len) + .map_err(Error::wrap)?; + let ser = SerializeDocumentTable::new(self, ser); + Ok(ser) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(Error::unsupported_type(Some(name))) + } +} + +/// Serialization for TOML [values][crate::Value]. +/// +/// This structure implements serialization support for TOML to serialize an +/// arbitrary type to TOML. Note that the TOML format does not support all +/// datatypes in Rust, such as enums, tuples, and tuple structs. These types +/// will generate an error when serialized. +/// +/// Currently a serializer always writes its output to an in-memory `String`, +/// which is passed in when creating the serializer itself. +/// +/// # Examples +/// +/// ``` +/// use serde::Serialize; +/// +/// #[derive(Serialize)] +/// struct Config { +/// database: Database, +/// } +/// +/// #[derive(Serialize)] +/// struct Database { +/// ip: String, +/// port: Vec<u16>, +/// connection_max: u32, +/// enabled: bool, +/// } +/// +/// let config = Config { +/// database: Database { +/// ip: "192.168.1.1".to_string(), +/// port: vec![8001, 8002, 8003], +/// connection_max: 5000, +/// enabled: false, +/// }, +/// }; +/// +/// let mut value = String::new(); +/// serde::Serialize::serialize( +/// &config, +/// toml::ser::ValueSerializer::new(&mut value) +/// ).unwrap(); +/// println!("{}", value) +/// ``` +#[non_exhaustive] +#[cfg(feature = "display")] +pub struct ValueSerializer<'d> { + dst: &'d mut String, +} + +#[cfg(feature = "display")] +impl<'d> ValueSerializer<'d> { + /// Creates a new serializer which will emit TOML into the buffer provided. + /// + /// The serializer can then be used to serialize a type after which the data + /// will be present in `dst`. + pub fn new(dst: &'d mut String) -> Self { + Self { dst } + } +} + +#[cfg(feature = "display")] +impl<'d> serde::ser::Serializer for ValueSerializer<'d> { + type Ok = (); + type Error = Error; + type SerializeSeq = SerializeValueArray<'d>; + type SerializeTuple = SerializeValueArray<'d>; + type SerializeTupleStruct = SerializeValueArray<'d>; + type SerializeTupleVariant = SerializeValueArray<'d>; + type SerializeMap = SerializeValueTable<'d>; + type SerializeStruct = SerializeValueTable<'d>; + type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>; + + fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_bool(v), + ) + } + + fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_i8(v), + ) + } + + fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_i16(v), + ) + } + + fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_i32(v), + ) + } + + fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_i64(v), + ) + } + + fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_u8(v), + ) + } + + fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_u16(v), + ) + } + + fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_u32(v), + ) + } + + fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_u64(v), + ) + } + + fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_f32(v), + ) + } + + fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_f64(v), + ) + } + + fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_char(v), + ) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_str(v), + ) + } + + fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_bytes(v), + ) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_none(), + ) + } + + fn serialize_some<T: ?Sized>(self, v: &T) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_some(v), + ) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_unit(), + ) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_unit_struct(name), + ) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_unit_variant( + name, + variant_index, + variant, + ), + ) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + name: &'static str, + v: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v), + ) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_newtype_variant( + name, + variant_index, + variant, + value, + ), + ) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + let ser = toml_edit::ser::ValueSerializer::new() + .serialize_seq(len) + .map_err(Error::wrap)?; + let ser = SerializeValueArray::new(self, ser); + Ok(ser) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + let ser = toml_edit::ser::ValueSerializer::new() + .serialize_map(len) + .map_err(Error::wrap)?; + let ser = SerializeValueTable::new(self, ser); + Ok(ser) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(Error::unsupported_type(Some(name))) + } +} + +#[cfg(feature = "display")] +use internal::*; + +#[cfg(feature = "display")] +mod internal { + use super::*; + + use crate::fmt::DocumentFormatter; + + type InnerSerializeDocumentSeq = + <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeSeq; + + #[doc(hidden)] + pub struct SerializeDocumentArray<'d> { + inner: InnerSerializeDocumentSeq, + dst: &'d mut String, + settings: DocumentFormatter, + } + + impl<'d> SerializeDocumentArray<'d> { + pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentSeq) -> Self { + Self { + inner, + dst: ser.dst, + settings: ser.settings, + } + } + } + + impl<'d> serde::ser::SerializeSeq for SerializeDocumentArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTuple for SerializeDocumentArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTupleVariant for SerializeDocumentArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTupleStruct for SerializeDocumentArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + type InnerSerializeDocumentTable = + <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeMap; + + #[doc(hidden)] + pub struct SerializeDocumentTable<'d> { + inner: InnerSerializeDocumentTable, + dst: &'d mut String, + settings: DocumentFormatter, + } + + impl<'d> SerializeDocumentTable<'d> { + pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentTable) -> Self { + Self { + inner, + dst: ser.dst, + settings: ser.settings, + } + } + } + + impl<'d> serde::ser::SerializeMap for SerializeDocumentTable<'d> { + type Ok = (); + type Error = Error; + + fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_key(input).map_err(Error::wrap) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_value(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeStruct for SerializeDocumentTable<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(key, value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + pub(crate) fn write_document( + dst: &mut String, + mut settings: DocumentFormatter, + value: Result<toml_edit::Value, crate::edit::ser::Error>, + ) -> Result<(), Error> { + use std::fmt::Write; + + let value = value.map_err(Error::wrap)?; + let mut table = match toml_edit::Item::Value(value).into_table() { + Ok(i) => i, + Err(_) => { + return Err(Error::unsupported_type(None)); + } + }; + + use toml_edit::visit_mut::VisitMut as _; + settings.visit_table_mut(&mut table); + + let doc: toml_edit::Document = table.into(); + write!(dst, "{}", doc).unwrap(); + + Ok(()) + } + + type InnerSerializeValueSeq = + <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeSeq; + + #[doc(hidden)] + pub struct SerializeValueArray<'d> { + inner: InnerSerializeValueSeq, + dst: &'d mut String, + } + + impl<'d> SerializeValueArray<'d> { + pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueSeq) -> Self { + Self { + inner, + dst: ser.dst, + } + } + } + + impl<'d> serde::ser::SerializeSeq for SerializeValueArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTuple for SerializeValueArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTupleVariant for SerializeValueArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTupleStruct for SerializeValueArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + type InnerSerializeValueTable = + <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeMap; + + #[doc(hidden)] + pub struct SerializeValueTable<'d> { + inner: InnerSerializeValueTable, + dst: &'d mut String, + } + + impl<'d> SerializeValueTable<'d> { + pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueTable) -> Self { + Self { + inner, + dst: ser.dst, + } + } + } + + impl<'d> serde::ser::SerializeMap for SerializeValueTable<'d> { + type Ok = (); + type Error = Error; + + fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_key(input).map_err(Error::wrap) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_value(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeStruct for SerializeValueTable<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(key, value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + pub(crate) fn write_value( + dst: &mut String, + value: Result<toml_edit::Value, crate::edit::ser::Error>, + ) -> Result<(), Error> { + use std::fmt::Write; + + let value = value.map_err(Error::wrap)?; + + write!(dst, "{}", value).unwrap(); + + Ok(()) + } +} diff --git a/vendor/toml/src/table.rs b/vendor/toml/src/table.rs new file mode 100644 index 000000000..a2d392bde --- /dev/null +++ b/vendor/toml/src/table.rs @@ -0,0 +1,114 @@ +use std::fmt; + +use serde::de; +use serde::ser; + +use crate::map::Map; +use crate::Value; + +/// Type representing a TOML table, payload of the `Value::Table` variant. +/// By default it is backed by a BTreeMap, enable the `preserve_order` feature +/// to use a LinkedHashMap instead. +pub type Table = Map<String, Value>; + +impl Table { + /// Convert a `T` into `toml::Table`. + /// + /// This conversion can fail if `T`'s implementation of `Serialize` decides to + /// fail, or if `T` contains a map with non-string keys. + pub fn try_from<T>(value: T) -> Result<Self, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(crate::value::TableSerializer) + } + + /// Interpret a `toml::Table` as an instance of type `T`. + /// + /// This conversion can fail if the structure of the `Table` does not match the structure + /// expected by `T`, for example if `T` is a bool which can't be mapped to a `Table`. It can + /// also fail if the structure is correct but `T`'s implementation of `Deserialize` decides + /// that something is wrong with the data, for example required struct fields are missing from + /// the TOML map or some number is too big to fit in the expected primitive type. + pub fn try_into<'de, T>(self) -> Result<T, crate::de::Error> + where + T: de::Deserialize<'de>, + { + de::Deserialize::deserialize(self) + } +} + +#[cfg(feature = "display")] +impl fmt::Display for Table { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + crate::ser::to_string(self) + .expect("Unable to represent value as string") + .fmt(f) + } +} + +#[cfg(feature = "parse")] +impl std::str::FromStr for Table { + type Err = crate::de::Error; + fn from_str(s: &str) -> Result<Self, Self::Err> { + crate::from_str(s) + } +} + +impl<'de> de::Deserializer<'de> for Table { + type Error = crate::de::Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + Value::Table(self).deserialize_any(visitor) + } + + #[inline] + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + Value::Table(self).deserialize_enum(name, variants, visitor) + } + + // `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, crate::de::Error> + where + V: de::Visitor<'de>, + { + Value::Table(self).deserialize_option(visitor) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + Value::Table(self).deserialize_newtype_struct(name, visitor) + } + + serde::forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq + bytes byte_buf map unit_struct tuple_struct struct + tuple ignored_any identifier + } +} + +impl<'de> de::IntoDeserializer<'de, crate::de::Error> for Table { + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} diff --git a/vendor/toml/src/value.rs b/vendor/toml/src/value.rs new file mode 100644 index 000000000..8ed75e819 --- /dev/null +++ b/vendor/toml/src/value.rs @@ -0,0 +1,1308 @@ +//! Definition of a TOML [value][Value] + +use std::collections::{BTreeMap, HashMap}; +use std::fmt; +use std::hash::Hash; +use std::mem::discriminant; +use std::ops; +use std::vec; + +use serde::de; +use serde::de::IntoDeserializer; +use serde::ser; + +use toml_datetime::__unstable as datetime; +pub use toml_datetime::{Date, Datetime, DatetimeParseError, Offset, Time}; + +/// Type representing a TOML array, payload of the `Value::Array` variant +pub type Array = Vec<Value>; + +#[doc(no_inline)] +pub use crate::Table; + +/// Representation of a TOML value. +#[derive(PartialEq, Clone, Debug)] +pub enum Value { + /// Represents a TOML string + String(String), + /// Represents a TOML integer + Integer(i64), + /// Represents a TOML float + Float(f64), + /// Represents a TOML boolean + Boolean(bool), + /// Represents a TOML datetime + Datetime(Datetime), + /// Represents a TOML array + Array(Array), + /// Represents a TOML table + Table(Table), +} + +impl Value { + /// Convert a `T` into `toml::Value` which is an enum that can represent + /// any valid TOML data. + /// + /// This conversion can fail if `T`'s implementation of `Serialize` decides to + /// fail, or if `T` contains a map with non-string keys. + pub fn try_from<T>(value: T) -> Result<Value, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(ValueSerializer) + } + + /// Interpret a `toml::Value` as an instance of type `T`. + /// + /// This conversion can fail if the structure of the `Value` does not match the + /// structure expected by `T`, for example if `T` is a struct type but the + /// `Value` contains something other than a TOML table. It can also fail if the + /// structure is correct but `T`'s implementation of `Deserialize` decides that + /// something is wrong with the data, for example required struct fields are + /// missing from the TOML map or some number is too big to fit in the expected + /// primitive type. + pub fn try_into<'de, T>(self) -> Result<T, crate::de::Error> + where + T: de::Deserialize<'de>, + { + de::Deserialize::deserialize(self) + } + + /// Index into a TOML array or map. A string index can be used to access a + /// value in a map, and a usize index can be used to access an element of an + /// array. + /// + /// Returns `None` if the type of `self` does not match the type of the + /// index, for example if the index is a string and `self` is an array or a + /// number. Also returns `None` if the given key does not exist in the map + /// or the given index is not within the bounds of the array. + pub fn get<I: Index>(&self, index: I) -> Option<&Value> { + index.index(self) + } + + /// Mutably index into a TOML array or map. A string index can be used to + /// access a value in a map, and a usize index can be used to access an + /// element of an array. + /// + /// Returns `None` if the type of `self` does not match the type of the + /// index, for example if the index is a string and `self` is an array or a + /// number. Also returns `None` if the given key does not exist in the map + /// or the given index is not within the bounds of the array. + pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Value> { + index.index_mut(self) + } + + /// Extracts the integer value if it is an integer. + pub fn as_integer(&self) -> Option<i64> { + match *self { + Value::Integer(i) => Some(i), + _ => None, + } + } + + /// Tests whether this value is an integer. + pub fn is_integer(&self) -> bool { + self.as_integer().is_some() + } + + /// Extracts the float value if it is a float. + pub fn as_float(&self) -> Option<f64> { + match *self { + Value::Float(f) => Some(f), + _ => None, + } + } + + /// Tests whether this value is a float. + pub fn is_float(&self) -> bool { + self.as_float().is_some() + } + + /// Extracts the boolean value if it is a boolean. + pub fn as_bool(&self) -> Option<bool> { + match *self { + Value::Boolean(b) => Some(b), + _ => None, + } + } + + /// Tests whether this value is a boolean. + pub fn is_bool(&self) -> bool { + self.as_bool().is_some() + } + + /// Extracts the string of this value if it is a string. + pub fn as_str(&self) -> Option<&str> { + match *self { + Value::String(ref s) => Some(&**s), + _ => None, + } + } + + /// Tests if this value is a string. + pub fn is_str(&self) -> bool { + self.as_str().is_some() + } + + /// Extracts the datetime value if it is a datetime. + /// + /// Note that a parsed TOML value will only contain ISO 8601 dates. An + /// example date is: + /// + /// ```notrust + /// 1979-05-27T07:32:00Z + /// ``` + pub fn as_datetime(&self) -> Option<&Datetime> { + match *self { + Value::Datetime(ref s) => Some(s), + _ => None, + } + } + + /// Tests whether this value is a datetime. + pub fn is_datetime(&self) -> bool { + self.as_datetime().is_some() + } + + /// Extracts the array value if it is an array. + pub fn as_array(&self) -> Option<&Vec<Value>> { + match *self { + Value::Array(ref s) => Some(s), + _ => None, + } + } + + /// Extracts the array value if it is an array. + pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> { + match *self { + Value::Array(ref mut s) => Some(s), + _ => None, + } + } + + /// Tests whether this value is an array. + pub fn is_array(&self) -> bool { + self.as_array().is_some() + } + + /// Extracts the table value if it is a table. + pub fn as_table(&self) -> Option<&Table> { + match *self { + Value::Table(ref s) => Some(s), + _ => None, + } + } + + /// Extracts the table value if it is a table. + pub fn as_table_mut(&mut self) -> Option<&mut Table> { + match *self { + Value::Table(ref mut s) => Some(s), + _ => None, + } + } + + /// Tests whether this value is a table. + pub fn is_table(&self) -> bool { + self.as_table().is_some() + } + + /// Tests whether this and another value have the same type. + pub fn same_type(&self, other: &Value) -> bool { + discriminant(self) == discriminant(other) + } + + /// Returns a human-readable representation of the type of this value. + pub fn type_str(&self) -> &'static str { + match *self { + Value::String(..) => "string", + Value::Integer(..) => "integer", + Value::Float(..) => "float", + Value::Boolean(..) => "boolean", + Value::Datetime(..) => "datetime", + Value::Array(..) => "array", + Value::Table(..) => "table", + } + } +} + +impl<I> ops::Index<I> for Value +where + I: Index, +{ + type Output = Value; + + fn index(&self, index: I) -> &Value { + self.get(index).expect("index not found") + } +} + +impl<I> ops::IndexMut<I> for Value +where + I: Index, +{ + fn index_mut(&mut self, index: I) -> &mut Value { + self.get_mut(index).expect("index not found") + } +} + +impl<'a> From<&'a str> for Value { + #[inline] + fn from(val: &'a str) -> Value { + Value::String(val.to_string()) + } +} + +impl<V: Into<Value>> From<Vec<V>> for Value { + fn from(val: Vec<V>) -> Value { + Value::Array(val.into_iter().map(|v| v.into()).collect()) + } +} + +impl<S: Into<String>, V: Into<Value>> From<BTreeMap<S, V>> for Value { + fn from(val: BTreeMap<S, V>) -> Value { + let table = val.into_iter().map(|(s, v)| (s.into(), v.into())).collect(); + + Value::Table(table) + } +} + +impl<S: Into<String> + Hash + Eq, V: Into<Value>> From<HashMap<S, V>> for Value { + fn from(val: HashMap<S, V>) -> Value { + let table = val.into_iter().map(|(s, v)| (s.into(), v.into())).collect(); + + Value::Table(table) + } +} + +macro_rules! impl_into_value { + ($variant:ident : $T:ty) => { + impl From<$T> for Value { + #[inline] + fn from(val: $T) -> Value { + Value::$variant(val.into()) + } + } + }; +} + +impl_into_value!(String: String); +impl_into_value!(Integer: i64); +impl_into_value!(Integer: i32); +impl_into_value!(Integer: i8); +impl_into_value!(Integer: u8); +impl_into_value!(Integer: u32); +impl_into_value!(Float: f64); +impl_into_value!(Float: f32); +impl_into_value!(Boolean: bool); +impl_into_value!(Datetime: Datetime); +impl_into_value!(Table: Table); + +/// Types that can be used to index a `toml::Value` +/// +/// Currently this is implemented for `usize` to index arrays and `str` to index +/// tables. +/// +/// This trait is sealed and not intended for implementation outside of the +/// `toml` crate. +pub trait Index: Sealed { + #[doc(hidden)] + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value>; + #[doc(hidden)] + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value>; +} + +/// An implementation detail that should not be implemented, this will change in +/// the future and break code otherwise. +#[doc(hidden)] +pub trait Sealed {} +impl Sealed for usize {} +impl Sealed for str {} +impl Sealed for String {} +impl<'a, T: Sealed + ?Sized> Sealed for &'a T {} + +impl Index for usize { + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { + match *val { + Value::Array(ref a) => a.get(*self), + _ => None, + } + } + + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { + match *val { + Value::Array(ref mut a) => a.get_mut(*self), + _ => None, + } + } +} + +impl Index for str { + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { + match *val { + Value::Table(ref a) => a.get(self), + _ => None, + } + } + + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { + match *val { + Value::Table(ref mut a) => a.get_mut(self), + _ => None, + } + } +} + +impl Index for String { + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { + self[..].index(val) + } + + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { + self[..].index_mut(val) + } +} + +impl<'s, T: ?Sized> Index for &'s T +where + T: Index, +{ + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { + (**self).index(val) + } + + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { + (**self).index_mut(val) + } +} + +#[cfg(feature = "display")] +impl fmt::Display for Value { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use serde::Serialize as _; + + let mut output = String::new(); + let serializer = crate::ser::ValueSerializer::new(&mut output); + self.serialize(serializer).unwrap(); + output.fmt(f) + } +} + +#[cfg(feature = "parse")] +impl std::str::FromStr for Value { + type Err = crate::de::Error; + fn from_str(s: &str) -> Result<Value, Self::Err> { + crate::from_str(s) + } +} + +impl ser::Serialize for Value { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + use serde::ser::SerializeMap; + + match *self { + Value::String(ref s) => serializer.serialize_str(s), + Value::Integer(i) => serializer.serialize_i64(i), + Value::Float(f) => serializer.serialize_f64(f), + Value::Boolean(b) => serializer.serialize_bool(b), + Value::Datetime(ref s) => s.serialize(serializer), + Value::Array(ref a) => a.serialize(serializer), + Value::Table(ref t) => { + let mut map = serializer.serialize_map(Some(t.len()))?; + // Be sure to visit non-tables first (and also non + // array-of-tables) as all keys must be emitted first. + for (k, v) in t { + if !v.is_table() && !v.is_array() + || (v + .as_array() + .map(|a| !a.iter().any(|v| v.is_table())) + .unwrap_or(false)) + { + map.serialize_entry(k, v)?; + } + } + for (k, v) in t { + if v.as_array() + .map(|a| a.iter().any(|v| v.is_table())) + .unwrap_or(false) + { + map.serialize_entry(k, v)?; + } + } + for (k, v) in t { + if v.is_table() { + map.serialize_entry(k, v)?; + } + } + map.end() + } + } + } +} + +impl<'de> de::Deserialize<'de> for Value { + fn deserialize<D>(deserializer: D) -> Result<Value, D::Error> + where + D: de::Deserializer<'de>, + { + struct ValueVisitor; + + impl<'de> de::Visitor<'de> for ValueVisitor { + type Value = Value; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("any valid TOML value") + } + + fn visit_bool<E>(self, value: bool) -> Result<Value, E> { + Ok(Value::Boolean(value)) + } + + fn visit_i64<E>(self, value: i64) -> Result<Value, E> { + Ok(Value::Integer(value)) + } + + fn visit_u64<E: de::Error>(self, value: u64) -> Result<Value, E> { + if value <= i64::max_value() as u64 { + Ok(Value::Integer(value as i64)) + } else { + Err(de::Error::custom("u64 value was too large")) + } + } + + fn visit_u32<E>(self, value: u32) -> Result<Value, E> { + Ok(Value::Integer(value.into())) + } + + fn visit_i32<E>(self, value: i32) -> Result<Value, E> { + Ok(Value::Integer(value.into())) + } + + fn visit_f64<E>(self, value: f64) -> Result<Value, E> { + Ok(Value::Float(value)) + } + + fn visit_str<E>(self, value: &str) -> Result<Value, E> { + Ok(Value::String(value.into())) + } + + fn visit_string<E>(self, value: String) -> Result<Value, E> { + Ok(Value::String(value)) + } + + fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error> + where + D: de::Deserializer<'de>, + { + de::Deserialize::deserialize(deserializer) + } + + fn visit_seq<V>(self, mut visitor: V) -> Result<Value, V::Error> + where + V: de::SeqAccess<'de>, + { + let mut vec = Vec::new(); + while let Some(elem) = visitor.next_element()? { + vec.push(elem); + } + Ok(Value::Array(vec)) + } + + fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error> + where + V: de::MapAccess<'de>, + { + let mut key = String::new(); + let datetime = visitor.next_key_seed(DatetimeOrTable { key: &mut key })?; + match datetime { + Some(true) => { + let date: datetime::DatetimeFromString = visitor.next_value()?; + return Ok(Value::Datetime(date.value)); + } + None => return Ok(Value::Table(Table::new())), + Some(false) => {} + } + let mut map = Table::new(); + map.insert(key, visitor.next_value()?); + while let Some(key) = visitor.next_key::<String>()? { + if let crate::map::Entry::Vacant(vacant) = map.entry(&key) { + vacant.insert(visitor.next_value()?); + } else { + let msg = format!("duplicate key: `{}`", key); + return Err(de::Error::custom(msg)); + } + } + Ok(Value::Table(map)) + } + } + + deserializer.deserialize_any(ValueVisitor) + } +} + +// This is wrapped by `Table` and any trait methods implemented here need to be wrapped there. +impl<'de> de::Deserializer<'de> for Value { + type Error = crate::de::Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + match self { + Value::Boolean(v) => visitor.visit_bool(v), + Value::Integer(n) => visitor.visit_i64(n), + Value::Float(n) => visitor.visit_f64(n), + Value::String(v) => visitor.visit_string(v), + Value::Datetime(v) => visitor.visit_string(v.to_string()), + Value::Array(v) => { + let len = v.len(); + let mut deserializer = SeqDeserializer::new(v); + let seq = visitor.visit_seq(&mut deserializer)?; + let remaining = deserializer.iter.len(); + if remaining == 0 { + Ok(seq) + } else { + Err(de::Error::invalid_length(len, &"fewer elements in array")) + } + } + Value::Table(v) => { + let len = v.len(); + let mut deserializer = MapDeserializer::new(v); + let map = visitor.visit_map(&mut deserializer)?; + let remaining = deserializer.iter.len(); + if remaining == 0 { + Ok(map) + } else { + Err(de::Error::invalid_length(len, &"fewer elements in map")) + } + } + } + } + + #[inline] + fn deserialize_enum<V>( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + match self { + Value::String(variant) => visitor.visit_enum(variant.into_deserializer()), + _ => Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"string only", + )), + } + } + + // `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, crate::de::Error> + where + V: de::Visitor<'de>, + { + visitor.visit_some(self) + } + + fn deserialize_newtype_struct<V>( + self, + _name: &'static str, + visitor: V, + ) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + serde::forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq + bytes byte_buf map unit_struct tuple_struct struct + tuple ignored_any identifier + } +} + +struct SeqDeserializer { + iter: vec::IntoIter<Value>, +} + +impl SeqDeserializer { + fn new(vec: Vec<Value>) -> Self { + SeqDeserializer { + iter: vec.into_iter(), + } + } +} + +impl<'de> de::SeqAccess<'de> for SeqDeserializer { + type Error = crate::de::Error; + + fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, crate::de::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => seed.deserialize(value).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> Option<usize> { + match self.iter.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +struct MapDeserializer { + iter: <Table as IntoIterator>::IntoIter, + value: Option<(String, Value)>, +} + +impl MapDeserializer { + fn new(map: Table) -> Self { + MapDeserializer { + iter: map.into_iter(), + value: None, + } + } +} + +impl<'de> de::MapAccess<'de> for MapDeserializer { + type Error = crate::de::Error; + + fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, crate::de::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some((key, value)) => { + self.value = Some((key.clone(), value)); + seed.deserialize(Value::String(key)).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, crate::de::Error> + where + T: de::DeserializeSeed<'de>, + { + let (key, res) = match self.value.take() { + Some((key, value)) => (key, seed.deserialize(value)), + None => return Err(de::Error::custom("value is missing")), + }; + res.map_err(|mut error| { + error.add_key(key); + error + }) + } + + fn size_hint(&self) -> Option<usize> { + match self.iter.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +impl<'de> de::IntoDeserializer<'de, crate::de::Error> for Value { + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + +struct ValueSerializer; + +impl ser::Serializer for ValueSerializer { + type Ok = Value; + type Error = crate::ser::Error; + + type SerializeSeq = ValueSerializeVec; + type SerializeTuple = ValueSerializeVec; + type SerializeTupleStruct = ValueSerializeVec; + type SerializeTupleVariant = ValueSerializeVec; + type SerializeMap = ValueSerializeMap; + type SerializeStruct = ValueSerializeMap; + type SerializeStructVariant = ser::Impossible<Value, crate::ser::Error>; + + fn serialize_bool(self, value: bool) -> Result<Value, crate::ser::Error> { + Ok(Value::Boolean(value)) + } + + fn serialize_i8(self, value: i8) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_i16(self, value: i16) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_i32(self, value: i32) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_i64(self, value: i64) -> Result<Value, crate::ser::Error> { + Ok(Value::Integer(value)) + } + + fn serialize_u8(self, value: u8) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_u16(self, value: u16) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_u32(self, value: u32) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_u64(self, value: u64) -> Result<Value, crate::ser::Error> { + if value <= i64::max_value() as u64 { + self.serialize_i64(value as i64) + } else { + Err(ser::Error::custom("u64 value was too large")) + } + } + + fn serialize_f32(self, value: f32) -> Result<Value, crate::ser::Error> { + self.serialize_f64(value.into()) + } + + fn serialize_f64(self, value: f64) -> Result<Value, crate::ser::Error> { + Ok(Value::Float(value)) + } + + fn serialize_char(self, value: char) -> Result<Value, crate::ser::Error> { + let mut s = String::new(); + s.push(value); + self.serialize_str(&s) + } + + fn serialize_str(self, value: &str) -> Result<Value, crate::ser::Error> { + Ok(Value::String(value.to_owned())) + } + + fn serialize_bytes(self, value: &[u8]) -> Result<Value, crate::ser::Error> { + let vec = value.iter().map(|&b| Value::Integer(b.into())).collect(); + Ok(Value::Array(vec)) + } + + fn serialize_unit(self) -> Result<Value, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some("unit"))) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Value, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result<Value, crate::ser::Error> { + self.serialize_str(_variant) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + value: &T, + ) -> Result<Value, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result<Value, crate::ser::Error> + where + T: ser::Serialize, + { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_none(self) -> Result<Value, crate::ser::Error> { + Err(crate::ser::Error::unsupported_none()) + } + + fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Value, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(self) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, crate::ser::Error> { + Ok(ValueSerializeVec { + vec: Vec::with_capacity(len.unwrap_or(0)), + }) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, crate::ser::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, crate::ser::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, crate::ser::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, crate::ser::Error> { + Ok(ValueSerializeMap { + ser: SerializeMap { + map: Table::new(), + next_key: None, + }, + }) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, crate::ser::Error> { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } +} + +pub(crate) struct TableSerializer; + +impl ser::Serializer for TableSerializer { + type Ok = Table; + type Error = crate::ser::Error; + + type SerializeSeq = ser::Impossible<Table, crate::ser::Error>; + type SerializeTuple = ser::Impossible<Table, crate::ser::Error>; + type SerializeTupleStruct = ser::Impossible<Table, crate::ser::Error>; + type SerializeTupleVariant = ser::Impossible<Table, crate::ser::Error>; + type SerializeMap = SerializeMap; + type SerializeStruct = SerializeMap; + type SerializeStructVariant = ser::Impossible<Table, crate::ser::Error>; + + fn serialize_bool(self, _value: bool) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_i8(self, _value: i8) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_i16(self, _value: i16) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_i32(self, _value: i32) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_i64(self, _value: i64) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_u8(self, _value: u8) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_u16(self, _value: u16) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_u32(self, _value: u32) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_u64(self, _value: u64) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_f32(self, _value: f32) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_f64(self, _value: f64) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_char(self, _value: char) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_str(self, _value: &str) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_unit(self) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_unit_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + value: &T, + ) -> Result<Table, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result<Table, crate::ser::Error> + where + T: ser::Serialize, + { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_none(self) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_none()) + } + + fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Table, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(self) + } + + fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleStruct, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_tuple_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleVariant, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, crate::ser::Error> { + Ok(SerializeMap { + map: Table::new(), + next_key: None, + }) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, crate::ser::Error> { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } +} + +struct ValueSerializeVec { + vec: Vec<Value>, +} + +impl ser::SerializeSeq for ValueSerializeVec { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + self.vec.push(Value::try_from(value)?); + Ok(()) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + Ok(Value::Array(self.vec)) + } +} + +impl ser::SerializeTuple for ValueSerializeVec { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + ser::SerializeSeq::end(self) + } +} + +impl ser::SerializeTupleStruct for ValueSerializeVec { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + ser::SerializeSeq::end(self) + } +} + +impl ser::SerializeTupleVariant for ValueSerializeVec { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + ser::SerializeSeq::end(self) + } +} + +pub(crate) struct SerializeMap { + map: Table, + next_key: Option<String>, +} + +impl ser::SerializeMap for SerializeMap { + type Ok = Table; + type Error = crate::ser::Error; + + fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + match Value::try_from(key)? { + Value::String(s) => self.next_key = Some(s), + _ => return Err(crate::ser::Error::key_not_string()), + }; + Ok(()) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + let key = self.next_key.take(); + let key = key.expect("serialize_value called before serialize_key"); + match Value::try_from(value) { + Ok(value) => { + self.map.insert(key, value); + } + Err(crate::ser::Error { + inner: crate::edit::ser::Error::UnsupportedNone, + }) => {} + Err(e) => return Err(e), + } + Ok(()) + } + + fn end(self) -> Result<Table, crate::ser::Error> { + Ok(self.map) + } +} + +impl ser::SerializeStruct for SerializeMap { + type Ok = Table; + type Error = crate::ser::Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeMap::serialize_key(self, key)?; + ser::SerializeMap::serialize_value(self, value) + } + + fn end(self) -> Result<Table, crate::ser::Error> { + ser::SerializeMap::end(self) + } +} + +struct ValueSerializeMap { + ser: SerializeMap, +} + +impl ser::SerializeMap for ValueSerializeMap { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + self.ser.serialize_key(key) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + self.ser.serialize_value(value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + self.ser.end().map(Value::Table) + } +} + +impl ser::SerializeStruct for ValueSerializeMap { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeMap::serialize_key(self, key)?; + ser::SerializeMap::serialize_value(self, value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + ser::SerializeMap::end(self) + } +} + +struct DatetimeOrTable<'a> { + key: &'a mut String, +} + +impl<'a, 'de> de::DeserializeSeed<'de> for DatetimeOrTable<'a> { + type Value = bool; + + fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + deserializer.deserialize_any(self) + } +} + +impl<'a, 'de> de::Visitor<'de> for DatetimeOrTable<'a> { + type Value = bool; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a string key") + } + + fn visit_str<E>(self, s: &str) -> Result<bool, E> + where + E: de::Error, + { + if s == datetime::FIELD { + Ok(true) + } else { + self.key.push_str(s); + Ok(false) + } + } + + fn visit_string<E>(self, s: String) -> Result<bool, E> + where + E: de::Error, + { + if s == datetime::FIELD { + Ok(true) + } else { + *self.key = s; + Ok(false) + } + } +} |