deser_toml/lib.rs
1//! Parse and serialize [TOML](https://toml.io/en/v1.1.0) compatible with
2//! deser.
3//!
4//! ```rust
5//! use deser::{Deserialize, Serialize};
6//!
7//! #[derive(Deserialize, Serialize, Debug)]
8//! struct Config {
9//! name: String,
10//! ports: Vec<u16>,
11//! }
12//!
13//! let config: Config = deser_toml::from_str(r#"
14//! name = "web"
15//! ports = [80, 443]
16//! "#).unwrap();
17//! assert_eq!(config.name, "web");
18//! assert_eq!(config.ports, [80, 443]);
19//!
20//! let toml = deser_toml::to_string(&config).unwrap();
21//! assert_eq!(toml, "name = \"web\"\nports = [80, 443]\n");
22//! ```
23//!
24//! # Data Model
25//!
26//! The parser implements TOML 1.1 and passes the
27//! [toml-test](https://github.com/toml-lang/toml-test) suite. TOML maps
28//! onto the deser data model as follows:
29//!
30//! | TOML | deser |
31//! |---------------------------------------|-----------------------------------------|
32//! | tables (including the document) | maps |
33//! | arrays (including arrays of tables) | sequences |
34//! | strings | `Str` |
35//! | integers | `U64`, `I64` |
36//! | floats | `F64` |
37//! | booleans | `Bool` |
38//! | date-times, dates and times | [`Datetime`] |
39//!
40//! Date-times are passed through deser as the well-known
41//! [`Datetime`] extension type which falls back to a
42//! string for types that do not know it. With the respective features of
43//! deser, the date and time types of `jiff`, `chrono` and `time` can be
44//! used directly (this example requires the `jiff` feature of deser):
45//!
46//! ```rust
47//! use deser::{Deserialize, Serialize};
48//!
49//! #[derive(Deserialize, Serialize)]
50//! struct Event {
51//! start: jiff::Timestamp,
52//! day: jiff::civil::Date,
53//! }
54//!
55//! let event: Event = deser_toml::from_str("
56//! start = 2024-06-19 15:22:45-04:00
57//! day = 2024-06-19
58//! ").unwrap();
59//! assert_eq!(event.start.to_string(), "2024-06-19T19:22:45Z");
60//!
61//! let toml = deser_toml::to_string(&event).unwrap();
62//! assert_eq!(toml, "start = 2024-06-19T19:22:45Z\nday = 2024-06-19\n");
63//! ```
64//!
65//! The document is always a table. Keys are emitted in the order in which
66//! they are defined in the document.
67//!
68//! Integers are supported in the range of `i64` and `u64`, integers that
69//! do not fit are an error. Floats that overflow to infinity are an error
70//! as well. Newlines in multi-line strings are normalized to `\n`. A
71//! UTF-8 byte order mark at the start of the document is ignored.
72//!
73//! When serializing, maps are written as tables and sequences of maps as
74//! arrays of tables. The well-known [`Timestamp`](deser_core::ext::Timestamp)
75//! type is written as offset date-time in UTC, other well-known types
76//! (such as UUIDs and decimals) are written as strings. Floats are
77//! written with the shortest text that reads back as the same value of
78//! their precision (`0.1f32` as `0.1`). TOML has no null value: map
79//! entries with null values
80//! are skipped and null values in sequences are an error. TOML has no
81//! bytes either, they are written as base64 strings by default (see
82//! [bytes](deser_core::adapters#bytes)). See [`SerializerConfig`] for more
83//! information.
84//!
85//! # Streams
86//!
87//! Documents are read from a [`Read`](std::io::Read) with [`from_reader`]
88//! and written to a [`Write`](std::io::Write) with [`to_writer`]. The
89//! configurations also create readers and writers of
90//! [`deser::io`](deser_core::io) ([`DeserializerConfig::reader`] and
91//! [`SerializerConfig::writer`]), the stream serializer ([`Serializer`])
92//! and deserializer ([`StreamDeserializer`]) work with other kinds of IO
93//! too (for instance async runtimes with `deser-tokio`). As TOML
94//! documents cannot be split, the whole document is read before it's
95//! parsed.
96//!
97//! # Features
98//!
99//! * `io` (enabled by default): reading and writing streams of the
100//! standard library, see [streams](#streams).
101//! * `speedups` (enabled by default): validates UTF-8 with
102//! [`simdutf8`](https://docs.rs/simdutf8).
103#![doc(html_logo_url = "https://raw.githubusercontent.com/mitsuhiko/deser/main/artwork/logo.svg")]
104
105// `copy.rs` is shared with other formats which only need `alloc`
106extern crate alloc;
107
108mod copy;
109mod datetime;
110mod de;
111mod document;
112mod parser;
113mod scan;
114mod ser;
115mod stream;
116
117pub use self::de::{
118 Deserializer, DeserializerConfig, DeserializerConfigBuilder, from_slice, from_str,
119};
120#[cfg(feature = "io")]
121pub use self::ser::to_writer;
122pub use self::ser::{Serializer, SerializerConfig, SerializerConfigBuilder, to_string};
123pub use self::stream::StreamDeserializer;
124#[cfg(feature = "io")]
125pub use self::stream::from_reader;
126/// Re-exported from [`deser::ext`](deser_core::ext) for convenience.
127pub use deser_core::ext::{Date, Datetime, Offset, Time};