1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//! Parse and write YAML compatible with deser.
//!
//! ```rust
//! use deser::{Deserialize, Serialize};
//!
//! #[derive(Deserialize, Serialize, Debug)]
//! struct Config {
//! name: String,
//! ports: Vec<u16>,
//! }
//!
//! let config: Config = deser_yaml::from_str("
//! name: web
//! ports: [80, 443]
//! ").unwrap();
//! assert_eq!(config.name, "web");
//! assert_eq!(config.ports, [80, 443]);
//!
//! assert_eq!(
//! deser_yaml::to_string(&config).unwrap(),
//! "name: web\nports:\n - 80\n - 443\n"
//! );
//! ```
//!
//! # Data Model
//!
//! The YAML parser passes the complete official
//! [YAML test suite](https://github.com/yaml/yaml-test-suite). YAML maps
//! onto the deser data model as follows:
//!
//! | YAML | deser |
//! |---------------------------------------|-----------------------------------------|
//! | `null`, `~`, empty | `Null` |
//! | `true`, `false` | `Bool` |
//! | integers | `U64`, `I64` (`u128` / `i128` if wider) |
//! | floats | `F64` |
//! | other scalars | `Str` |
//! | `!!binary` | `Bytes` |
//! | `!!timestamp` | [`Datetime`](deser_core::ext::Datetime) |
//! | mappings and sequences | maps and sequences |
//!
//! Which plain (unquoted) scalars are null, booleans or numbers depends on
//! the YAML version, see [`Version`]. As their type is inferred from
//! their text, they are passed on as
//! [`Implicit`](deser_core::Atom::Implicit) atoms: types that expect strings
//! receive the text, all others the value. `version: 1.10` is `1.1` for an
//! `f64` and `"1.10"` for a `String`, `~` is `None` for an `Option<String>`
//! and `"~"` for a `String`, and keys like `200` work for maps with string
//! keys. Quoted scalars are always strings and scalars with a standard tag
//! (like `!!int 42`) are always of the type of their tag.
//!
//! ```rust
//! #[derive(deser::Deserialize)]
//! struct Package {
//! version: String,
//! port: u16,
//! }
//!
//! let package: Package =
//! deser_yaml::from_str("version: 1.10\nport: 0x1F").unwrap();
//! assert_eq!(package.version, "1.10");
//! assert_eq!(package.port, 31);
//! ```
//! The standard tags (`!!str`, `!!int`, `!!float`, `!!bool`, `!!null`,
//! `!!binary`, `!!timestamp`, `!!seq` and `!!map`) determine the type of a
//! value, all other tags are passed on out of band (see [Tags](#tags)).
//! Timestamps are only recognized with an explicit `!!timestamp` tag. They
//! are passed on as the well-known [`Datetime`](deser_core::ext::Datetime) type
//! (a date or an offset date-time, timestamps without time zone are in UTC)
//! which falls back to a string. Map keys can be of any
//! type.
//!
//! Aliases are expanded: every alias produces the events of the node it
//! refers to (see [`DeserializerConfig::set_alias_limit`]).
//!
//! # Serialization
//!
//! [`to_string`] writes values as block collections: sequences with `-`,
//! mappings with `key: value`, empty collections as `{}` and `[]`. How the
//! output looks can be configured with [`SerializerConfig`] (indentation,
//! quoting, null, bytes, ...). Values are always written so that they read
//! back as the same values, also by readers of YAML 1.1 (such as PyYAML)
//! unless configured otherwise with [`SerializerConfig::set_compat`]:
//!
//! | deser | YAML |
//! |-----------------------------------------|-----------------------------------------------|
//! | `Null` | `null` (see [`NullStyle`]) |
//! | `Bool`, integers | `true`, `false`, `42` |
//! | `F32`, `F64` | `1.5`, `1.0e+20`, `.inf`, `.nan` (the shortest text for the precision) |
//! | `Str` | plain if possible, otherwise quoted (see [`QuoteStyle`]), with line breaks as literal block scalar (see [`MultilineStyle`]) |
//! | [`Implicit`](deser_core::Atom::Implicit) | its text if readers read it as the same value (`1.10`, `0x1F`, `~`), otherwise the value |
//! | `Bytes` | `!!binary` (see [`SerializerConfig::set_binary`]) |
//! | [`Datetime`](deser_core::ext::Datetime) | timestamp (see [`SerializerConfig::set_timestamp_tag`]) |
//! | maps and sequences | block mappings and sequences, flow style (`[a, b]`, `{a: 1}`) if compact (see [`FlowPolicy`]), keys that are collections or long use `? key` |
//!
//! The style of individual values can be requested with hints: the
//! well-known [`Layout`](deser_core::hints::Layout) for collections (flow or
//! block) and [`ScalarStyle`](style::ScalarStyle) for strings (see
//! [`style`]). Values set them with adapters, layers can set them for
//! instance by path. Hints are preferences: a value is written in another
//! style if the requested one cannot represent it. When reading, flow
//! collections are reported as compact so that they stay flow collections
//! through a [`Recording`](deser_core::de::Recording). Plain scalars keep
//! their text the same way, `version: 1.10` read into a `deser_value::Value` or a
//! recording is written as `version: 1.10` again.
//!
//! Tags are written with [`Tagged`] or [`set_tag`] (see [Tags](#tags)). Streams of
//! multiple documents are written with [`Serializer`].
//!
//! # Tags
//!
//! Tags are not part of the deser data model. The standard tags determine
//! the type of a value (see [Data Model](#data-model)), all
//! other tags are exchanged out of band through the
//! [`State`](deser_core::State):
//!
//! * When deserializing, the tag of a node is published into the state for
//! the first event of the node (the atom or the start of the map or
//! sequence). Types can pick it up with [`take_tag`].
//! Types which do not care about tags never see them, which means that
//! unknown tags are transparent: the value of `!color red` is the string
//! `red`.
//! * When serializing, [`set_tag`] registers the tag of a value in the state
//! and the serializer writes it in front of the node.
//! * [`Tagged`] captures the tag of a value and writes it.
//!
//! Both directions use the same event data, so values which capture event
//! data (such as [`Recording`](deser_core::de::Recording)) keep the tags.
//!
//! Tags are reported fully resolved: `!foo` stays `!foo` but `!!set`
//! becomes `tag:yaml.org,2002:set` and tag handles declared with `%TAG`
//! directives are expanded.
//!
//! # Documents
//!
//! A YAML stream can contain multiple documents. [`from_str`] expects at
//! most one document, [`Deserializer`] can read them one by one:
//!
//! ```rust
//! let mut de = deser_yaml::Deserializer::from_str("--- a\n--- b\n");
//! let docs = de.iter::<String>().collect::<Result<Vec<_>, _>>().unwrap();
//! assert_eq!(docs, ["a", "b"]);
//! ```
//!
//! # Streams
//!
//! Values are read from a [`Read`](std::io::Read) with [`from_reader`]
//! and written to a [`Write`](std::io::Write) with [`to_writer`]. To read
//! or write streams of documents the configurations create readers and
//! writers of [`deser::io`](deser_core::io) ([`DeserializerConfig::reader`]
//! and [`SerializerConfig::writer`]). The reader only buffers until a
//! document is complete:
//!
//! ```rust
//! # #[cfg(feature = "io")] {
//! use deser_yaml::{DeserializerConfig, SerializerConfig};
//!
//! const ENDED: SerializerConfig =
//! SerializerConfig::builder().end_documents(true).build();
//! let mut writer = ENDED.writer(Vec::new());
//! writer.write(&vec![1, 2]).unwrap();
//! writer.write(&"done").unwrap();
//! let output = writer.into_inner();
//! assert_eq!(output, b"- 1\n- 2\n...\n---\ndone\n...\n");
//!
//! let mut reader = DeserializerConfig::new().reader(&output[..]);
//! assert_eq!(reader.read::<Vec<u32>>().unwrap(), Some(vec![1, 2]));
//! assert_eq!(reader.read::<String>().unwrap().as_deref(), Some("done"));
//! assert_eq!(reader.read::<String>().unwrap(), None);
//! # }
//! ```
//!
//! The stream serializer ([`Serializer`]) and the stream deserializer
//! ([`StreamDeserializer`]) do not do IO themselves (see
//! [`deser::stream`](deser_core::stream)), they also work with other kinds
//! of IO (for instance async runtimes with `deser-tokio`).
//!
//! # Features
//!
//! * `io` (enabled by default): reading and writing streams of the
//! standard library, see [streams](#streams).
//! * `speedups` (enabled by default): validates UTF-8 with
//! [`simdutf8`](https://docs.rs/simdutf8).
// `copy.rs` is shared with other formats which only need `alloc`
extern crate alloc;
pub use ;
pub use Version;
pub use to_writer;
pub use ;
pub use StreamDeserializer;
pub use from_reader;
pub use ;