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