aboutsummaryrefslogtreecommitdiff
path: root/src/ser/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ser/mod.rs')
-rw-r--r--src/ser/mod.rs165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/ser/mod.rs b/src/ser/mod.rs
new file mode 100644
index 0000000..2c31020
--- /dev/null
+++ b/src/ser/mod.rs
@@ -0,0 +1,165 @@
+//! 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 convertable to `String` for serializing to TOML
+ KeyNotString,
+ /// A serialized date was invalid
+ DateInvalid,
+ /// Other serialization error
+ 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::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<crate::TomlError> for Error {
+ fn from(e: crate::TomlError) -> Error {
+ Self::custom(e)
+ }
+}
+
+impl From<Error> 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.
+pub fn to_vec<T: ?Sized>(value: &T) -> Result<Vec<u8>, 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<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_edit::ser::to_string(&config).unwrap();
+/// println!("{}", toml)
+/// ```
+pub fn to_string<T: ?Sized>(value: &T) -> Result<String, Error>
+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.
+pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error>
+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<T: ?Sized>(value: &T) -> Result<crate::Document, Error>
+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;