//! Serializing Rust structures into TOML. //! //! This module contains all the Serde support for serializing Rust structures into TOML. mod array; mod key; mod map; mod pretty; mod value; pub(crate) use array::*; pub(crate) use key::*; pub(crate) use map::*; use crate::visit_mut::VisitMut; /// Errors that can occur when deserializing a type. #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum Error { /// Type could not be serialized to TOML UnsupportedType(Option<&'static str>), /// Value was out of range for the given type OutOfRange(Option<&'static str>), /// `None` could not be serialized to TOML UnsupportedNone, /// Key was not convertible to `String` for serializing to TOML KeyNotString, /// A serialized date was invalid DateInvalid, /// Other serialization error Custom(String), } impl Error { pub(crate) fn custom(msg: T) -> Self where T: std::fmt::Display, { Error::Custom(msg.to_string()) } } impl serde::ser::Error for Error { fn custom(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::OutOfRange(Some(t)) => write!(formatter, "out-of-range value for {t} type"), Self::OutOfRange(None) => write!(formatter, "out-of-range value"), Self::UnsupportedNone => "unsupported None value".fmt(formatter), Self::KeyNotString => "map key was not a string".fmt(formatter), Self::DateInvalid => "a serialized date was invalid".fmt(formatter), Self::Custom(s) => s.fmt(formatter), } } } impl From for Error { fn from(e: crate::TomlError) -> Error { Self::custom(e) } } impl From for crate::TomlError { fn from(e: Error) -> crate::TomlError { Self::custom(e.to_string(), None) } } impl std::error::Error for Error {} /// Serialize the given data structure as a TOML byte vector. /// /// 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. #[cfg(feature = "display")] pub fn to_vec(value: &T) -> Result, Error> where T: serde::ser::Serialize, { to_string(value).map(|e| e.into_bytes()) } /// 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. /// /// # Examples /// /// ``` /// use serde::Serialize; /// /// #[derive(Serialize)] /// struct Config { /// database: Database, /// } /// /// #[derive(Serialize)] /// struct Database { /// ip: String, /// port: Vec, /// 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_edit::ser::to_string(&config).unwrap(); /// println!("{}", toml) /// ``` #[cfg(feature = "display")] pub fn to_string(value: &T) -> Result where T: serde::ser::Serialize, { to_document(value).map(|e| e.to_string()) } /// 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 `ValueSerializer::pretty` for more details. #[cfg(feature = "display")] pub fn to_string_pretty(value: &T) -> Result where T: serde::ser::Serialize, { let mut document = to_document(value)?; pretty::Pretty.visit_document_mut(&mut document); Ok(document.to_string()) } /// Serialize the given data structure into a TOML document. /// /// This would allow custom formatting to be applied, mixing with format preserving edits, etc. pub fn to_document(value: &T) -> Result where T: serde::ser::Serialize, { let value = value.serialize(ValueSerializer::new())?; let item = crate::Item::Value(value); let root = item .into_table() .map_err(|_| Error::UnsupportedType(None))?; Ok(root.into()) } pub use value::ValueSerializer;