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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
//!
//! Rust library for using the [Serde] serialization framework with data in
//! [YAML] file format.
//!
//! [Serde]: https://github.com/serde-rs/serde
//! [YAML]: https://yaml.org/
//!
//! # Examples
//!
//! ```
//! use std::collections::BTreeMap;
//!
//! fn main() -> Result<(), serde_yaml_gtc::Error> {
//! // You have some type.
//! let mut map = BTreeMap::new();
//! map.insert("x".to_string(), 1.0);
//! map.insert("y".to_string(), 2.0);
//!
//! // Serialize it to a YAML string.
//! let yaml = serde_yaml_gtc::to_string(&map)?;
//! assert_eq!(yaml, "x: 1.0\ny: 2.0\n");
//!
//! // Deserialize it back to a Rust type.
//! let deserialized_map: BTreeMap<String, f64> = serde_yaml_gtc::from_str(&yaml)?;
//! assert_eq!(map, deserialized_map);
//! Ok(())
//! }
//! ```
//! ## Errors
//!
//! Attempting to serialize a value with an invalid YAML tag will
//! result in an [`Error`] whose cause is internally represented by the private
//! `TagError` variant.
//!
//! ## Using Serde derive
//!
//! It can also be used with Serde's derive macros to handle structs and enums
//! defined in your program.
//!
//! Structs serialize in the obvious way:
//!
//! ```
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Serialize, Deserialize, PartialEq, Debug)]
//! struct Point {
//! x: f64,
//! y: f64,
//! }
//!
//! fn main() -> Result<(), serde_yaml_gtc::Error> {
//! let point = Point { x: 1.0, y: 2.0 };
//!
//! let yaml = serde_yaml_gtc::to_string(&point)?;
//! assert_eq!(yaml, "x: 1.0\ny: 2.0\n");
//!
//! let deserialized_point: Point = serde_yaml_gtc::from_str(&yaml)?;
//! assert_eq!(point, deserialized_point);
//! Ok(())
//! }
//! ```
//!
//! Enums serialize using a YAML map whose key is the variant name.
//!
//! ```
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Serialize, Deserialize, PartialEq, Debug)]
//! enum Enum {
//! Unit,
//! Newtype(usize),
//! Tuple(usize, usize, usize),
//! Struct { x: f64, y: f64 },
//! }
//!
//! fn main() -> Result<(), serde_yaml_gtc::Error> {
//! let yaml = "
//! - Newtype: 1
//! - Tuple:
//! - 0
//! - 0
//! - 0
//! - Struct:
//! x: 1.0
//! y: 2.0
//! ";
//! let values: Vec<Enum> = serde_yaml_gtc::from_str(yaml)?;
//! assert_eq!(values[0], Enum::Newtype(1));
//! assert_eq!(values[1], Enum::Tuple(0, 0, 0));
//! assert_eq!(values[2], Enum::Struct { x: 1.0, y: 2.0 });
//!
//! // The last two in YAML's block style instead:
//! let yaml = "
//! - Tuple:
//! - 0
//! - 0
//! - 0
//! - Struct:
//! x: 1.0
//! y: 2.0
//! ";
//! let values: Vec<Enum> = serde_yaml_gtc::from_str(yaml)?;
//! assert_eq!(values[0], Enum::Tuple(0, 0, 0));
//! assert_eq!(values[1], Enum::Struct { x: 1.0, y: 2.0 });
//!
//! // Variants with no data are written as just the string name.
//! let yaml = "
//! - Unit
//! ";
//! let values: Vec<Enum> = serde_yaml_gtc::from_str(yaml)?;
//! assert_eq!(values[0], Enum::Unit);
//!
//! Ok(())
//! }
//! ```
//!
//! ## Using `Value`
//!
//! The `Value` enum represents any YAML node at runtime. It is useful when you
//! don't have a fixed Rust type or when you need to preserve YAML features such
//! as anchors and aliases.
//!
//! Basic construction examples:
//!
//! ```
//! use serde_yaml_gtc::{Mapping, Value};
//!
//! // Scalars
//! let n = Value::from(42); // number
//! let b = Value::from(true); // bool
//! let s = Value::from("hello"); // string
//!
//! // Sequence from Vec and from iterator
//! let seq = Value::from(vec![1, 2, 3]);
//! let seq2: Value = ["a", "b", "c"].into_iter().collect();
//!
//! // Mapping (a key to value map)
//! let mut m = Mapping::new();
//! m.set("name", Value::from("app"));
//! m.set("version", Value::from(1));
//! let doc = Value::from(m);
//!
//! // Serialize to YAML
//! let yaml = serde_yaml_gtc::to_string(&doc).unwrap();
//! assert!(yaml.contains("name: app"));
//! ```
//!
//! ### Anchors and aliases
//!
//! When building `Value`s manually you can attach an anchor to scalars,
//! sequences, and mappings, and you can create `Value::Alias` nodes that refer
//! to them by name. During serialization, aliases to missing anchors are
//! rejected by default.
//!
//! ```
//! use serde_yaml_gtc::{Mapping, Value};
//!
//! // Create a scalar with an anchor "greet"
//! let anchored = Value::String("Hello".to_string(), Some("greet".to_string()));
//!
//! // Build a small document that reuses the anchored value via an alias
//! let mut root = Mapping::new();
//! root.set("first", anchored.clone());
//! root.set("second", Value::Alias("greet".to_string()));
//! let yaml = serde_yaml_gtc::to_string(&Value::from(root)).unwrap();
//!
//! // The exact formatting may vary, but both an anchor and an alias are emitted
//! assert!(yaml.contains("&greet"), "expected an anchor in: {yaml}");
//! assert!(yaml.contains("*greet"), "expected an alias in: {yaml}");
//! ```
//!
//! Anchors can be attached to complex nodes too:
//!
//! ```
//! use serde_yaml_gtc::{Mapping, Value};
//!
//! // An anchored mapping
//! let mut base = Mapping::with_anchor("base");
//! base.set("x", 1.into());
//! base.set("y", 2.into());
//!
//! // Refer to it elsewhere using an alias node
//! let mut root = Mapping::new();
//! root.set("anchor", Value::from(base));
//! root.set("alias", Value::Alias("base".into()));
//!
//! let out = serde_yaml_gtc::to_string(&Value::from(root)).unwrap();
//! assert!(out.contains("&base"));
//! assert!(out.contains("*base"));
//! ```
//!
//! If you serialize an alias whose anchor has not appeared earlier in the
//! document, serialization fails by default. You can change this behavior using
//! `SerializerBuilder::check_unresolved_anchors(false)` if you prefer deferred
//! checking on the consumer side.
//!
//! ```
//! use serde::Serialize;
//! use serde_yaml_gtc::{SerializerBuilder, Value};
//!
//! // Try to serialize a dangling alias and observe the error.
//! let mut buf = Vec::new();
//! let mut ser = SerializerBuilder::default()
//! .check_unresolved_anchors(true)
//! .build(&mut buf)
//! .unwrap();
//!
//! let err = Value::Alias("missing".into()).serialize(&mut ser).unwrap_err();
//! assert!(err.to_string().starts_with("reference to non existing anchor"));
//! ```
//!
//! For in-memory processing of YAML Values that contain anchors/aliases, you
//! can expand aliases after parsing:
//!
//! ```
//! use serde_yaml_gtc::Value;
//!
//! let yaml = "a: &id 1\nb: *id\n";
//! let mut v: Value = serde_yaml_gtc::from_str_value_preserve(yaml).unwrap();
//! v.resolve_aliases().unwrap();
//! assert_eq!(v["a"].as_i64(), v["b"].as_i64());
//! ```
// Suppressed clippy_pedantic lints
pub use crate;
pub use crate;
pub use crateSequenceStyle;
pub use crate;
pub use crate;
pub use crateMapping;
pub use crateunexpected;
// Prevent downstream code from implementing the Index trait.