Repository: toml-rs/toml (language: rust)

Issue:
More `Error(UnsupportedType)` Feedback
Really helpful library, thanks so much for your work on it. 

This issue is borne of https://github.com/dan-fritchman/Layout21/issues/33, in which: 

* I have a big tree of `struct`s, with lots of fields, internal types, and external types along the way
* I pass the biggest top-most one to `toml::to_string()`
* What comes back is this:

```
failures:

---- tests::empty_lib_to_toml stdout ----
thread 'tests::empty_lib_to_toml' panicked at 'save failed: Error(UnsupportedType)', gds21/src/tests.rs:214:50
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

Question: is there any good way to get more than `UnsupportedType` as feedback here?  
(Set a setting, submit a PR to improve the error message, whatever.) 

Thanks again!


Discussion / hints:
Yes, ideally we report more details to help people with this.  However, a lot of things will be changing with #340 which I'm actively working on so I'd like to hold off on other changes until then.
Ok, cool, understand.
FWIW after an upgrade of `toml` (and some edits to our library), that error is now: 

```
---- tests::golden_toml stdout ----
thread 'gds_serialization::tests::golden_toml' panicked at 'Could not save output file: values must be emitted before tables', 
```

I see there are handfuls of past discussions on this "ordering problem". My read is that they are all resolved, and should be handled inside the serializer? Do I have that wrong? In any case, is there a good reference for what "should work", e.g. do struct-fields need to be arranged in a particular order, etc. 


Fix patch:
diff --git a/crates/toml/src/fmt.rs b/crates/toml/src/fmt.rs
new file mode 100644
index 00000000..0e96bf05
--- /dev/null
+++ b/crates/toml/src/fmt.rs
@@ -0,0 +1,60 @@
+#[derive(Copy, Clone, Default)]
+pub(crate) struct DocumentFormatter {
+    pub(crate) multiline_array: bool,
+}
+
+impl toml_edit::visit_mut::VisitMut for DocumentFormatter {
+    fn visit_document_mut(&mut self, node: &mut toml_edit::Document) {
+        toml_edit::visit_mut::visit_document_mut(self, node);
+    }
+
+    fn visit_item_mut(&mut self, node: &mut toml_edit::Item) {
+        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,
+        };
+        *node = other;
+
+        toml_edit::visit_mut::visit_item_mut(self, node);
+    }
+
+    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);
+        }
+    }
+}
diff --git a/crates/toml/src/lib.rs b/crates/toml/src/lib.rs
index d68d9bea..e0c3b813 100644
--- a/crates/toml/src/lib.rs
+++ b/crates/toml/src/lib.rs
@@ -153,7 +153,7 @@ pub use crate::value::Value;
 
 pub mod ser;
 #[doc(no_inline)]
-pub use crate::ser::{to_string, to_string_pretty, to_vec, Serializer};
+pub use crate::ser::{to_string, to_string_pretty, Serializer};
 pub mod de;
 #[doc(no_inline)]
 pub use crate::de::{from_str, Deserializer, ValueDeserializer};
@@ -161,6 +161,8 @@ pub use crate::de::{from_str, Deserializer, ValueDeserializer};
 #[doc(hidden)]
 pub mod macros;
 
+mod fmt;
+
 pub use serde_spanned::Spanned;
 
 // Shortcuts for the module doc-comment
diff --git a/crates/toml/src/ser.rs b/crates/toml/src/ser.rs
index 74bacb6b..4833751b 100644
--- a/crates/toml/src/ser.rs
+++ b/crates/toml/src/ser.rs
@@ -3,48 +3,8 @@
 //! 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.
-//!
-//! Note that the TOML format has a restriction that if a table itself contains
-//! tables, all keys with non-table values must be emitted first. This is
-//! typically easy to ensure happens when you're defining a `struct` as you can
-//! reorder the fields manually, but when working with maps (such as `BTreeMap`
-//! or `HashMap`) this can lead to serialization errors. In those situations you
-//! may use the `tables_last` function in this module like so:
-//!
-//! ```rust
-//! # use serde::Serialize;
-//! # use std::collections::HashMap;
-//! #[derive(Serialize)]
-//! struct Manifest {
-//!     package: Package,
-//!     #[serde(serialize_with = "toml::ser::tables_last")]
-//!     dependencies: HashMap<String, Dependency>,
-//! }
-//! # type Package = String;
-//! # type Dependency = String;
-//! # fn main() {}
-//! ```
-
-use std::cell::Cell;
-use std::error;
-use std::fmt::{self, Write};
-use std::marker;
-use std::rc::Rc;
-
-use serde::ser;
-use toml_datetime::__unstable as datetime;
-
-/// 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: ser::Serialize,
-{
-    to_string(value).map(|e| e.into_bytes())
-}
+
+use crate::fmt::DocumentFormatter;
 
 /// Serialize the given data structure as a String of TOML.
 ///
@@ -84,11 +44,12 @@ where
 /// ```
 pub fn to_string<T: ?Sized>(value: &T) -> Result<String, Error>
 where
-    T: ser::Serialize,
+    T: serde::ser::Serialize,
 {
-    let mut dst = String::with_capacity(128);
-    value.serialize(&mut Serializer::new(&mut dst))?;
-    Ok(dst)
+    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.
@@ -97,92 +58,68 @@ where
 /// "pretty" output. See `Serializer::pretty` for more details.
 pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error>
 where
-    T: ser::Serialize,
+    T: serde::ser::Serialize,
 {
-    let mut dst = String::with_capacity(128);
-    value.serialize(&mut Serializer::pretty(&mut dst))?;
-    Ok(dst)
+    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(Debug, PartialEq, Eq, Clone)]
-#[non_exhaustive]
-pub enum Error {
-    /// Indicates that a Rust type was requested to be serialized but it was not
-    /// supported.
-    ///
-    /// Currently the TOML format does not support serializing types such as
-    /// enums, tuples and tuple structs.
-    UnsupportedType,
-
-    /// The key of all TOML maps must be strings, but serialization was
-    /// attempted where the key of a map was not a string.
-    KeyNotString,
-
-    /// An error that we never omit but keep for backwards compatibility
-    #[doc(hidden)]
-    KeyNewline,
-
-    /// An array had to be homogeneous, but now it is allowed to be heterogeneous.
-    #[doc(hidden)]
-    ArrayMixedType,
-
-    /// All values in a TOML table must be emitted before further tables are
-    /// emitted. If a value is emitted *after* a table then this error is
-    /// generated.
-    ValueAfterTable,
-
-    /// A serialized date was invalid.
-    DateInvalid,
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Error {
+    pub(crate) inner: toml_edit::ser::Error,
+}
 
-    /// A serialized number was invalid.
-    NumberInvalid,
+impl Error {
+    pub(crate) fn new(inner: impl std::fmt::Display) -> Self {
+        Self {
+            inner: toml_edit::ser::Error::Custom(inner.to_string()),
+        }
+    }
 
-    /// None was attempted to be serialized, but it's not supported.
-    UnsupportedNone,
+    pub(crate) fn wrap(inner: toml_edit::ser::Error) -> Self {
+        Self { inner }
+    }
 
-    /// A custom error which could be generated when serializing a particular
-    /// type.
-    Custom(String),
-}
+    pub(crate) fn unsupported_type(t: Option<&'static str>) -> Self {
+        Self {
+            inner: toml_edit::ser::Error::UnsupportedType(t),
+        }
+    }
 
-#[derive(Debug, Default, Clone)]
-/// Internal place for holding array settings
-struct ArraySettings {
-    indent: usize,
-    trailing_comma: bool,
-}
+    pub(crate) fn unsupported_none() -> Self {
+        Self {
+            inner: toml_edit::ser::Error::UnsupportedNone,
+        }
+    }
 
-impl ArraySettings {
-    fn pretty() -> ArraySettings {
-        ArraySettings {
-            indent: 4,
-            trailing_comma: true,
+    pub(crate) fn key_not_string() -> Self {
+        Self {
+            inner: toml_edit::ser::Error::KeyNotString,
         }
     }
 }
 
-#[derive(Debug, Default, Clone)]
-/// String settings
-struct StringSettings {
-    /// Whether to use literal strings when possible
-    literal: bool,
+impl serde::ser::Error for Error {
+    fn custom<T>(msg: T) -> Self
+    where
+        T: std::fmt::Display,
+    {
+        Error::new(msg)
+    }
 }
 
-impl StringSettings {
-    fn pretty() -> StringSettings {
-        StringSettings { literal: true }
+impl std::fmt::Display for Error {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        self.inner.fmt(f)
     }
 }
 
-#[derive(Debug, Default, Clone)]
-/// Internal struct for holding serialization settings
-struct Settings {
-    array: Option<ArraySettings>,
-    string: Option<StringSettings>,
-}
+impl std::error::Error for Error {}
 
-/// Serialization implementation for TOML.
+/// 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
@@ -191,718 +128,250 @@ struct Settings {
 ///
 /// Currently a serializer always writes its output to an in-memory `String`,
 /// which is passed in when creating the serializer itself.
-pub struct Serializer<'a> {
-    dst: &'a mut String,
-    state: State<'a>,
-    settings: Rc<Settings>,
-}
-
-#[derive(Debug, Copy, Clone)]
-enum ArrayState {
-    Started,
-    StartedAsATable,
-}
-
-#[derive(Debug, Clone)]
-enum State<'a> {
-    Table {
-        key: &'a str,
-        parent: &'a State<'a>,
-        first: &'a Cell<bool>,
-        table_emitted: &'a Cell<bool>,
-    },
-    Array {
-        parent: &'a State<'a>,
-        first: &'a Cell<bool>,
-        type_: &'a Cell<Option<ArrayState>>,
-        len: Option<usize>,
-    },
-    End,
-}
-
-#[doc(hidden)]
-pub struct SerializeSeq<'a, 'b> {
-    ser: &'b mut Serializer<'a>,
-    first: Cell<bool>,
-    type_: Cell<Option<ArrayState>>,
-    len: Option<usize>,
-}
-
-#[doc(hidden)]
-pub enum SerializeTable<'a, 'b> {
-    Datetime(&'b mut Serializer<'a>),
-    Table {
-        ser: &'b mut Serializer<'a>,
-        key: String,
-        first: Cell<bool>,
-        table_emitted: Cell<bool>,
-    },
+#[non_exhaustive]
+pub struct Serializer<'d> {
+    dst: &'d mut String,
+    settings: DocumentFormatter,
 }
 
-impl<'a> Serializer<'a> {
+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: &'a mut String) -> Serializer<'a> {
-        Serializer {
+    pub fn new(dst: &'d mut String) -> Self {
+        Self {
             dst,
-            state: State::End,
-            settings: Rc::new(Settings::default()),
+            settings: Default::default(),
         }
     }
 
-    /// Instantiate a "pretty" formatter
-    ///
-    /// By default this will use:
-    ///
-    /// - pretty strings: strings with newlines will use the `'''` syntax. See
-    ///   `Serializer::pretty_string`
-    /// - pretty arrays: each item in arrays will be on a newline, have an indentation of 4 and
-    ///   have a trailing comma. See `Serializer::pretty_array`
-    pub fn pretty(dst: &'a mut String) -> Serializer<'a> {
-        Serializer {
-            dst,
-            state: State::End,
-            settings: Rc::new(Settings {
-                array: Some(ArraySettings::pretty()),
-                string: Some(StringSettings::pretty()),
-            }),
-        }
+    /// Apply a default "pretty" policy to the document
+    pub fn pretty(dst: &'d mut String) -> Self {
+        let mut ser = Serializer::new(dst);
+        ser.settings.multiline_array = true;
+        ser
     }
-
-    /// Enable or Disable pretty strings
-    ///
-    /// If enabled, literal strings will be used when possible and strings with
-    /// one or more newlines will use triple quotes (i.e.: `'''` or `"""`)
-    ///
-    /// # Examples
-    ///
-    /// Instead of:
-    ///
-    /// ```toml,ignore
-    /// single = "no newlines"
-    /// text = "\nfoo\nbar\n"
-    /// ```
-    ///
-    /// You will have:
-    ///
-    /// ```toml,ignore
-    /// single = 'no newlines'
-    /// text = '''
-    /// foo
-    /// bar
-    /// '''
-    /// ```
-    pub fn pretty_string(&mut self, value: bool) -> &mut Self {
-        Rc::get_mut(&mut self.settings).unwrap().string = if value {
-            Some(StringSettings::pretty())
-        } else {
-            None
-        };
-        self
-    }
-
-    /// Enable or Disable Literal strings for pretty strings
-    ///
-    /// If enabled, literal strings will be used when possible and strings with
-    /// one or more newlines will use triple quotes (i.e.: `'''` or `"""`)
-    ///
-    /// If disabled, literal strings will NEVER be used and strings with one or
-    /// more newlines will use `"""`
-    ///
-    /// # Examples
-    ///
-    /// Instead of:
-    ///
-    /// ```toml,ignore
-    /// single = "no newlines"
-    /// text = "\nfoo\nbar\n"
-    /// ```
-    ///
-    /// You will have:
-    ///
-    /// ```toml,ignore
-    /// single = "no newlines"
-    /// text = """
-    /// foo
-    /// bar
-    /// """
-    /// ```
-    pub fn pretty_string_literal(&mut self, value: bool) -> &mut Self {
-        let use_default = if let Some(ref mut s) = Rc::get_mut(&mut self.settings).unwrap().string {
-            s.literal = value;
-            false
-        } else {
-            true
-        };
-
-        if use_default {
-            let mut string = StringSettings::pretty();
-            string.literal = value;
-            Rc::get_mut(&mut self.settings).unwrap().string = Some(string);
-        }
-        self
-    }
-
-    /// Enable or Disable pretty arrays
-    ///
-    /// If enabled, arrays will always have each item on their own line.
-    ///
-    /// Some specific features can be controlled via other builder methods:
-    ///
-    /// - `Serializer::pretty_array_indent`: set the indent to a value other
-    ///   than 4.
-    /// - `Serializer::pretty_array_trailing_comma`: enable/disable the trailing
-    ///   comma on the last item.
-    ///
-    /// # Examples
-    ///
-    /// Instead of:
-    ///
-    /// ```toml,ignore
-    /// array = ["foo", "bar"]
-    /// ```
-    ///
-    /// You will have:
-    ///
-    /// ```toml,ignore
-    /// array = [
-    ///     "foo",
-    ///     "bar",
-    /// ]
-    /// ```
-    pub fn pretty_array(&mut self, value: bool) -> &mut Self {
-        Rc::get_mut(&mut self.settings).unwrap().array = if value {
-            Some(ArraySettings::pretty())
-        } else {
-            None
-        };
-        self
-    }
-
-    /// Set the indent for pretty arrays
-    ///
-    /// See `Serializer::pretty_array` for more details.
-    pub fn pretty_array_indent(&mut self, value: usize) -> &mut Self {
-        let use_default = if let Some(ref mut a) = Rc::get_mut(&mut self.settings).unwrap().array {
-            a.indent = value;
-            false
-        } else {
-            true
-        };
-
-        if use_default {
-            let mut array = ArraySettings::pretty();
-            array.indent = value;
-            Rc::get_mut(&mut self.settings).unwrap().array = Some(array);
-        }
-        self
-    }
-
-    /// Specify whether to use a trailing comma when serializing pretty arrays
-    ///
-    /// See `Serializer::pretty_array` for more details.
-    pub fn pretty_array_trailing_comma(&mut self, value: bool) -> &mut Self {
-        let use_default = if let Some(ref mut a) = Rc::get_mut(&mut self.settings).unwrap().array {
-            a.trailing_comma = value;
-            false
-        } else {
-            true
-        };
-
-        if use_default {
-            let mut array = ArraySettings::pretty();
-            array.trailing_comma = value;
-            Rc::get_mut(&mut self.settings).unwrap().array = Some(array);
-        }
-        self
-    }
-
-    fn display<T: fmt::Display>(&mut self, t: T, type_: ArrayState) -> Result<(), Error> {
-        self.emit_key(type_)?;
-        write!(self.dst, "{}", t).map_err(ser::Error::custom)?;
-        if let State::Table { .. } = self.state {
-            self.dst.push('\n');
-        }
-        Ok(())
-    }
-
-    fn emit_key(&mut self, type_: ArrayState) -> Result<(), Error> {
-        self.array_type(type_)?;
-        let state = self.state.clone();
-        self._emit_key(&state)
-    }
-
-    // recursive implementation of `emit_key` above
-    fn _emit_key(&mut self, state: &State<'_>) -> Result<(), Error> {
-        match *state {
-            State::End => Ok(()),
-            State::Array {
-                parent,
-                first,
-                type_,
-                len,
-            } => {
-                assert!(type_.get().is_some());
-                if first.get() {
-                    self._emit_key(parent)?;
-                }
-                self.emit_array(first, len)
-            }
-            State::Table {
-                parent,
-                first,
-                table_emitted,
-                key,
-            } => {
-                if table_emitted.get() {
-                    return Err(Error::ValueAfterTable);
-                }
-                if first.get() {
-                    self.emit_table_header(parent)?;
-                    first.set(false);
-                }
-                self.escape_key(key)?;
-                self.dst.push_str(" = ");
-                Ok(())
-            }
-        }
-    }
-
-    fn emit_array(&mut self, first: &Cell<bool>, len: Option<usize>) -> Result<(), Error> {
-        match (len, &self.settings.array) {
-            (Some(0..=1), _) | (_, &None) => {
-                if first.get() {
-                    self.dst.push('[')
-                } else {
-                    self.dst.push_str(", ")
-                }
-            }
-            (_, &Some(ref a)) => {
-                if first.get() {
-                    self.dst.push_str("[\n")
-                } else {
-                    self.dst.push_str(",\n")
-                }
-                for _ in 0..a.indent {
-                    self.dst.push(' ');
-                }
-            }
-        }
-        Ok(())
-    }
-
-    fn array_type(&mut self, type_: ArrayState) -> Result<(), Error> {
-        let prev = match self.state {
-            State::Array { type_, .. } => type_,
-            _ => return Ok(()),
-        };
-        if prev.get().is_none() {
-            prev.set(Some(type_));
-        }
-        Ok(())
-    }
-
-    fn escape_key(&mut self, key: &str) -> Result<(), Error> {
-        let ok = !key.is_empty()
-            && key
-                .chars()
-                .all(|c| matches!(c,'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_'));
-        if ok {
-            write!(self.dst, "{}", key).map_err(ser::Error::custom)?;
-        } else {
-            self.emit_str(key, true)?;
-        }
-        Ok(())
-    }
-
-    fn emit_str(&mut self, value: &str, is_key: bool) -> Result<(), Error> {
-        #[derive(PartialEq)]
-        enum Type {
-            NewlineTripple,
-            OnelineTripple,
-            OnelineSingle,
-        }
-
-        enum Repr {
-            /// represent as a literal string (using '')
-            Literal(String, Type),
-            /// represent the std way (using "")
-            Std(Type),
-        }
-
-        fn do_pretty(value: &str) -> Repr {
-            // For doing pretty prints we store in a new String
-            // because there are too many cases where pretty cannot
-            // work. We need to determine:
-            // - if we are a "multi-line" pretty (if there are \n)
-            // - if ['''] appears if multi or ['] if single
-            // - if there are any invalid control characters
-            //
-            // Doing it any other way would require multiple passes
-            // to determine if a pretty string works or not.
-            let mut out = String::with_capacity(value.len() * 2);
-            let mut ty = Type::OnelineSingle;
-            // found consecutive single quotes
-            let mut max_found_singles = 0;
-            let mut found_singles = 0;
-            let mut can_be_pretty = true;
-
-            for ch in value.chars() {
-                if can_be_pretty {
-                    if ch == '\'' {
-                        found_singles += 1;
-                        if found_singles >= 3 {
-                            can_be_pretty = false;
-                        }
-                    } else {
-                        if found_singles > max_found_singles {
-                            max_found_singles = found_singles;
-                        }
-                        found_singles = 0
-                    }
-                    match ch {
-                        '\t' => {}
-                        '\n' => ty = Type::NewlineTripple,
-                        // Escape codes are needed if any ascii control
-                        // characters are present, including \b \f \r.
-                        c if c <= '\u{1f}' || c == '\u{7f}' => can_be_pretty = false,
-                        _ => {}
-                    }
-                    out.push(ch);
-                } else {
-                    // the string cannot be represented as pretty,
-                    // still check if it should be multiline
-                    if ch == '\n' {
-                        ty = Type::NewlineTripple;
-                    }
-                }
-            }
-            if can_be_pretty && found_singles > 0 && value.ends_with('\'') {
-                // We cannot escape the ending quote so we must use """
-                can_be_pretty = false;
-            }
-            if !can_be_pretty {
-                debug_assert!(ty != Type::OnelineTripple);
-                return Repr::Std(ty);
-            }
-            if found_singles > max_found_singles {
-                max_found_singles = found_singles;
-            }
-            debug_assert!(max_found_singles < 3);
-            if ty == Type::OnelineSingle && max_found_singles >= 1 {
-                // no newlines, but must use ''' because it has ' in it
-                ty = Type::OnelineTripple;
-            }
-            Repr::Literal(out, ty)
-        }
-
-        let repr = if !is_key && self.settings.string.is_some() {
-            match (&self.settings.string, do_pretty(value)) {
-                (&Some(StringSettings { literal: false, .. }), Repr::Literal(_, ty)) => {
-                    Repr::Std(ty)
-                }
-                (_, r) => r,
-            }
-        } else {
-            Repr::Std(Type::OnelineSingle)
-        };
-        match repr {
-            Repr::Literal(literal, ty) => {
-                // A pretty string
-                match ty {
-                    Type::NewlineTripple => self.dst.push_str("'''\n"),
-                    Type::OnelineTripple => self.dst.push_str("'''"),
-                    Type::OnelineSingle => self.dst.push('\''),
-                }
-                self.dst.push_str(&literal);
-                match ty {
-                    Type::OnelineSingle => self.dst.push('\''),
-                    _ => self.dst.push_str("'''"),
-                }
-            }
-            Repr::Std(ty) => {
-                match ty {
-                    Type::NewlineTripple => self.dst.push_str("\"\"\"\n"),
-                    // note: OnelineTripple can happen if do_pretty wants to do
-                    // '''it's one line'''
-                    // but settings.string.literal == false
-                    Type::OnelineSingle | Type::OnelineTripple => self.dst.push('"'),
-                }
-                for ch in value.chars() {
-                    match ch {
-                        '\u{8}' => self.dst.push_str("\\b"),
-                        '\u{9}' => self.dst.push_str("\\t"),
-                        '\u{a}' => match ty {
-                            Type::NewlineTripple => self.dst.push('\n'),
-                            Type::OnelineSingle => self.dst.push_str("\\n"),
-                            _ => unreachable!(),
-                        },
-                        '\u{c}' => self.dst.push_str("\\f"),
-                        '\u{d}' => self.dst.push_str("\\r"),
-                        '\u{22}' => self.dst.push_str("\\\""),
-                        '\u{5c}' => self.dst.push_str("\\\\"),
-                        c if c <= '\u{1f}' || c == '\u{7f}' => {
-                            write!(self.dst, "\\u{:04X}", ch as u32).map_err(ser::Error::custom)?;
-                        }
-                        ch => self.dst.push(ch),
-                    }
-                }
-                match ty {
-                    Type::NewlineTripple => self.dst.push_str("\"\"\""),
-                    Type::OnelineSingle | Type::OnelineTripple => self.dst.push('"'),
-                }
-            }
-        }
-        Ok(())
-    }
-
-    fn emit_table_header(&mut self, state: &State<'_>) -> Result<(), Error> {
-        let array_of_tables = match *state {
-            State::End => return Ok(()),
-            State::Array { .. } => true,
-            _ => false,
-        };
-
-        // Unlike [..]s, we can't omit [[..]] ancestors, so be sure to emit table
-        // headers for them.
-        let mut p = state;
-        if let State::Array { first, parent, .. } = *state {
-            if first.get() {
-                p = parent;
-            }
-        }
-        while let State::Table { first, parent, .. } = *p {
-            p = parent;
-            if !first.get() {
-                break;
-            }
-            if let State::Array {
-                parent: &State::Table { .. },
-                ..
-            } = *parent
-            {
-                self.emit_table_header(parent)?;
-                break;
-            }
-        }
-
-        match *state {
-            State::Table { first, .. } => {
-                if !first.get() {
-                    // Newline if we are a table that is not the first
-                    // table in the document.
-                    self.dst.push('\n');
-                }
-            }
-            State::Array { parent, first, .. } => {
-                if !first.get() {
-                    // Always newline if we are not the first item in the
-                    // table-array
-                    self.dst.push('\n');
-                } else if let State::Table { first, .. } = *parent {
-                    if !first.get() {
-                        // Newline if we are not the first item in the document
-                        self.dst.push('\n');
-                    }
-                }
-            }
-            _ => {}
-        }
-        self.dst.push('[');
-        if array_of_tables {
-            self.dst.push('[');
-        }
-        self.emit_key_part(state)?;
-        if array_of_tables {
-            self.dst.push(']');
-        }
-        self.dst.push_str("]\n");
-        Ok(())
-    }
-
-    fn emit_key_part(&mut self, key: &State<'_>) -> Result<bool, Error> {
-        match *key {
-            State::Array { parent, .. } => self.emit_key_part(parent),
-            State::End => Ok(true),
-            State::Table {
-                key,
-                parent,
-                table_emitted,
-                ..
-            } => {
-                table_emitted.set(true);
-                let first = self.emit_key_part(parent)?;
-                if !first {
-                    self.dst.push('.');
-                }
-                self.escape_key(key)?;
-                Ok(false)
-            }
-        }
-    }
-}
-
-macro_rules! serialize_float {
-    ($this:expr, $v:expr) => {{
-        $this.emit_key(ArrayState::Started)?;
-        match ($v.is_sign_negative(), $v.is_nan(), $v == 0.0) {
-            (true, true, _) => write!($this.dst, "-nan"),
-            (false, true, _) => write!($this.dst, "nan"),
-            (true, false, true) => write!($this.dst, "-0.0"),
-            (false, false, true) => write!($this.dst, "0.0"),
-            (_, false, false) => write!($this.dst, "{}", $v).and_then(|_| {
-                if $v % 1.0 == 0.0 {
-                    write!($this.dst, ".0")
-                } else {
-                    Ok(())
-                }
-            }),
-        }
-        .map_err(ser::Error::custom)?;
-
-        if let State::Table { .. } = $this.state {
-            $this.dst.push_str("\n");
-        }
-        return Ok(());
-    }};
 }
 
-impl<'a, 'b> ser::Serializer for &'b mut Serializer<'a> {
+impl<'d> serde::ser::Serializer for Serializer<'d> {
     type Ok = ();
     type Error = Error;
-    type SerializeSeq = SerializeSeq<'a, 'b>;
-    type SerializeTuple = SerializeSeq<'a, 'b>;
-    type SerializeTupleStruct = SerializeSeq<'a, 'b>;
-    type SerializeTupleVariant = SerializeSeq<'a, 'b>;
-    type SerializeMap = SerializeTable<'a, 'b>;
-    type SerializeStruct = SerializeTable<'a, 'b>;
-    type SerializeStructVariant = ser::Impossible<(), Error>;
-
-    fn serialize_bool(self, v: bool) -> Result<(), Self::Error> {
-        self.display(v, ArrayState::Started)
-    }
-
-    fn serialize_i8(self, v: i8) -> Result<(), Self::Error> {
-        self.display(v, ArrayState::Started)
-    }
-
-    fn serialize_i16(self, v: i16) -> Result<(), Self::Error> {
-        self.display(v, ArrayState::Started)
+    type SerializeSeq = SerializeDocumentArray<'d>;
+    type SerializeTuple = SerializeDocumentArray<'d>;
+    type SerializeTupleStruct = SerializeDocumentArray<'d>;
+    type SerializeTupleVariant = SerializeDocumentArray<'d>;
+    type SerializeMap = SerializeDocumentTable<'d>;
+    type SerializeStruct = SerializeDocumentTable<'d>;
+    type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
+
+    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_i32(self, v: i32) -> Result<(), Self::Error> {
-        self.display(v, ArrayState::Started)
+    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_i64(self, v: i64) -> Result<(), Self::Error> {
-        self.display(v, ArrayState::Started)
+    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_u8(self, v: u8) -> Result<(), Self::Error> {
-        self.display(v, ArrayState::Started)
-    }
-
-    fn serialize_u16(self, v: u16) -> Result<(), Self::Error> {
-        self.display(v, ArrayState::Started)
-    }
-
-    fn serialize_u32(self, v: u32) -> Result<(), Self::Error> {
-        self.display(v, ArrayState::Started)
-    }
-
-    fn serialize_u64(self, v: u64) -> Result<(), Self::Error> {
-        self.display(v, ArrayState::Started)
-    }
-
-    fn serialize_f32(self, v: f32) -> Result<(), Self::Error> {
-        serialize_float!(self, v)
-    }
-
-    fn serialize_f64(self, v: f64) -> Result<(), Self::Error> {
-        serialize_float!(self, v)
-    }
-
-    fn serialize_char(self, v: char) -> Result<(), Self::Error> {
-        let mut buf = [0; 4];
-        self.serialize_str(v.encode_utf8(&mut buf))
-    }
-
-    fn serialize_str(self, value: &str) -> Result<(), Self::Error> {
-        self.emit_key(ArrayState::Started)?;
-        self.emit_str(value, false)?;
-        if let State::Table { .. } = self.state {
-            self.dst.push('\n');
-        }
-        Ok(())
-    }
-
-    fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> {
-        use serde::ser::Serialize;
-        value.serialize(self)
-    }
-
-    fn serialize_none(self) -> Result<(), Self::Error> {
-        Err(Error::UnsupportedNone)
+    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: ?Sized>(self, value: &T) -> Result<(), Self::Error>
+    fn serialize_some<T: ?Sized>(self, v: &T) -> Result<Self::Ok, Self::Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        value.serialize(self)
+        write_document(
+            self.dst,
+            self.settings,
+            toml_edit::ser::ValueSerializer::new().serialize_some(v),
+        )
     }
 
-    fn serialize_unit(self) -> Result<(), Self::Error> {
-        Err(Error::UnsupportedType)
+    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::Error> {
-        Err(Error::UnsupportedType)
+    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,
+        name: &'static str,
+        variant_index: u32,
         variant: &'static str,
-    ) -> Result<(), Self::Error> {
-        self.serialize_str(variant)
+    ) -> 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: ?Sized>(
         self,
-        _name: &'static str,
-        value: &T,
-    ) -> Result<(), Self::Error>
+        name: &'static str,
+        v: &T,
+    ) -> Result<Self::Ok, Self::Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        value.serialize(self)
+        write_document(
+            self.dst,
+            self.settings,
+            toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v),
+        )
     }
 
     fn serialize_newtype_variant<T: ?Sized>(
         self,
-        _name: &'static str,
-        _variant_index: u32,
-        _variant: &'static str,
-        _value: &T,
-    ) -> Result<(), Self::Error>
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+        value: &T,
+    ) -> Result<Self::Ok, Self::Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        Err(Error::UnsupportedType)
+        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> {
-        self.array_type(ArrayState::Started)?;
-        Ok(SerializeSeq {
-            ser: self,
-            first: Cell::new(true),
-            type_: Cell::new(None),
-            len,
-        })
+        let ser = toml_edit::ser::ValueSerializer::new()
+            .serialize_seq(len)
+            .map_err(Error::wrap)?;
+        let ser = SerializeDocumentArray::new(self, ser);
+        Ok(ser)
     }
 
     fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
@@ -927,570 +396,437 @@ impl<'a, 'b> ser::Serializer for &'b mut Serializer<'a> {
         self.serialize_seq(Some(len))
     }
 
-    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
-        self.array_type(ArrayState::StartedAsATable)?;
-        Ok(SerializeTable::Table {
-            ser: self,
-            key: String::new(),
-            first: Cell::new(true),
-            table_emitted: Cell::new(false),
-        })
+    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 = SerializeDocumentTable::new(self, ser);
+        Ok(ser)
     }
 
     fn serialize_struct(
         self,
-        name: &'static str,
-        _len: usize,
+        _name: &'static str,
+        len: usize,
     ) -> Result<Self::SerializeStruct, Self::Error> {
-        if name == datetime::NAME {
-            self.array_type(ArrayState::Started)?;
-            Ok(SerializeTable::Datetime(self))
-        } else {
-            self.array_type(ArrayState::StartedAsATable)?;
-            Ok(SerializeTable::Table {
-                ser: self,
-                key: String::new(),
-                first: Cell::new(true),
-                table_emitted: Cell::new(false),
-            })
-        }
+        self.serialize_map(Some(len))
     }
 
     fn serialize_struct_variant(
         self,
-        _name: &'static str,
+        name: &'static str,
         _variant_index: u32,
         _variant: &'static str,
         _len: usize,
     ) -> Result<Self::SerializeStructVariant, Self::Error> {
-        Err(Error::UnsupportedType)
+        Err(Error::unsupported_type(Some(name)))
     }
 }
 
-impl<'a, 'b> ser::SerializeSeq for SerializeSeq<'a, 'b> {
-    type Ok = ();
-    type Error = Error;
+type InnerSerializeDocumentSeq =
+    <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeSeq;
 
-    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
-    where
-        T: ser::Serialize,
-    {
-        value.serialize(&mut Serializer {
-            dst: &mut *self.ser.dst,
-            state: State::Array {
-                parent: &self.ser.state,
-                first: &self.first,
-                type_: &self.type_,
-                len: self.len,
-            },
-            settings: self.ser.settings.clone(),
-        })?;
-        self.first.set(false);
-        Ok(())
-    }
-
-    fn end(self) -> Result<(), Error> {
-        match self.type_.get() {
-            Some(ArrayState::StartedAsATable) => return Ok(()),
-            Some(ArrayState::Started) => match (self.len, &self.ser.settings.array) {
-                (Some(0..=1), _) | (_, &None) => {
-                    self.ser.dst.push(']');
-                }
-                (_, &Some(ref a)) => {
-                    if a.trailing_comma {
-                        self.ser.dst.push(',');
-                    }
-                    self.ser.dst.push_str("\n]");
-                }
-            },
-            None => {
-                assert!(self.first.get());
-                self.ser.emit_key(ArrayState::Started)?;
-                self.ser.dst.push_str("[]")
-            }
-        }
-        if let State::Table { .. } = self.ser.state {
-            self.ser.dst.push('\n');
+#[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,
         }
-        Ok(())
     }
 }
 
-impl<'a, 'b> ser::SerializeTuple for SerializeSeq<'a, 'b> {
+impl<'d> serde::ser::SerializeSeq for SerializeDocumentArray<'d> {
     type Ok = ();
     type Error = Error;
 
     fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        ser::SerializeSeq::serialize_element(self, value)
+        self.inner.serialize_element(value).map_err(Error::wrap)
     }
 
-    fn end(self) -> Result<(), Error> {
-        ser::SerializeSeq::end(self)
+    fn end(self) -> Result<Self::Ok, Self::Error> {
+        write_document(self.dst, self.settings, self.inner.end())
     }
 }
 
-impl<'a, 'b> ser::SerializeTupleVariant for SerializeSeq<'a, 'b> {
+impl<'d> serde::ser::SerializeTuple for SerializeDocumentArray<'d> {
     type Ok = ();
     type Error = Error;
 
-    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        ser::SerializeSeq::serialize_element(self, value)
+        self.inner.serialize_element(value).map_err(Error::wrap)
     }
 
-    fn end(self) -> Result<(), Error> {
-        ser::SerializeSeq::end(self)
+    fn end(self) -> Result<Self::Ok, Self::Error> {
+        write_document(self.dst, self.settings, self.inner.end())
     }
 }
 
-impl<'a, 'b> ser::SerializeTupleStruct for SerializeSeq<'a, 'b> {
+impl<'d> serde::ser::SerializeTupleVariant for SerializeDocumentArray<'d> {
     type Ok = ();
     type Error = Error;
 
     fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        ser::SerializeSeq::serialize_element(self, value)
+        self.inner.serialize_field(value).map_err(Error::wrap)
     }
 
-    fn end(self) -> Result<(), Error> {
-        ser::SerializeSeq::end(self)
+    fn end(self) -> Result<Self::Ok, Self::Error> {
+        write_document(self.dst, self.settings, self.inner.end())
     }
 }
 
-impl<'a, 'b> ser::SerializeMap for SerializeTable<'a, 'b> {
+impl<'d> serde::ser::SerializeTupleStruct for SerializeDocumentArray<'d> {
     type Ok = ();
     type Error = Error;
 
-    fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Error>
+    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        match *self {
-            SerializeTable::Datetime(_) => panic!(), // shouldn't be possible
-            SerializeTable::Table { ref mut key, .. } => {
-                key.truncate(0);
-                *key = input.serialize(StringExtractor)?;
-            }
-        }
-        Ok(())
+        self.inner.serialize_field(value).map_err(Error::wrap)
     }
 
-    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
-    where
-        T: ser::Serialize,
-    {
-        match *self {
-            SerializeTable::Datetime(_) => panic!(), // shouldn't be possible
-            SerializeTable::Table {
-                ref mut ser,
-                ref key,
-                ref first,
-                ref table_emitted,
-                ..
-            } => {
-                let res = value.serialize(&mut Serializer {
-                    dst: &mut *ser.dst,
-                    state: State::Table {
-                        key,
-                        parent: &ser.state,
-                        first,
-                        table_emitted,
-                    },
-                    settings: ser.settings.clone(),
-                });
-                match res {
-                    Ok(()) => first.set(false),
-                    Err(Error::UnsupportedNone) => {}
-                    Err(e) => return Err(e),
-                }
-            }
-        }
-        Ok(())
-    }
-
-    fn end(self) -> Result<(), Error> {
-        match self {
-            SerializeTable::Datetime(_) => panic!(), // shouldn't be possible
-            SerializeTable::Table { ser, first, .. } => {
-                if first.get() {
-                    let state = ser.state.clone();
-                    ser.emit_table_header(&state)?;
-                }
-            }
-        }
-        Ok(())
+    fn end(self) -> Result<Self::Ok, Self::Error> {
+        write_document(self.dst, self.settings, self.inner.end())
     }
 }
 
-impl<'a, 'b> ser::SerializeStruct for SerializeTable<'a, 'b> {
-    type Ok = ();
-    type Error = Error;
+type InnerSerializeDocumentTable =
+    <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeMap;
 
-    fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
-    where
-        T: ser::Serialize,
-    {
-        match *self {
-            SerializeTable::Datetime(ref mut ser) => {
-                if key == datetime::FIELD {
-                    value.serialize(DateStrEmitter(ser))?;
-                } else {
-                    return Err(Error::DateInvalid);
-                }
-            }
-            SerializeTable::Table {
-                ref mut ser,
-                ref first,
-                ref table_emitted,
-                ..
-            } => {
-                let res = value.serialize(&mut Serializer {
-                    dst: &mut *ser.dst,
-                    state: State::Table {
-                        key,
-                        parent: &ser.state,
-                        first,
-                        table_emitted,
-                    },
-                    settings: ser.settings.clone(),
-                });
-                match res {
-                    Ok(()) => first.set(false),
-                    Err(Error::UnsupportedNone) => {}
-                    Err(e) => return Err(e),
-                }
-            }
-        }
-        Ok(())
-    }
-
-    fn end(self) -> Result<(), Error> {
-        match self {
-            SerializeTable::Datetime(_) => {}
-            SerializeTable::Table { ser, first, .. } => {
-                if first.get() {
-                    let state = ser.state.clone();
-                    ser.emit_table_header(&state)?;
-                }
-            }
+#[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,
         }
-        Ok(())
     }
 }
 
-struct DateStrEmitter<'a, 'b>(&'b mut Serializer<'a>);
-
-impl<'a, 'b> ser::Serializer for DateStrEmitter<'a, 'b> {
+impl<'d> serde::ser::SerializeMap for SerializeDocumentTable<'d> {
     type Ok = ();
     type Error = Error;
-    type SerializeSeq = ser::Impossible<(), Error>;
-    type SerializeTuple = ser::Impossible<(), Error>;
-    type SerializeTupleStruct = ser::Impossible<(), Error>;
-    type SerializeTupleVariant = ser::Impossible<(), Error>;
-    type SerializeMap = ser::Impossible<(), Error>;
-    type SerializeStruct = ser::Impossible<(), Error>;
-    type SerializeStructVariant = ser::Impossible<(), Error>;
-
-    fn serialize_bool(self, _v: bool) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_i8(self, _v: i8) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_i16(self, _v: i16) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
 
-    fn serialize_i32(self, _v: i32) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_i64(self, _v: i64) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_u8(self, _v: u8) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_u16(self, _v: u16) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_u32(self, _v: u32) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_u64(self, _v: u64) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_f32(self, _v: f32) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_f64(self, _v: f64) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_char(self, _v: char) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_str(self, value: &str) -> Result<(), Self::Error> {
-        self.0.display(value, ArrayState::Started)?;
-        Ok(())
-    }
-
-    fn serialize_bytes(self, _value: &[u8]) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_none(self) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
-
-    fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<(), Self::Error>
+    fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        Err(Error::DateInvalid)
+        self.inner.serialize_key(input).map_err(Error::wrap)
     }
 
-    fn serialize_unit(self) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
+    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+    where
+        T: serde::ser::Serialize,
+    {
+        self.inner.serialize_value(value).map_err(Error::wrap)
     }
 
-    fn serialize_unit_struct(self, _name: &'static str) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
+    fn end(self) -> Result<Self::Ok, Self::Error> {
+        write_document(self.dst, self.settings, self.inner.end())
     }
+}
 
-    fn serialize_unit_variant(
-        self,
-        _name: &'static str,
-        _variant_index: u32,
-        _variant: &'static str,
-    ) -> Result<(), Self::Error> {
-        Err(Error::DateInvalid)
-    }
+impl<'d> serde::ser::SerializeStruct for SerializeDocumentTable<'d> {
+    type Ok = ();
+    type Error = Error;
 
-    fn serialize_newtype_struct<T: ?Sized>(
-        self,
-        _name: &'static str,
-        _value: &T,
+    fn serialize_field<T: ?Sized>(
+        &mut self,
+        key: &'static str,
+        value: &T,
     ) -> Result<(), Self::Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        Err(Error::DateInvalid)
+        self.inner.serialize_field(key, value).map_err(Error::wrap)
     }
 
-    fn serialize_newtype_variant<T: ?Sized>(
-        self,
-        _name: &'static str,
-        _variant_index: u32,
-        _variant: &'static str,
-        _value: &T,
-    ) -> Result<(), Self::Error>
-    where
-        T: ser::Serialize,
-    {
-        Err(Error::DateInvalid)
+    fn end(self) -> Result<Self::Ok, Self::Error> {
+        write_document(self.dst, self.settings, self.inner.end())
     }
+}
 
-    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
-        Err(Error::DateInvalid)
-    }
+fn write_document(
+    dst: &mut String,
+    mut settings: DocumentFormatter,
+    value: Result<toml_edit::Value, toml_edit::ser::Error>,
+) -> Result<(), Error> {
+    use std::fmt::Write;
 
-    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
-        Err(Error::DateInvalid)
-    }
+    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));
+        }
+    };
 
-    fn serialize_tuple_struct(
-        self,
-        _name: &'static str,
-        _len: usize,
-    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
-        Err(Error::DateInvalid)
-    }
+    use toml_edit::visit_mut::VisitMut as _;
+    settings.visit_table_mut(&mut table);
 
-    fn serialize_tuple_variant(
-        self,
-        _name: &'static str,
-        _variant_index: u32,
-        _variant: &'static str,
-        _len: usize,
-    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
-        Err(Error::DateInvalid)
-    }
+    let doc: toml_edit::Document = table.into();
+    write!(dst, "{}", doc).unwrap();
 
-    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
-        Err(Error::DateInvalid)
-    }
+    Ok(())
+}
 
-    fn serialize_struct(
-        self,
-        _name: &'static str,
-        _len: usize,
-    ) -> Result<Self::SerializeStruct, Self::Error> {
-        Err(Error::DateInvalid)
-    }
+/// Serialization for TOML values.
+///
+/// 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.
+#[non_exhaustive]
+pub struct ValueSerializer<'d> {
+    dst: &'d mut String,
+}
 
-    fn serialize_struct_variant(
-        self,
-        _name: &'static str,
-        _variant_index: u32,
-        _variant: &'static str,
-        _len: usize,
-    ) -> Result<Self::SerializeStructVariant, Self::Error> {
-        Err(Error::DateInvalid)
+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 }
     }
 }
 
-struct StringExtractor;
-
-impl ser::Serializer for StringExtractor {
-    type Ok = String;
+impl<'d> serde::ser::Serializer for ValueSerializer<'d> {
+    type Ok = ();
     type Error = Error;
-    type SerializeSeq = ser::Impossible<String, Error>;
-    type SerializeTuple = ser::Impossible<String, Error>;
-    type SerializeTupleStruct = ser::Impossible<String, Error>;
-    type SerializeTupleVariant = ser::Impossible<String, Error>;
-    type SerializeMap = ser::Impossible<String, Error>;
-    type SerializeStruct = ser::Impossible<String, Error>;
-    type SerializeStructVariant = ser::Impossible<String, Error>;
+    type SerializeSeq = SerializeValueArray<'d>;
+    type SerializeTuple = SerializeValueArray<'d>;
+    type SerializeTupleStruct = SerializeValueArray<'d>;
+    type SerializeTupleVariant = SerializeValueArray<'d>;
+    type SerializeMap = SerializeValueTable<'d>;
+    type SerializeStruct = SerializeValueTable<'d>;
+    type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
 
-    fn serialize_bool(self, _v: bool) -> Result<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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, value: &str) -> Result<String, Self::Error> {
-        Ok(value.to_string())
+    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, _value: &[u8]) -> Result<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+        write_value(
+            self.dst,
+            toml_edit::ser::ValueSerializer::new().serialize_none(),
+        )
     }
 
-    fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<String, Self::Error>
+    fn serialize_some<T: ?Sized>(self, v: &T) -> Result<Self::Ok, Self::Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        Err(Error::KeyNotString)
+        write_value(
+            self.dst,
+            toml_edit::ser::ValueSerializer::new().serialize_some(v),
+        )
     }
 
-    fn serialize_unit(self) -> Result<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+    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<String, Self::Error> {
-        Err(Error::KeyNotString)
+        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: ?Sized>(
         self,
-        _name: &'static str,
-        value: &T,
-    ) -> Result<String, Self::Error>
+        name: &'static str,
+        v: &T,
+    ) -> Result<Self::Ok, Self::Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        value.serialize(self)
+        write_value(
+            self.dst,
+            toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v),
+        )
     }
 
     fn serialize_newtype_variant<T: ?Sized>(
         self,
-        _name: &'static str,
-        _variant_index: u32,
-        _variant: &'static str,
-        _value: &T,
-    ) -> Result<String, Self::Error>
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+        value: &T,
+    ) -> Result<Self::Ok, Self::Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        Err(Error::KeyNotString)
+        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> {
-        Err(Error::KeyNotString)
+    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 = SerializeValueArray::new(self, ser);
+        Ok(ser)
     }
 
-    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
-        Err(Error::KeyNotString)
+    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,
+        len: usize,
     ) -> Result<Self::SerializeTupleStruct, Self::Error> {
-        Err(Error::KeyNotString)
+        self.serialize_seq(Some(len))
     }
 
     fn serialize_tuple_variant(
@@ -1498,356 +834,189 @@ impl ser::Serializer for StringExtractor {
         _name: &'static str,
         _variant_index: u32,
         _variant: &'static str,
-        _len: usize,
+        len: usize,
     ) -> Result<Self::SerializeTupleVariant, Self::Error> {
-        Err(Error::KeyNotString)
+        self.serialize_seq(Some(len))
     }
 
-    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
-        Err(Error::KeyNotString)
+    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 = SerializeValueTable::new(self, ser);
+        Ok(ser)
     }
 
     fn serialize_struct(
         self,
         _name: &'static str,
-        _len: usize,
+        len: usize,
     ) -> Result<Self::SerializeStruct, Self::Error> {
-        Err(Error::KeyNotString)
+        self.serialize_map(Some(len))
     }
 
     fn serialize_struct_variant(
         self,
-        _name: &'static str,
+        name: &'static str,
         _variant_index: u32,
         _variant: &'static str,
         _len: usize,
     ) -> Result<Self::SerializeStructVariant, Self::Error> {
-        Err(Error::KeyNotString)
+        Err(Error::unsupported_type(Some(name)))
     }
 }
 
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            Error::UnsupportedType => "unsupported Rust type".fmt(f),
-            Error::KeyNotString => "map key was not a string".fmt(f),
-            Error::ValueAfterTable => "values must be emitted before tables".fmt(f),
-            Error::DateInvalid => "a serialized date was invalid".fmt(f),
-            Error::NumberInvalid => "a serialized number was invalid".fmt(f),
-            Error::UnsupportedNone => "unsupported None value".fmt(f),
-            Error::Custom(ref s) => s.fmt(f),
-            Error::KeyNewline => unreachable!(),
-            Error::ArrayMixedType => unreachable!(),
-        }
-    }
-}
-
-impl error::Error for Error {}
-
-impl ser::Error for Error {
-    fn custom<T: fmt::Display>(msg: T) -> Error {
-        Error::Custom(msg.to_string())
-    }
-}
+type InnerSerializeValueSeq = <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeSeq;
 
-enum Category {
-    Primitive,
-    Array,
-    Table,
+#[doc(hidden)]
+pub struct SerializeValueArray<'d> {
+    inner: InnerSerializeValueSeq,
+    dst: &'d mut String,
 }
 
-/// Convenience function to serialize items in a map in an order valid with
-/// TOML.
-///
-/// TOML carries the restriction that keys in a table must be serialized last if
-/// their value is a table itself. This isn't always easy to guarantee, so this
-/// helper can be used like so:
-///
-/// ```rust
-/// # use serde::Serialize;
-/// # use std::collections::HashMap;
-/// #[derive(Serialize)]
-/// struct Manifest {
-///     package: Package,
-///     #[serde(serialize_with = "toml::ser::tables_last")]
-///     dependencies: HashMap<String, Dependency>,
-/// }
-/// # type Package = String;
-/// # type Dependency = String;
-/// # fn main() {}
-/// ```
-pub fn tables_last<'a, I, K, V, S>(data: &'a I, serializer: S) -> Result<S::Ok, S::Error>
-where
-    &'a I: IntoIterator<Item = (K, V)>,
-    K: ser::Serialize,
-    V: ser::Serialize,
-    S: ser::Serializer,
-{
-    use serde::ser::SerializeMap;
-
-    let mut map = serializer.serialize_map(None)?;
-    for (k, v) in data {
-        if let Category::Primitive = v.serialize(Categorize::new())? {
-            map.serialize_entry(&k, &v)?;
-        }
-    }
-    for (k, v) in data {
-        if let Category::Array = v.serialize(Categorize::new())? {
-            map.serialize_entry(&k, &v)?;
+impl<'d> SerializeValueArray<'d> {
+    pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueSeq) -> Self {
+        Self {
+            inner,
+            dst: ser.dst,
         }
     }
-    for (k, v) in data {
-        if let Category::Table = v.serialize(Categorize::new())? {
-            map.serialize_entry(&k, &v)?;
-        }
-    }
-    map.end()
-}
-
-struct Categorize<E>(marker::PhantomData<E>);
-
-impl<E> Categorize<E> {
-    fn new() -> Self {
-        Categorize(marker::PhantomData)
-    }
 }
 
-impl<E: ser::Error> ser::Serializer for Categorize<E> {
-    type Ok = Category;
-    type Error = E;
-    type SerializeSeq = Self;
-    type SerializeTuple = Self;
-    type SerializeTupleStruct = Self;
-    type SerializeTupleVariant = Self;
-    type SerializeMap = Self;
-    type SerializeStruct = Self;
-    type SerializeStructVariant = ser::Impossible<Category, E>;
-
-    fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Primitive)
-    }
-
-    fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Array)
-    }
-
-    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
-        Err(ser::Error::custom("unsupported"))
-    }
-
-    fn serialize_some<T: ?Sized + ser::Serialize>(self, v: &T) -> Result<Self::Ok, Self::Error> {
-        v.serialize(self)
-    }
-
-    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
-        Err(ser::Error::custom("unsupported"))
-    }
-
-    fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
-        Err(ser::Error::custom("unsupported"))
-    }
-
-    fn serialize_unit_variant(
-        self,
-        _: &'static str,
-        _: u32,
-        _: &'static str,
-    ) -> Result<Self::Ok, Self::Error> {
-        Err(ser::Error::custom("unsupported"))
-    }
-
-    fn serialize_newtype_struct<T: ?Sized + ser::Serialize>(
-        self,
-        _: &'static str,
-        v: &T,
-    ) -> Result<Self::Ok, Self::Error> {
-        v.serialize(self)
-    }
-
-    fn serialize_newtype_variant<T: ?Sized + ser::Serialize>(
-        self,
-        _: &'static str,
-        _: u32,
-        _: &'static str,
-        _: &T,
-    ) -> Result<Self::Ok, Self::Error> {
-        Err(ser::Error::custom("unsupported"))
-    }
-
-    fn serialize_seq(self, _: Option<usize>) -> Result<Self, Self::Error> {
-        Ok(self)
-    }
-
-    fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
-        Ok(self)
-    }
-
-    fn serialize_tuple_struct(
-        self,
-        _: &'static str,
-        _: usize,
-    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
-        Ok(self)
-    }
-
-    fn serialize_tuple_variant(
-        self,
-        _: &'static str,
-        _: u32,
-        _: &'static str,
-        _: usize,
-    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
-        Ok(self)
-    }
-
-    fn serialize_map(self, _: Option<usize>) -> Result<Self, Self::Error> {
-        Ok(self)
-    }
+impl<'d> serde::ser::SerializeSeq for SerializeValueArray<'d> {
+    type Ok = ();
+    type Error = Error;
 
-    fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self, Self::Error> {
-        Ok(self)
+    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    where
+        T: serde::ser::Serialize,
+    {
+        self.inner.serialize_element(value).map_err(Error::wrap)
     }
 
-    fn serialize_struct_variant(
-        self,
-        _: &'static str,
-        _: u32,
-        _: &'static str,
-        _: usize,
-    ) -> Result<Self::SerializeStructVariant, Self::Error> {
-        Err(ser::Error::custom("unsupported"))
+    fn end(self) -> Result<Self::Ok, Self::Error> {
+        write_value(self.dst, self.inner.end())
     }
 }
 
-impl<E: ser::Error> ser::SerializeSeq for Categorize<E> {
-    type Ok = Category;
-    type Error = E;
+impl<'d> serde::ser::SerializeTuple for SerializeValueArray<'d> {
+    type Ok = ();
+    type Error = Error;
 
-    fn serialize_element<T: ?Sized + ser::Serialize>(&mut self, _: &T) -> Result<(), Self::Error> {
-        Ok(())
+    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    where
+        T: serde::ser::Serialize,
+    {
+        self.inner.serialize_element(value).map_err(Error::wrap)
     }
 
     fn end(self) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Array)
+        write_value(self.dst, self.inner.end())
     }
 }
 
-impl<E: ser::Error> ser::SerializeTuple for Categorize<E> {
-    type Ok = Category;
-    type Error = E;
+impl<'d> serde::ser::SerializeTupleVariant for SerializeValueArray<'d> {
+    type Ok = ();
+    type Error = Error;
 
-    fn serialize_element<T: ?Sized + ser::Serialize>(&mut self, _: &T) -> Result<(), Self::Error> {
-        Ok(())
+    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    where
+        T: serde::ser::Serialize,
+    {
+        self.inner.serialize_field(value).map_err(Error::wrap)
     }
 
     fn end(self) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Array)
+        write_value(self.dst, self.inner.end())
     }
 }
 
-impl<E: ser::Error> ser::SerializeTupleVariant for Categorize<E> {
-    type Ok = Category;
-    type Error = E;
+impl<'d> serde::ser::SerializeTupleStruct for SerializeValueArray<'d> {
+    type Ok = ();
+    type Error = Error;
 
-    fn serialize_field<T: ?Sized + ser::Serialize>(&mut self, _: &T) -> Result<(), Self::Error> {
-        Ok(())
+    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    where
+        T: serde::ser::Serialize,
+    {
+        self.inner.serialize_field(value).map_err(Error::wrap)
     }
 
     fn end(self) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Array)
+        write_value(self.dst, self.inner.end())
     }
 }
 
-impl<E: ser::Error> ser::SerializeTupleStruct for Categorize<E> {
-    type Ok = Category;
-    type Error = E;
+type InnerSerializeValueTable =
+    <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeMap;
 
-    fn serialize_field<T: ?Sized + ser::Serialize>(&mut self, _: &T) -> Result<(), Self::Error> {
-        Ok(())
-    }
+#[doc(hidden)]
+pub struct SerializeValueTable<'d> {
+    inner: InnerSerializeValueTable,
+    dst: &'d mut String,
+}
 
-    fn end(self) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Array)
+impl<'d> SerializeValueTable<'d> {
+    pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueTable) -> Self {
+        Self {
+            inner,
+            dst: ser.dst,
+        }
     }
 }
 
-impl<E: ser::Error> ser::SerializeMap for Categorize<E> {
-    type Ok = Category;
-    type Error = E;
+impl<'d> serde::ser::SerializeMap for SerializeValueTable<'d> {
+    type Ok = ();
+    type Error = Error;
 
-    fn serialize_key<T: ?Sized + ser::Serialize>(&mut self, _: &T) -> Result<(), Self::Error> {
-        Ok(())
+    fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error>
+    where
+        T: serde::ser::Serialize,
+    {
+        self.inner.serialize_key(input).map_err(Error::wrap)
     }
 
-    fn serialize_value<T: ?Sized + ser::Serialize>(&mut self, _: &T) -> Result<(), Self::Error> {
-        Ok(())
+    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+    where
+        T: serde::ser::Serialize,
+    {
+        self.inner.serialize_value(value).map_err(Error::wrap)
     }
 
     fn end(self) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Table)
+        write_value(self.dst, self.inner.end())
     }
 }
 
-impl<E: ser::Error> ser::SerializeStruct for Categorize<E> {
-    type Ok = Category;
-    type Error = E;
+impl<'d> serde::ser::SerializeStruct for SerializeValueTable<'d> {
+    type Ok = ();
+    type Error = Error;
 
-    fn serialize_field<T: ?Sized>(&mut self, _: &'static str, _: &T) -> Result<(), Self::Error>
+    fn serialize_field<T: ?Sized>(
+        &mut self,
+        key: &'static str,
+        value: &T,
+    ) -> Result<(), Self::Error>
     where
-        T: ser::Serialize,
+        T: serde::ser::Serialize,
     {
-        Ok(())
+        self.inner.serialize_field(key, value).map_err(Error::wrap)
     }
 
     fn end(self) -> Result<Self::Ok, Self::Error> {
-        Ok(Category::Table)
+        write_value(self.dst, self.inner.end())
     }
 }
+
+fn write_value(
+    dst: &mut String,
+    value: Result<toml_edit::Value, toml_edit::ser::Error>,
+) -> Result<(), Error> {
+    use std::fmt::Write;
+
+    let value = value.map_err(Error::wrap)?;
+
+    write!(dst, "{}", value).unwrap();
+
+    Ok(())
+}
diff --git a/crates/toml/src/value.rs b/crates/toml/src/value.rs
index 775b76d7..71e3b5d4 100644
--- a/crates/toml/src/value.rs
+++ b/crates/toml/src/value.rs
@@ -482,9 +482,12 @@ where
 
 impl fmt::Display for Value {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        crate::ser::to_string(self)
-            .expect("Unable to represent value as string")
-            .fmt(f)
+        use serde::Serialize as _;
+
+        let mut output = String::new();
+        let serializer = crate::ser::ValueSerializer::new(&mut output);
+        self.serialize(serializer).unwrap();
+        output.fmt(f)
     }
 }
 
@@ -895,11 +898,11 @@ impl ser::Serializer for ValueSerializer {
     }
 
     fn serialize_unit(self) -> Result<Value, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(Some("unit")))
     }
 
-    fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+    fn serialize_unit_struct(self, name: &'static str) -> Result<Value, crate::ser::Error> {
+        Err(crate::ser::Error::unsupported_type(Some(name)))
     }
 
     fn serialize_unit_variant(
@@ -924,7 +927,7 @@ impl ser::Serializer for ValueSerializer {
 
     fn serialize_newtype_variant<T: ?Sized>(
         self,
-        _name: &'static str,
+        name: &'static str,
         _variant_index: u32,
         _variant: &'static str,
         _value: &T,
@@ -932,11 +935,11 @@ impl ser::Serializer for ValueSerializer {
     where
         T: ser::Serialize,
     {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(Some(name)))
     }
 
     fn serialize_none(self) -> Result<Value, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedNone)
+        Err(crate::ser::Error::unsupported_none())
     }
 
     fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Value, crate::ser::Error>
@@ -993,12 +996,12 @@ impl ser::Serializer for ValueSerializer {
 
     fn serialize_struct_variant(
         self,
-        _name: &'static str,
+        name: &'static str,
         _variant_index: u32,
         _variant: &'static str,
         _len: usize,
     ) -> Result<Self::SerializeStructVariant, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(Some(name)))
     }
 }
 
@@ -1017,76 +1020,76 @@ impl ser::Serializer for TableSerializer {
     type SerializeStructVariant = ser::Impossible<Table, crate::ser::Error>;
 
     fn serialize_bool(self, _value: bool) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_i8(self, _value: i8) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_i16(self, _value: i16) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_i32(self, _value: i32) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_i64(self, _value: i64) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_u8(self, _value: u8) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_u16(self, _value: u16) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_u32(self, _value: u32) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_u64(self, _value: u64) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_f32(self, _value: f32) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_f64(self, _value: f64) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_char(self, _value: char) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_str(self, _value: &str) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_bytes(self, _value: &[u8]) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_unit(self) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_unit_struct(self, _name: &'static str) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_unit_variant(
         self,
-        _name: &'static str,
+        name: &'static str,
         _variant_index: u32,
         _variant: &'static str,
     ) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(Some(name)))
     }
 
     fn serialize_newtype_struct<T: ?Sized>(
@@ -1102,7 +1105,7 @@ impl ser::Serializer for TableSerializer {
 
     fn serialize_newtype_variant<T: ?Sized>(
         self,
-        _name: &'static str,
+        name: &'static str,
         _variant_index: u32,
         _variant: &'static str,
         _value: &T,
@@ -1110,11 +1113,11 @@ impl ser::Serializer for TableSerializer {
     where
         T: ser::Serialize,
     {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(Some(name)))
     }
 
     fn serialize_none(self) -> Result<Table, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedNone)
+        Err(crate::ser::Error::unsupported_none())
     }
 
     fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Table, crate::ser::Error>
@@ -1125,29 +1128,29 @@ impl ser::Serializer for TableSerializer {
     }
 
     fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(None))
     }
 
     fn serialize_tuple_struct(
         self,
-        _name: &'static str,
+        name: &'static str,
         _len: usize,
     ) -> Result<Self::SerializeTupleStruct, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(Some(name)))
     }
 
     fn serialize_tuple_variant(
         self,
-        _name: &'static str,
+        name: &'static str,
         _variant_index: u32,
         _variant: &'static str,
         _len: usize,
     ) -> Result<Self::SerializeTupleVariant, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(Some(name)))
     }
 
     fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, crate::ser::Error> {
@@ -1167,12 +1170,12 @@ impl ser::Serializer for TableSerializer {
 
     fn serialize_struct_variant(
         self,
-        _name: &'static str,
+        name: &'static str,
         _variant_index: u32,
         _variant: &'static str,
         _len: usize,
     ) -> Result<Self::SerializeStructVariant, crate::ser::Error> {
-        Err(crate::ser::Error::UnsupportedType)
+        Err(crate::ser::Error::unsupported_type(Some(name)))
     }
 }
 
@@ -1260,7 +1263,7 @@ impl ser::SerializeMap for SerializeMap {
     {
         match Value::try_from(key)? {
             Value::String(s) => self.next_key = Some(s),
-            _ => return Err(crate::ser::Error::KeyNotString),
+            _ => return Err(crate::ser::Error::key_not_string()),
         };
         Ok(())
     }
@@ -1275,7 +1278,9 @@ impl ser::SerializeMap for SerializeMap {
             Ok(value) => {
                 self.map.insert(key, value);
             }
-            Err(crate::ser::Error::UnsupportedNone) => {}
+            Err(crate::ser::Error {
+                inner: toml_edit::ser::Error::UnsupportedNone,
+            }) => {}
             Err(e) => return Err(e),
         }
         Ok(())


Test patch:
diff --git a/crates/toml/tests/testsuite/display_tricky.rs b/crates/toml/tests/testsuite/display_tricky.rs
index 3fd04fbf..379ae913 100644
--- a/crates/toml/tests/testsuite/display_tricky.rs
+++ b/crates/toml/tests/testsuite/display_tricky.rs
@@ -50,6 +50,6 @@ fn both_ends() {
     )
     .unwrap();
 
-    let recipe_toml = toml::Value::try_from(recipe_fails).unwrap();
+    let recipe_toml = toml::Table::try_from(recipe_fails).unwrap();
     recipe_toml.to_string();
 }
diff --git a/crates/toml/tests/testsuite/pretty.rs b/crates/toml/tests/testsuite/pretty.rs
index dab72c8a..0b06fa2b 100644
--- a/crates/toml/tests/testsuite/pretty.rs
+++ b/crates/toml/tests/testsuite/pretty.rs
@@ -6,7 +6,10 @@ const NO_PRETTY: &str = "\
 array = [\"item 1\", \"item 2\"]
 empty = []
 oneline = \"this has no newlines.\"
-text = \"\\nthis is the first line\\nthis is the second line\\n\"
+text = '''
+
+this is the first line\\nthis is the second line
+'''
 ";
 
 #[test]
@@ -14,43 +17,23 @@ fn no_pretty() {
     let toml = NO_PRETTY;
     let value: toml::Value = toml::from_str(toml).unwrap();
     let mut result = String::with_capacity(128);
-    value
-        .serialize(&mut toml::Serializer::new(&mut result))
-        .unwrap();
-    println!("EXPECTED:\n{}", toml);
-    println!("\nRESULT:\n{}", result);
-    assert_eq!(toml, &result);
-}
-
-#[test]
-fn disable_pretty() {
-    let toml = NO_PRETTY;
-    let value: toml::Value = toml::from_str(toml).unwrap();
-    let mut result = String::with_capacity(128);
-    {
-        let mut serializer = toml::Serializer::pretty(&mut result);
-        serializer.pretty_string(false);
-        serializer.pretty_array(false);
-        value.serialize(&mut serializer).unwrap();
-    }
-    println!("EXPECTED:\n{}", toml);
-    println!("\nRESULT:\n{}", result);
-    assert_eq!(toml, &result);
+    value.serialize(toml::Serializer::new(&mut result)).unwrap();
+    assert_eq(toml, &result);
 }
 
 const PRETTY_STD: &str = "\
 [example]
 array = [
-    'item 1',
-    'item 2',
+    \"item 1\",
+    \"item 2\",
 ]
 empty = []
-one = ['one']
-oneline = 'this has no newlines.'
-text = '''
+one = [\"one\"]
+oneline = \"this has no newlines.\"
+text = \"\"\"
 this is the first line
 this is the second line
-'''
+\"\"\"
 ";
 
 #[test]
@@ -59,139 +42,30 @@ fn pretty_std() {
     let value: toml::Value = toml::from_str(toml).unwrap();
     let mut result = String::with_capacity(128);
     value
-        .serialize(&mut toml::Serializer::pretty(&mut result))
+        .serialize(toml::Serializer::pretty(&mut result))
         .unwrap();
-    println!("EXPECTED:\n{}", toml);
-    println!("\nRESULT:\n{}", result);
     assert_eq(toml, &result);
 }
 
-const PRETTY_INDENT_2: &str = "\
-[example]
-array = [
-  'item 1',
-  'item 2',
-]
-empty = []
-one = ['one']
-oneline = 'this has no newlines.'
-text = '''
-this is the first line
-this is the second line
-'''
-three = [
-  'one',
-  'two',
-  'three',
-]
-";
-
-#[test]
-fn pretty_indent_2() {
-    let toml = PRETTY_INDENT_2;
-    let value: toml::Value = toml::from_str(toml).unwrap();
-    let mut result = String::with_capacity(128);
-    {
-        let mut serializer = toml::Serializer::pretty(&mut result);
-        serializer.pretty_array_indent(2);
-        value.serialize(&mut serializer).unwrap();
-    }
-    println!(">> Result:\n{}", result);
-    assert_eq!(toml, &result);
-}
-
-const PRETTY_INDENT_2_OTHER: &str = "\
-[example]
-array = [
-  \"item 1\",
-  \"item 2\",
-]
-empty = []
-oneline = \"this has no newlines.\"
-text = \"\\nthis is the first line\\nthis is the second line\\n\"
-";
-
-#[test]
-/// Test pretty indent when gotten the other way
-fn pretty_indent_2_other() {
-    let toml = PRETTY_INDENT_2_OTHER;
-    let value: toml::Value = toml::from_str(toml).unwrap();
-    let mut result = String::with_capacity(128);
-    {
-        let mut serializer = toml::Serializer::new(&mut result);
-        serializer.pretty_array_indent(2);
-        value.serialize(&mut serializer).unwrap();
-    }
-    assert_eq!(toml, &result);
-}
-
-const PRETTY_ARRAY_NO_COMMA: &str = "\
-[example]
-array = [
-    \"item 1\",
-    \"item 2\"
-]
-empty = []
-oneline = \"this has no newlines.\"
-text = \"\\nthis is the first line\\nthis is the second line\\n\"
-";
-#[test]
-/// Test pretty indent when gotten the other way
-fn pretty_indent_array_no_comma() {
-    let toml = PRETTY_ARRAY_NO_COMMA;
-    let value: toml::Value = toml::from_str(toml).unwrap();
-    let mut result = String::with_capacity(128);
-    {
-        let mut serializer = toml::Serializer::new(&mut result);
-        serializer.pretty_array_trailing_comma(false);
-        value.serialize(&mut serializer).unwrap();
-    }
-    assert_eq!(toml, &result);
-}
-
-const PRETTY_NO_STRING: &str = "\
-[example]
-array = [
-    \"item 1\",
-    \"item 2\",
-]
-empty = []
-oneline = \"this has no newlines.\"
-text = \"\\nthis is the first line\\nthis is the second line\\n\"
-";
-#[test]
-/// Test pretty indent when gotten the other way
-fn pretty_no_string() {
-    let toml = PRETTY_NO_STRING;
-    let value: toml::Value = toml::from_str(toml).unwrap();
-    let mut result = String::with_capacity(128);
-    {
-        let mut serializer = toml::Serializer::pretty(&mut result);
-        serializer.pretty_string(false);
-        value.serialize(&mut serializer).unwrap();
-    }
-    assert_eq!(toml, &result);
-}
-
 const PRETTY_TRICKY: &str = r##"[example]
 f = "\f"
-glass = '''
+glass = """
 Nothing too unusual, except that I can eat glass in:
 - Greek: Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα. 
 - Polish: Mogę jeść szkło, i mi nie szkodzi. 
 - Hindi: मैं काँच खा सकता हूँ, मुझे उस से कोई पीडा नहीं होती. 
 - Japanese: 私はガラスを食べられます。それは私を傷つけません。 
-'''
+"""
 r = "\r"
 r_newline = """
 \r
 """
-single = '''this is a single line but has '' cuz it's tricky'''
+single = "this is a single line but has '' cuz it's tricky"
 single_tricky = "single line with ''' in it"
-tabs = '''
+tabs = """
 this is pretty standard
-	except for some 	tabs right here
-'''
+\texcept for some   \btabs right here
+"""
 text = """
 this is the first line.
 This has a ''' in it and \"\"\" cuz it's tricky yo
@@ -206,24 +80,22 @@ fn pretty_tricky() {
     let value: toml::Value = toml::from_str(toml).unwrap();
     let mut result = String::with_capacity(128);
     value
-        .serialize(&mut toml::Serializer::pretty(&mut result))
+        .serialize(toml::Serializer::pretty(&mut result))
         .unwrap();
-    println!("EXPECTED:\n{}", toml);
-    println!("\nRESULT:\n{}", result);
-    assert_eq!(toml, &result);
+    assert_eq(toml, &result);
 }
 
 const PRETTY_TABLE_ARRAY: &str = r##"[[array]]
-key = 'foo'
+key = "foo"
 
 [[array]]
-key = 'bar'
+key = "bar"
 
 [abc]
-doc = 'this is a table'
+doc = "this is a table"
 
 [example]
-single = 'this is a single line string'
+single = "this is a single line string"
 "##;
 
 #[test]
@@ -232,11 +104,9 @@ fn pretty_table_array() {
     let value: toml::Value = toml::from_str(toml).unwrap();
     let mut result = String::with_capacity(128);
     value
-        .serialize(&mut toml::Serializer::pretty(&mut result))
+        .serialize(toml::Serializer::pretty(&mut result))
         .unwrap();
-    println!("EXPECTED:\n{}", toml);
-    println!("\nRESULT:\n{}", result);
-    assert_eq!(toml, &result);
+    assert_eq(toml, &result);
 }
 
 const TABLE_ARRAY: &str = r##"[[array]]
@@ -257,56 +127,6 @@ fn table_array() {
     let toml = TABLE_ARRAY;
     let value: toml::Value = toml::from_str(toml).unwrap();
     let mut result = String::with_capacity(128);
-    value
-        .serialize(&mut toml::Serializer::new(&mut result))
-        .unwrap();
-    println!("EXPECTED:\n{}", toml);
-    println!("\nRESULT:\n{}", result);
-    assert_eq(toml, &result);
-}
-
-const PRETTY_TRICKY_NON_LITERAL: &str = r##"[example]
-f = "\f"
-glass = """
-Nothing too unusual, except that I can eat glass in:
-- Greek: Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα. 
-- Polish: Mogę jeść szkło, i mi nie szkodzi. 
-- Hindi: मैं काँच खा सकता हूँ, मुझे उस से कोई पीडा नहीं होती. 
-- Japanese: 私はガラスを食べられます。それは私を傷つけません。 
-"""
-plain = """
-This has a couple of lines
-Because it likes to.
-"""
-r = "\r"
-r_newline = """
-\r
-"""
-single = "this is a single line but has '' cuz it's tricky"
-single_tricky = "single line with ''' in it"
-tabs = """
-this is pretty standard
-\texcept for some \ttabs right here
-"""
-text = """
-this is the first line.
-This has a ''' in it and \"\"\" cuz it's tricky yo
-Also ' and \" because why not
-this is the fourth line
-"""
-"##;
-
-#[test]
-fn pretty_tricky_non_literal() {
-    let toml = PRETTY_TRICKY_NON_LITERAL;
-    let value: toml::Value = toml::from_str(toml).unwrap();
-    let mut result = String::with_capacity(128);
-    {
-        let mut serializer = toml::Serializer::pretty(&mut result);
-        serializer.pretty_string_literal(false);
-        value.serialize(&mut serializer).unwrap();
-    }
-    println!("EXPECTED:\n{}", toml);
-    println!("\nRESULT:\n{}", result);
+    value.serialize(toml::Serializer::new(&mut result)).unwrap();
     assert_eq(toml, &result);
 }
diff --git a/crates/toml/tests/testsuite/serde.rs b/crates/toml/tests/testsuite/serde.rs
index bb5ec8cb..a9dd3e5a 100644
--- a/crates/toml/tests/testsuite/serde.rs
+++ b/crates/toml/tests/testsuite/serde.rs
@@ -28,14 +28,12 @@ macro_rules! equivalent {
         assert_eq!(literal, t!(toml.clone().try_into()));
 
         // Through a string equivalent
-        println!("to_string(literal)");
-        snapbox::assert_eq(toml.to_string(), t!(toml::to_string(&literal)));
-        println!("to_string(toml)");
-        snapbox::assert_eq(toml.to_string(), t!(toml::to_string(&toml)));
+        println!("to_string");
+        snapbox::assert_eq(t!(toml::to_string(&toml)), t!(toml::to_string(&literal)));
         println!("literal, from_str(toml)");
-        assert_eq!(literal, t!(toml::from_str(&toml.to_string())));
+        assert_eq!(literal, t!(toml::from_str(&t!(toml::to_string(&toml)))));
         println!("toml, from_str(toml)");
-        assert_eq!(toml, t!(toml::from_str(&toml.to_string())));
+        assert_eq!(toml, t!(toml::from_str(&t!(toml::to_string(&toml)))));
     }};
 }
 
diff --git a/crates/toml/tests/testsuite/tables_last.rs b/crates/toml/tests/testsuite/tables_last.rs
index 32a94a9f..3339e0a0 100644
--- a/crates/toml/tests/testsuite/tables_last.rs
+++ b/crates/toml/tests/testsuite/tables_last.rs
@@ -2,21 +2,21 @@ use std::collections::HashMap;
 
 use serde::Serialize;
 
-#[derive(Serialize)]
-struct A {
-    #[serde(serialize_with = "toml::ser::tables_last")]
-    vals: HashMap<&'static str, Value>,
-}
-
-#[derive(Serialize)]
-#[serde(untagged)]
-enum Value {
-    Map(HashMap<&'static str, &'static str>),
-    Int(i32),
-}
-
 #[test]
 fn always_works() {
+    // Ensure this works without the removed "toml::ser::tables_last"
+    #[derive(Serialize)]
+    struct A {
+        vals: HashMap<&'static str, Value>,
+    }
+
+    #[derive(Serialize)]
+    #[serde(untagged)]
+    enum Value {
+        Map(HashMap<&'static str, &'static str>),
+        Int(i32),
+    }
+
     let mut a = A {
         vals: HashMap::new(),
     };