toml_edit/ser/
mod.rs

1//! Serializing Rust structures into TOML.
2//!
3//! This module contains all the Serde support for serializing Rust structures into TOML.
4
5mod array;
6mod key;
7mod map;
8mod pretty;
9mod value;
10
11pub(crate) use array::*;
12pub(crate) use key::*;
13pub(crate) use map::*;
14
15use crate::visit_mut::VisitMut;
16
17/// Errors that can occur when deserializing a type.
18#[derive(Debug, Clone, PartialEq, Eq)]
19#[non_exhaustive]
20pub enum Error {
21    /// Type could not be serialized to TOML
22    UnsupportedType(Option<&'static str>),
23    /// `None` could not be serialized to TOML
24    UnsupportedNone,
25    /// Key was not convertable to `String` for serializing to TOML
26    KeyNotString,
27    /// A serialized date was invalid
28    DateInvalid,
29    /// Other serialization error
30    Custom(String),
31}
32
33impl Error {
34    pub(crate) fn custom<T>(msg: T) -> Self
35    where
36        T: std::fmt::Display,
37    {
38        Error::Custom(msg.to_string())
39    }
40}
41
42impl serde::ser::Error for Error {
43    fn custom<T>(msg: T) -> Self
44    where
45        T: std::fmt::Display,
46    {
47        Self::custom(msg)
48    }
49}
50
51impl std::fmt::Display for Error {
52    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
53        match self {
54            Self::UnsupportedType(Some(t)) => write!(formatter, "unsupported {t} type"),
55            Self::UnsupportedType(None) => write!(formatter, "unsupported rust type"),
56            Self::UnsupportedNone => "unsupported None value".fmt(formatter),
57            Self::KeyNotString => "map key was not a string".fmt(formatter),
58            Self::DateInvalid => "a serialized date was invalid".fmt(formatter),
59            Self::Custom(s) => s.fmt(formatter),
60        }
61    }
62}
63
64impl From<crate::TomlError> for Error {
65    fn from(e: crate::TomlError) -> Error {
66        Self::custom(e)
67    }
68}
69
70impl From<Error> for crate::TomlError {
71    fn from(e: Error) -> crate::TomlError {
72        Self::custom(e.to_string(), None)
73    }
74}
75
76impl std::error::Error for Error {}
77
78/// Serialize the given data structure as a TOML byte vector.
79///
80/// Serialization can fail if `T`'s implementation of `Serialize` decides to
81/// fail, if `T` contains a map with non-string keys, or if `T` attempts to
82/// serialize an unsupported datatype such as an enum, tuple, or tuple struct.
83pub fn to_vec<T: ?Sized>(value: &T) -> Result<Vec<u8>, Error>
84where
85    T: serde::ser::Serialize,
86{
87    to_string(value).map(|e| e.into_bytes())
88}
89
90/// Serialize the given data structure as a String of TOML.
91///
92/// Serialization can fail if `T`'s implementation of `Serialize` decides to
93/// fail, if `T` contains a map with non-string keys, or if `T` attempts to
94/// serialize an unsupported datatype such as an enum, tuple, or tuple struct.
95///
96/// # Examples
97///
98/// ```
99/// use serde::Serialize;
100///
101/// #[derive(Serialize)]
102/// struct Config {
103///     database: Database,
104/// }
105///
106/// #[derive(Serialize)]
107/// struct Database {
108///     ip: String,
109///     port: Vec<u16>,
110///     connection_max: u32,
111///     enabled: bool,
112/// }
113///
114/// let config = Config {
115///     database: Database {
116///         ip: "192.168.1.1".to_string(),
117///         port: vec![8001, 8002, 8003],
118///         connection_max: 5000,
119///         enabled: false,
120///     },
121/// };
122///
123/// let toml = toml_edit::ser::to_string(&config).unwrap();
124/// println!("{}", toml)
125/// ```
126pub fn to_string<T: ?Sized>(value: &T) -> Result<String, Error>
127where
128    T: serde::ser::Serialize,
129{
130    to_document(value).map(|e| e.to_string())
131}
132
133/// Serialize the given data structure as a "pretty" String of TOML.
134///
135/// This is identical to `to_string` except the output string has a more
136/// "pretty" output. See `ValueSerializer::pretty` for more details.
137pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error>
138where
139    T: serde::ser::Serialize,
140{
141    let mut document = to_document(value)?;
142    pretty::Pretty.visit_document_mut(&mut document);
143    Ok(document.to_string())
144}
145
146/// Serialize the given data structure into a TOML document.
147///
148/// This would allow custom formatting to be applied, mixing with format preserving edits, etc.
149pub fn to_document<T: ?Sized>(value: &T) -> Result<crate::Document, Error>
150where
151    T: serde::ser::Serialize,
152{
153    let value = value.serialize(ValueSerializer::new())?;
154    let item = crate::Item::Value(value);
155    let root = item
156        .into_table()
157        .map_err(|_| Error::UnsupportedType(None))?;
158    Ok(root.into())
159}
160
161pub use value::ValueSerializer;