feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support: - Splash screen on boot (1.5s) with project name, version, board - Dashboard showing radio state, config, counters, RSSI/SNR - RSSI history sparkline (64-sample ring buffer, 2px-wide bars) - DisplayOn/DisplayOff host commands routed via dedicated channel - Pure render functions against generic DrawTarget (no hardware coupling) - Display on/off control bypasses radio task entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
17624 files changed
+4564928
-38
No files matched your search
Vendored
+313
@@ -0,0 +1,313 @@
|
||||
//! 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(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::fmt::Debug 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> serde::Deserializer<'de> for Deserializer<'_> {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: serde::de::Visitor<'de>,
|
||||
{
|
||||
let inner = toml_edit::de::Deserializer::parse(self.input).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 = toml_edit::de::Deserializer::parse(self.input).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 = toml_edit::de::Deserializer::parse(self.input).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 = toml_edit::de::Deserializer::parse(self.input).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 = toml_edit::de::Deserializer::parse(self.input).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> serde::Deserializer<'de> for ValueDeserializer<'_> {
|
||||
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
|
||||
}
|
||||
}
|
||||
Vendored
+91
@@ -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(crate) struct Error {
|
||||
inner: String,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Add key while unwinding
|
||||
pub(crate) fn add_key(&mut self, _key: String) {}
|
||||
|
||||
/// What went wrong
|
||||
pub(crate) 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 {}
|
||||
}
|
||||
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub(crate) struct DocumentFormatter {
|
||||
pub(crate) multiline_array: bool,
|
||||
is_value: bool,
|
||||
}
|
||||
|
||||
impl toml_edit::visit_mut::VisitMut for DocumentFormatter {
|
||||
fn visit_document_mut(&mut self, node: &mut toml_edit::DocumentMut) {
|
||||
toml_edit::visit_mut::visit_document_mut(self, node);
|
||||
}
|
||||
|
||||
fn visit_item_mut(&mut self, node: &mut toml_edit::Item) {
|
||||
let is_parent_value = self.is_value;
|
||||
if !is_parent_value {
|
||||
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,
|
||||
};
|
||||
self.is_value = other.is_value();
|
||||
*node = other;
|
||||
}
|
||||
|
||||
toml_edit::visit_mut::visit_item_mut(self, node);
|
||||
self.is_value = is_parent_value;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+185
@@ -0,0 +1,185 @@
|
||||
//! A [serde]-compatible [TOML]-parsing library
|
||||
//!
|
||||
//! TOML itself is a simple, ergonomic, and readable configuration format:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [package]
|
||||
//! name = "toml"
|
||||
//!
|
||||
//! [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/
|
||||
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
// 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)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(clippy::print_stderr)]
|
||||
#![warn(clippy::print_stdout)]
|
||||
|
||||
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;
|
||||
|
||||
#[doc = include_str!("../README.md")]
|
||||
#[cfg(doctest)]
|
||||
pub struct ReadmeDoctests;
|
||||
Vendored
+455
@@ -0,0 +1,455 @@
|
||||
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"
|
||||
///
|
||||
/// [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.copysign(-1.0))
|
||||
};
|
||||
|
||||
(@value (nan)) => {
|
||||
$crate::Value::Float(::std::f64::NAN.copysign(1.0))
|
||||
};
|
||||
|
||||
(@value nan) => {
|
||||
$crate::Value::Float(::std::f64::NAN.copysign(1.0))
|
||||
};
|
||||
|
||||
(@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
|
||||
}
|
||||
Vendored
+636
@@ -0,0 +1,636 @@
|
||||
// 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>(&self, key: &Q) -> Option<&Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
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>(&self, key: &Q) -> bool
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
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>(&mut self, key: &Q) -> Option<&mut Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
self.map.get_mut(key)
|
||||
}
|
||||
|
||||
/// Returns the key-value pair matching the given 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_key_value<Q>(&self, key: &Q) -> Option<(&String, &Value)>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: ?Sized + Ord + Eq + Hash,
|
||||
{
|
||||
self.map.get_key_value(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>(&mut self, key: &Q) -> Option<Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
{
|
||||
self.map.remove(key)
|
||||
}
|
||||
#[cfg(feature = "preserve_order")]
|
||||
{
|
||||
self.map.shift_remove(key)
|
||||
}
|
||||
}
|
||||
|
||||
/// Retains only the elements specified by the `keep` predicate.
|
||||
///
|
||||
/// In other words, remove all pairs `(k, v)` for which `keep(&k, &mut v)`
|
||||
/// returns `false`.
|
||||
///
|
||||
/// The elements are visited in iteration order.
|
||||
#[inline]
|
||||
pub fn retain<F>(&mut self, mut keep: F)
|
||||
where
|
||||
F: FnMut(&str, &mut Value) -> bool,
|
||||
{
|
||||
self.map.retain(|key, value| keep(key.as_str(), value));
|
||||
}
|
||||
|
||||
/// 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<Q> ops::Index<&Q> for Map<String, Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
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<Q> ops::IndexMut<&Q> for Map<String, Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
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 {
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
{
|
||||
self.occupied.remove()
|
||||
}
|
||||
#[cfg(feature = "preserve_order")]
|
||||
{
|
||||
self.occupied.shift_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);
|
||||
Vendored
+107
@@ -0,0 +1,107 @@
|
||||
use super::write_document;
|
||||
use super::{Error, Serializer};
|
||||
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 serde::ser::SerializeSeq for SerializeDocumentArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeTuple for SerializeDocumentArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeTupleStruct for SerializeDocumentArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 InnerSerializeDocumentTupleVariant =
|
||||
<toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeTupleVariant;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeDocumentTupleVariant<'d> {
|
||||
inner: InnerSerializeDocumentTupleVariant,
|
||||
dst: &'d mut String,
|
||||
settings: DocumentFormatter,
|
||||
}
|
||||
|
||||
impl<'d> SerializeDocumentTupleVariant<'d> {
|
||||
pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentTupleVariant) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
dst: ser.dst,
|
||||
settings: ser.settings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeTupleVariant for SerializeDocumentTupleVariant<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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())
|
||||
}
|
||||
}
|
||||
Vendored
+118
@@ -0,0 +1,118 @@
|
||||
use super::write_document;
|
||||
use super::{Error, Serializer};
|
||||
use crate::fmt::DocumentFormatter;
|
||||
|
||||
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 serde::ser::SerializeMap for SerializeDocumentTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_key<T>(&mut self, input: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_key(input).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeStruct for SerializeDocumentTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStructVariant for SerializeDocumentTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
serde::ser::SerializeStruct::serialize_field(self, key, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
serde::ser::SerializeStruct::end(self)
|
||||
}
|
||||
}
|
||||
|
||||
type InnerSerializeDocumentStructVariant =
|
||||
<toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeStructVariant;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeDocumentStructVariant<'d> {
|
||||
inner: InnerSerializeDocumentStructVariant,
|
||||
dst: &'d mut String,
|
||||
settings: DocumentFormatter,
|
||||
}
|
||||
|
||||
impl<'d> SerializeDocumentStructVariant<'d> {
|
||||
pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentStructVariant) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
dst: ser.dst,
|
||||
settings: ser.settings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStructVariant for SerializeDocumentStructVariant<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_field(key, value).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
write_document(self.dst, self.settings, self.inner.end())
|
||||
}
|
||||
}
|
||||
Vendored
+484
@@ -0,0 +1,484 @@
|
||||
//! 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.
|
||||
|
||||
#[cfg(feature = "display")]
|
||||
mod array;
|
||||
#[cfg(feature = "display")]
|
||||
mod map;
|
||||
#[cfg(feature = "display")]
|
||||
mod ser_value;
|
||||
|
||||
#[cfg(feature = "display")]
|
||||
pub use ser_value::ValueSerializer;
|
||||
|
||||
/// 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>(value: &T) -> Result<String, Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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::DocumentMut`](https://docs.rs/toml_edit/latest/toml_edit/struct.DocumentMut.html).
|
||||
#[cfg(feature = "display")]
|
||||
pub fn to_string_pretty<T>(value: &T) -> Result<String, Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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(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::fmt::Debug 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`].
|
||||
#[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::DocumentMut`](https://docs.rs/toml_edit/latest/toml_edit/struct.DocumentMut.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 = array::SerializeDocumentArray<'d>;
|
||||
type SerializeTuple = array::SerializeDocumentArray<'d>;
|
||||
type SerializeTupleStruct = array::SerializeDocumentArray<'d>;
|
||||
type SerializeTupleVariant = array::SerializeDocumentTupleVariant<'d>;
|
||||
type SerializeMap = map::SerializeDocumentTable<'d>;
|
||||
type SerializeStruct = map::SerializeDocumentTable<'d>;
|
||||
type SerializeStructVariant = map::SerializeDocumentStructVariant<'d>;
|
||||
|
||||
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>(self, v: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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>(self, name: &'static str, v: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
write_document(
|
||||
self.dst,
|
||||
self.settings,
|
||||
toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v),
|
||||
)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 = array::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> {
|
||||
let ser = toml_edit::ser::ValueSerializer::new()
|
||||
.serialize_tuple_variant(name, variant_index, variant, len)
|
||||
.map_err(Error::wrap)?;
|
||||
let ser = array::SerializeDocumentTupleVariant::new(self, ser);
|
||||
Ok(ser)
|
||||
}
|
||||
|
||||
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 = map::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> {
|
||||
let ser = toml_edit::ser::ValueSerializer::new()
|
||||
.serialize_struct_variant(name, variant_index, variant, len)
|
||||
.map_err(Error::wrap)?;
|
||||
let ser = map::SerializeDocumentStructVariant::new(self, ser);
|
||||
Ok(ser)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "display")]
|
||||
pub(crate) fn write_document(
|
||||
dst: &mut String,
|
||||
mut settings: crate::fmt::DocumentFormatter,
|
||||
value: Result<toml_edit::Value, crate::edit::ser::Error>,
|
||||
) -> Result<(), Error> {
|
||||
use std::fmt::Write;
|
||||
use toml_edit::visit_mut::VisitMut as _;
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
settings.visit_table_mut(&mut table);
|
||||
|
||||
let doc: toml_edit::DocumentMut = table.into();
|
||||
write!(dst, "{doc}").unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
use super::write_value;
|
||||
use super::{Error, ValueSerializer};
|
||||
|
||||
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 serde::ser::SerializeSeq for SerializeValueArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeTuple for SerializeValueArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeTupleStruct for SerializeValueArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 InnerSerializeValueTupleVariant =
|
||||
<toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeTupleVariant;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeValueTupleVariant<'d> {
|
||||
inner: InnerSerializeValueTupleVariant,
|
||||
dst: &'d mut String,
|
||||
}
|
||||
|
||||
impl<'d> SerializeValueTupleVariant<'d> {
|
||||
pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueTupleVariant) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
dst: ser.dst,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeTupleVariant for SerializeValueTupleVariant<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_field(value).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
write_value(self.dst, self.inner.end())
|
||||
}
|
||||
}
|
||||
Vendored
+95
@@ -0,0 +1,95 @@
|
||||
use super::write_value;
|
||||
use super::{Error, ValueSerializer};
|
||||
|
||||
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 serde::ser::SerializeMap for SerializeValueTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_key<T>(&mut self, input: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_key(input).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeStruct for SerializeValueTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
type InnerSerializeValueStructVariant =
|
||||
<toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeStructVariant;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeValueStructVariant<'d> {
|
||||
inner: InnerSerializeValueStructVariant,
|
||||
dst: &'d mut String,
|
||||
}
|
||||
|
||||
impl<'d> SerializeValueStructVariant<'d> {
|
||||
pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueStructVariant) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
dst: ser.dst,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStructVariant for SerializeValueStructVariant<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_field(key, value).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
write_value(self.dst, self.inner.end())
|
||||
}
|
||||
}
|
||||
Vendored
+328
@@ -0,0 +1,328 @@
|
||||
mod array;
|
||||
mod map;
|
||||
|
||||
use super::Error;
|
||||
|
||||
/// 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)
|
||||
/// ```
|
||||
#[cfg(feature = "display")]
|
||||
pub struct ValueSerializer<'d> {
|
||||
dst: &'d mut String,
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> serde::ser::Serializer for ValueSerializer<'d> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type SerializeSeq = array::SerializeValueArray<'d>;
|
||||
type SerializeTuple = array::SerializeValueArray<'d>;
|
||||
type SerializeTupleStruct = array::SerializeValueArray<'d>;
|
||||
type SerializeTupleVariant = array::SerializeValueTupleVariant<'d>;
|
||||
type SerializeMap = map::SerializeValueTable<'d>;
|
||||
type SerializeStruct = map::SerializeValueTable<'d>;
|
||||
type SerializeStructVariant = map::SerializeValueStructVariant<'d>;
|
||||
|
||||
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>(self, v: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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>(self, name: &'static str, v: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
write_value(
|
||||
self.dst,
|
||||
toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v),
|
||||
)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 = array::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> {
|
||||
let ser = toml_edit::ser::ValueSerializer::new()
|
||||
.serialize_tuple_variant(name, variant_index, variant, len)
|
||||
.map_err(Error::wrap)?;
|
||||
let ser = array::SerializeValueTupleVariant::new(self, ser);
|
||||
Ok(ser)
|
||||
}
|
||||
|
||||
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 = map::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> {
|
||||
let ser = toml_edit::ser::ValueSerializer::new()
|
||||
.serialize_struct_variant(name, variant_index, variant, len)
|
||||
.map_err(Error::wrap)?;
|
||||
let ser = map::SerializeValueStructVariant::new(self, ser);
|
||||
Ok(ser)
|
||||
}
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
Vendored
+115
@@ -0,0 +1,115 @@
|
||||
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 entries are stored in
|
||||
/// [lexicographic order](https://doc.rust-lang.org/std/primitive.str.html#impl-Ord-for-str)
|
||||
/// of the keys. Enable the `preserve_order` feature to store entries in the order they appear in
|
||||
/// the source file.
|
||||
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 std::fmt::Display for Table {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::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::IntoDeserializer<'_, crate::de::Error> for Table {
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
Vendored
+1495
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user