Expand description
Parse and write YAML compatible with deser.
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. 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 |
| 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 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.
#[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).
Timestamps are only recognized with an explicit !!timestamp tag. They
are passed on as the well-known 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 | its text if readers read it as the same value (1.10, 0x1F, ~), otherwise the value |
Bytes | !!binary (see SerializerConfig::set_binary) |
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 for collections (flow or
block) and 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. 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). 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), all
other tags are exchanged out of band through the
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 redis the stringred. - When serializing,
set_tagregisters the tag of a value in the state and the serializer writes it in front of the node. Taggedcaptures the tag of a value and writes it.
Both directions use the same event data, so values which capture event
data (such as 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:
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 with from_reader
and written to a Write with to_writer. To read
or write streams of documents the configurations create readers and
writers of deser::io (DeserializerConfig::reader
and SerializerConfig::writer). The reader only buffers until a
document is complete:
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), they also work with other kinds
of IO (for instance async runtimes with deser-tokio).
§Features
Modules§
- style
- Hints for the style of YAML scalars.
Structs§
- Deserializer
- Deserializes YAML.
- Deserializer
Config - Configures how YAML is deserialized.
- Deserializer
Config Builder - Builds a
DeserializerConfig. - Iter
- An iterator over the documents of a YAML stream.
- Serializer
- Serializes values into YAML documents.
- Serializer
Config - Configures how values are serialized to YAML.
- Serializer
Config Builder - Builds a
SerializerConfig. - Stream
Deserializer - Reads a stream of YAML documents (see
deser::stream). - Tagged
- A value with an optional YAML tag.
Enums§
- Flow
Policy - When collections are written in flow style (
[a, b],{a: 1}). - Indent
- How the output is indented.
- Multiline
Style - How strings with line breaks are written.
- Null
Style - How null is written.
- Quote
Style - How strings are quoted when they cannot be written plain.
- Version
- The YAML version that determines how plain scalars are resolved.
Functions§
- from_
reader - Deserializes a value from a reader.
- from_
slice - Deserializes a value from YAML in a byte slice.
- from_
str - Deserializes a value from YAML.
- set_tag
- Sets the tag of the node that is serialized.
- take_
tag - Takes the tag of the current node from the state.
- to_
string - Serializes a value to YAML.
- to_
writer - Serializes a value to a writer.