/rust/registry/src/index.crates.io-1949cf8c6b5b557f/deser-yaml-0.10.1/src/de.rs
Line | Count | Source |
1 | | use std::borrow::Cow; |
2 | | use std::collections::{HashMap, HashSet}; |
3 | | use std::marker::PhantomData; |
4 | | use std::sync::Arc; |
5 | | |
6 | | use deser_core::de::{self, Deserialize, DeserializeDriver, deserialize_value}; |
7 | | use deser_core::hints::Layout; |
8 | | use deser_core::{Atom, Error, ErrorKind, Event, Implicit, ImplicitValue, Source, TrackLocations}; |
9 | | |
10 | | use crate::event::{Event as YamlEvent, EventKind, Mark, ScalarStyle}; |
11 | | use crate::parser::{Parser, error_at}; |
12 | | use crate::resolve::{ScalarTag, Version}; |
13 | | use crate::resolve::{ |
14 | | classify_tag, is_collection_tag, resolve_plain, resolve_plain_implicit, resolve_standard, |
15 | | }; |
16 | | use crate::tag::NodeTag; |
17 | | |
18 | | /// The default for [`DeserializerConfig::set_alias_limit`]. |
19 | | const DEFAULT_ALIAS_LIMIT: usize = 1_000_000; |
20 | | |
21 | | /// Configures how YAML is deserialized. |
22 | | /// |
23 | | /// The configuration is independent of the input so it can be created once |
24 | | /// (even as a constant) and used for many inputs. The methods |
25 | | /// [`from_str`](Self::from_str) and [`from_slice`](Self::from_slice) work |
26 | | /// like the functions of the same name. To read multiple documents with |
27 | | /// the configuration create a [`Deserializer`] with |
28 | | /// [`Deserializer::from_str_with_config`] or |
29 | | /// [`Deserializer::from_slice_with_config`]. |
30 | | /// |
31 | | /// ``` |
32 | | /// use deser_yaml::{DeserializerConfig, Version}; |
33 | | /// |
34 | | /// const CONFIG: DeserializerConfig = DeserializerConfig::builder() |
35 | | /// .version(Version::V1_1).build(); |
36 | | /// let (flag, mode): (bool, u32) = CONFIG.from_str("[yes, 0777]").unwrap(); |
37 | | /// assert_eq!((flag, mode), (true, 0o777)); |
38 | | /// ``` |
39 | | #[derive(Debug, Clone, PartialEq, Eq)] |
40 | | pub struct DeserializerConfig { |
41 | | version: Version, |
42 | | alias_limit: usize, |
43 | | merge_keys: bool, |
44 | | |
45 | | context: deser_core::Context, |
46 | | } |
47 | | |
48 | | impl Default for DeserializerConfig { |
49 | 0 | fn default() -> DeserializerConfig { |
50 | 0 | DeserializerConfig::new() |
51 | 0 | } |
52 | | } |
53 | | |
54 | | impl DeserializerConfig { |
55 | | /// Creates the default configuration. |
56 | 37.6k | pub const fn new() -> DeserializerConfig { |
57 | 37.6k | DeserializerConfig { |
58 | 37.6k | version: Version::V1_2, |
59 | 37.6k | alias_limit: DEFAULT_ALIAS_LIMIT, |
60 | 37.6k | merge_keys: true, |
61 | 37.6k | |
62 | 37.6k | context: deser_core::Context::new(), |
63 | 37.6k | } |
64 | 37.6k | } |
65 | | |
66 | | /// Returns a builder for the configuration (see [`DeserializerConfigBuilder`]). |
67 | 0 | pub const fn builder() -> DeserializerConfigBuilder { |
68 | 0 | DeserializerConfigBuilder::new() |
69 | 0 | } |
70 | | |
71 | | /// Returns a builder that starts with this configuration. |
72 | 0 | pub const fn into_builder(self) -> DeserializerConfigBuilder { |
73 | 0 | DeserializerConfigBuilder { value: self } |
74 | 0 | } |
75 | | |
76 | | /// Sets the context the values are deserialized in. |
77 | | /// |
78 | | /// The values of the context are the defaults of the extension values |
79 | | /// of the state (see [`Context`](deser_core::Context)), for instance |
80 | | /// the variants of open enums. The deserializers and readers created |
81 | | /// with the configuration use this context. A context set |
82 | | /// on the driver takes precedence. |
83 | 0 | pub fn set_context(&mut self, context: deser_core::Context) { |
84 | 0 | self.context = context; |
85 | 0 | } |
86 | | |
87 | | /// Returns the configuration without its context (for the frames of |
88 | | /// streams, which get the context of the stream). |
89 | 0 | pub(crate) fn without_context(&self) -> DeserializerConfig { |
90 | 0 | let mut config = self.clone(); |
91 | 0 | config.context = deser_core::Context::default(); |
92 | 0 | config |
93 | 0 | } |
94 | | |
95 | | /// Returns the context the values are deserialized in. |
96 | 0 | pub fn context(&self) -> &deser_core::Context { |
97 | 0 | &self.context |
98 | 0 | } |
99 | | |
100 | | /// Sets the YAML version for documents that do not declare one. |
101 | | /// |
102 | | /// The version determines how plain scalars are resolved. Documents |
103 | | /// that start with a `%YAML` directive use the version they declare. The |
104 | | /// default is [`Version::V1_2`]. |
105 | 0 | pub const fn set_version(&mut self, version: Version) { |
106 | 0 | self.version = version; |
107 | 0 | } |
108 | | |
109 | | /// Limits the number of events that aliases can expand to per document. |
110 | | /// |
111 | | /// Every scalar and every start and end of a collection that is replayed |
112 | | /// for an alias counts as one event. The default is 1,000,000. |
113 | 0 | pub const fn set_alias_limit(&mut self, limit: usize) { |
114 | 0 | self.alias_limit = limit; |
115 | 0 | } |
116 | | |
117 | | /// Enables or disables merge keys. |
118 | | /// |
119 | | /// Merge keys (`<<`) insert the entries of other mappings into a |
120 | | /// mapping. They are defined for YAML 1.1 but widely used with all |
121 | | /// versions of YAML, which is why they are enabled by default: |
122 | | /// |
123 | | /// ``` |
124 | | /// use std::collections::BTreeMap; |
125 | | /// use deser::Deserialize; |
126 | | /// |
127 | | /// #[derive(Deserialize)] |
128 | | /// struct Service { |
129 | | /// image: String, |
130 | | /// replicas: u32, |
131 | | /// } |
132 | | /// |
133 | | /// let input = " |
134 | | /// base: &base {image: app, replicas: 1} |
135 | | /// web: |
136 | | /// <<: *base |
137 | | /// replicas: 3 |
138 | | /// "; |
139 | | /// let value: BTreeMap<String, Service> = |
140 | | /// deser_yaml::from_str(input).unwrap(); |
141 | | /// assert_eq!(value["web"].image, "app"); |
142 | | /// assert_eq!(value["web"].replicas, 3); |
143 | | /// ``` |
144 | | /// |
145 | | /// Only a plain `<<` is a merge key (`"<<"` is a regular key). Its value |
146 | | /// must be a mapping or a sequence of mappings. Keys of the mapping take |
147 | | /// precedence over merged keys, and with multiple mappings the earlier |
148 | | /// ones take precedence. The merged entries are emitted after the |
149 | | /// entries of the mapping. |
150 | | /// |
151 | | /// When disabled, `<<` is a regular key. |
152 | 0 | pub const fn set_merge_keys(&mut self, yes: bool) { |
153 | 0 | self.merge_keys = yes; |
154 | 0 | } |
155 | | |
156 | | /// Deserializes a value from YAML. |
157 | | /// |
158 | | /// See [`from_str`]. |
159 | 25.1k | pub fn from_str<'de, T: Deserialize<'de>>(&self, s: &'de str) -> Result<T, Error> { |
160 | 25.1k | deserialize_value(|driver| self.drive_str(s, driver)) <deser_yaml::de::DeserializerConfig>::from_str::<deser_value::value::Value>::{closure#0}Line | Count | Source | 160 | 25.1k | deserialize_value(|driver| self.drive_str(s, driver)) |
Unexecuted instantiation: <deser_yaml::de::DeserializerConfig>::from_str::<_>::{closure#0} |
161 | 25.1k | } <deser_yaml::de::DeserializerConfig>::from_str::<deser_value::value::Value> Line | Count | Source | 159 | 25.1k | pub fn from_str<'de, T: Deserialize<'de>>(&self, s: &'de str) -> Result<T, Error> { | 160 | 25.1k | deserialize_value(|driver| self.drive_str(s, driver)) | 161 | 25.1k | } |
Unexecuted instantiation: <deser_yaml::de::DeserializerConfig>::from_str::<_> |
162 | | |
163 | | /// The part of [`from_str`](Self::from_str) that does not depend on the |
164 | | /// type of the value, it exists once. |
165 | 25.1k | fn drive_str<'de>( |
166 | 25.1k | &self, |
167 | 25.1k | s: &'de str, |
168 | 25.1k | driver: &mut DeserializeDriver<'_, 'de>, |
169 | 25.1k | ) -> Result<(), Error> { |
170 | 25.1k | drive_single(Deserializer::from_str_with_config(s, self.clone()), driver) |
171 | 25.1k | } |
172 | | |
173 | | /// Deserializes a value from YAML in a byte slice. |
174 | | /// |
175 | | /// See [`from_slice`]. |
176 | 0 | pub fn from_slice<'de, T: Deserialize<'de>>(&self, bytes: &'de [u8]) -> Result<T, Error> { |
177 | 0 | deserialize_value(|driver| self.drive_slice(bytes, driver)) |
178 | 0 | } |
179 | | |
180 | | /// The part of [`from_slice`](Self::from_slice) that does not depend on |
181 | | /// the type of the value, it exists once. |
182 | 0 | fn drive_slice<'de>( |
183 | 0 | &self, |
184 | 0 | bytes: &'de [u8], |
185 | 0 | driver: &mut DeserializeDriver<'_, 'de>, |
186 | 0 | ) -> Result<(), Error> { |
187 | 0 | drive_single( |
188 | 0 | Deserializer::from_slice_with_config(bytes, self.clone()), |
189 | 0 | driver, |
190 | | ) |
191 | 0 | } |
192 | | } |
193 | | |
194 | | /// Builds a [`DeserializerConfig`]. |
195 | | /// |
196 | | /// The methods have the names of the setters of [`DeserializerConfig`] (without `set_`). |
197 | | #[derive(Debug, Clone)] |
198 | | #[must_use] |
199 | | pub struct DeserializerConfigBuilder { |
200 | | value: DeserializerConfig, |
201 | | } |
202 | | |
203 | | impl DeserializerConfigBuilder { |
204 | | /// Creates a builder that starts with the default. |
205 | 0 | pub const fn new() -> DeserializerConfigBuilder { |
206 | 0 | DeserializerConfigBuilder { |
207 | 0 | value: DeserializerConfig::new(), |
208 | 0 | } |
209 | 0 | } |
210 | | |
211 | | /// Sets the YAML version for documents that do not declare one. |
212 | | /// |
213 | | /// See [`DeserializerConfig::set_version`]. |
214 | 0 | pub const fn version(mut self, version: Version) -> DeserializerConfigBuilder { |
215 | 0 | self.value.set_version(version); |
216 | 0 | self |
217 | 0 | } |
218 | | |
219 | | /// Limits the number of events that aliases can expand to per document. |
220 | | /// |
221 | | /// See [`DeserializerConfig::set_alias_limit`]. |
222 | 0 | pub const fn alias_limit(mut self, limit: usize) -> DeserializerConfigBuilder { |
223 | 0 | self.value.set_alias_limit(limit); |
224 | 0 | self |
225 | 0 | } |
226 | | |
227 | | /// Enables or disables merge keys. |
228 | | /// |
229 | | /// See [`DeserializerConfig::set_merge_keys`]. |
230 | 0 | pub const fn merge_keys(mut self, yes: bool) -> DeserializerConfigBuilder { |
231 | 0 | self.value.set_merge_keys(yes); |
232 | 0 | self |
233 | 0 | } |
234 | | |
235 | | /// Sets the context the values are deserialized in. |
236 | | /// |
237 | | /// See [`DeserializerConfig::set_context`]. |
238 | 0 | pub fn context(mut self, context: deser_core::Context) -> DeserializerConfigBuilder { |
239 | 0 | self.value.set_context(context); |
240 | 0 | self |
241 | 0 | } |
242 | | |
243 | | /// Returns the built [`DeserializerConfig`]. |
244 | 0 | pub const fn build(self) -> DeserializerConfig { |
245 | | // the value cannot be moved out of the builder in a const fn as the |
246 | | // builder needs dropping (the context has a destructor) |
247 | | // SAFETY: the value is read once and the builder is forgotten |
248 | 0 | let value = unsafe { core::ptr::read(&self.value) }; |
249 | 0 | core::mem::forget(self); |
250 | 0 | value |
251 | 0 | } |
252 | | } |
253 | | |
254 | | impl Default for DeserializerConfigBuilder { |
255 | 0 | fn default() -> DeserializerConfigBuilder { |
256 | 0 | DeserializerConfigBuilder::new() |
257 | 0 | } |
258 | | } |
259 | | |
260 | | /// Deserializes YAML. |
261 | | /// |
262 | | /// A YAML stream can contain multiple documents. Every call to |
263 | | /// [`deserialize`](Self::deserialize) reads the next document: |
264 | | /// |
265 | | /// ``` |
266 | | /// use deser_yaml::Deserializer; |
267 | | /// |
268 | | /// let mut de = Deserializer::from_str("--- 1\n--- two\n"); |
269 | | /// assert_eq!(de.deserialize::<u32>().unwrap(), 1); |
270 | | /// assert_eq!(de.deserialize::<String>().unwrap(), "two"); |
271 | | /// assert!(de.is_end()); |
272 | | /// ``` |
273 | | /// |
274 | | /// To deserialize a single document, use [`from_str`] and |
275 | | /// [`from_slice`] (or the methods of the same name on |
276 | | /// [`DeserializerConfig`]). |
277 | | /// |
278 | | /// # Aliases |
279 | | /// |
280 | | /// Aliases (`*name`) are expanded: the events of the anchored node are |
281 | | /// replayed. To protect against inputs that expand exponentially (the |
282 | | /// "billion laughs" attack) the number of events produced by aliases is |
283 | | /// limited, see [`DeserializerConfig::set_alias_limit`]. |
284 | | pub struct Deserializer<'a> { |
285 | | input: &'a str, |
286 | | parser: Parser<'a>, |
287 | | peeked: Option<YamlEvent<'a>>, |
288 | | started: bool, |
289 | | /// An error that is reported by the next call. |
290 | | pending_error: Option<Error>, |
291 | | /// The parser failed, no further documents can be read. |
292 | | failed: bool, |
293 | | config: DeserializerConfig, |
294 | | /// Merge keys are enabled and the input contains `<<`. Otherwise |
295 | | /// there cannot be merge keys. |
296 | | track_merges: bool, |
297 | | /// The input as source for location tracking, shared by all documents. |
298 | | source: Option<Arc<str>>, |
299 | | doc: Document<'a>, |
300 | | } |
301 | | |
302 | | /// A node event as it is recorded for anchors. |
303 | | #[derive(Clone)] |
304 | | enum Node<'a> { |
305 | | Scalar { |
306 | | tag: Option<Cow<'a, str>>, |
307 | | style: ScalarStyle, |
308 | | value: Cow<'a, str>, |
309 | | start: Mark, |
310 | | end: usize, |
311 | | }, |
312 | | Start { |
313 | | tag: Option<Cow<'a, str>>, |
314 | | is_map: bool, |
315 | | /// `true` for flow collections (`[a]` and `{a: b}`). |
316 | | flow: bool, |
317 | | start: Mark, |
318 | | end: usize, |
319 | | }, |
320 | | End { |
321 | | is_map: bool, |
322 | | start: Mark, |
323 | | end: usize, |
324 | | }, |
325 | | /// An alias, resolved to the range of the anchored node in the |
326 | | /// recorded nodes. |
327 | | Alias { range: (usize, usize) }, |
328 | | } |
329 | | |
330 | | /// The per document state. |
331 | | #[derive(Default)] |
332 | | struct Document<'a> { |
333 | | version: Version, |
334 | | /// The recorded nodes. Nodes are only recorded while an anchored |
335 | | /// collection is open. Nested anchors share the recording. |
336 | | nodes: Vec<Node<'a>>, |
337 | | /// The anchors and the range of their nodes in `nodes`. |
338 | | anchors: HashMap<Cow<'a, str>, (usize, usize)>, |
339 | | /// The collections that are currently recorded. |
340 | | open: Vec<OpenNode<'a>>, |
341 | | /// The range of the last collection that was captured (recorded |
342 | | /// without anchor, for merge keys). |
343 | | captured: Option<(usize, usize)>, |
344 | | /// The depth of the collections from the parser (without aliases). |
345 | | depth: usize, |
346 | | } |
347 | | |
348 | | /// A collection that is being recorded. |
349 | | struct OpenNode<'a> { |
350 | | anchor: Option<Cow<'a, str>>, |
351 | | /// The index of the start node in the recording. |
352 | | start: usize, |
353 | | /// The depth of the collection. |
354 | | depth: usize, |
355 | | /// The range should be stored in `captured` when the collection ends. |
356 | | capture: bool, |
357 | | } |
358 | | |
359 | | impl<'a> Document<'a> { |
360 | 135k | fn reset(&mut self, version: Version) { |
361 | 135k | self.version = version; |
362 | 135k | self.nodes.clear(); |
363 | 135k | self.anchors.clear(); |
364 | 135k | self.open.clear(); |
365 | 135k | self.captured = None; |
366 | 135k | self.depth = 0; |
367 | 135k | } |
368 | | |
369 | | /// Turns a parser event into a node and records anchors. |
370 | | /// |
371 | | /// If `capture` is set, a collection is recorded even without anchor |
372 | | /// and its range is stored in `captured` once it ends. |
373 | 14.1M | fn record(&mut self, event: YamlEvent<'a>, capture: bool) -> Result<Node<'a>, Error> { |
374 | 14.1M | let start = event.start; |
375 | 14.1M | let end = event.end.offset; |
376 | 14.1M | let is_map = matches!(event.kind, EventKind::MappingStart { .. }); |
377 | 14.1M | let (node, anchor) = match event.kind { |
378 | | EventKind::Scalar { |
379 | 7.06M | props, |
380 | 7.06M | style, |
381 | 7.06M | value, |
382 | 7.06M | } => ( |
383 | 7.06M | Node::Scalar { |
384 | 7.06M | tag: props.tag, |
385 | 7.06M | style, |
386 | 7.06M | value, |
387 | 7.06M | start, |
388 | 7.06M | end, |
389 | 7.06M | }, |
390 | 7.06M | props.anchor, |
391 | 7.06M | ), |
392 | 2.87M | EventKind::SequenceStart { props, flow } | EventKind::MappingStart { props, flow } => { |
393 | 4.60M | self.depth += 1; |
394 | 4.60M | ( |
395 | 4.60M | Node::Start { |
396 | 4.60M | tag: props.tag, |
397 | 4.60M | is_map, |
398 | 4.60M | flow, |
399 | 4.60M | start, |
400 | 4.60M | end, |
401 | 4.60M | }, |
402 | 4.60M | props.anchor, |
403 | 4.60M | ) |
404 | | } |
405 | | EventKind::SequenceEnd | EventKind::MappingEnd => { |
406 | 2.44M | let is_map = event.kind == EventKind::MappingEnd; |
407 | 2.44M | self.depth -= 1; |
408 | 2.44M | let node = Node::End { is_map, start, end }; |
409 | 2.44M | if !self.open.is_empty() { |
410 | 410k | self.nodes.push(node.clone()); |
411 | 410k | let depth = self.depth + 1; |
412 | 410k | if let Some(open) = self.open.pop_if(|x| x.depth == depth) { |
413 | 62.9k | let range = (open.start, self.nodes.len()); |
414 | 62.9k | if let Some(name) = open.anchor { |
415 | 41.3k | self.anchors.insert(name, range); |
416 | 41.3k | } |
417 | 62.9k | if open.capture { |
418 | 22.0k | self.captured = Some(range); |
419 | 40.8k | } |
420 | 347k | } |
421 | 2.03M | } |
422 | 2.44M | return Ok(node); |
423 | | } |
424 | 14.5k | EventKind::Alias { anchor } => { |
425 | 2.42M | if self.open.iter().any(|x| x.anchor.as_ref() == Some(&anchor)) { |
426 | 19 | return Err(error_at(start, "recursive alias")); |
427 | 14.5k | } |
428 | 14.5k | let range = match self.anchors.get(&anchor) { |
429 | 14.0k | Some(&range) => range, |
430 | 476 | None => return Err(error_at(start, &format!("unknown anchor `{}`", anchor))), |
431 | | }; |
432 | 14.0k | let node = Node::Alias { range }; |
433 | 14.0k | if !self.open.is_empty() { |
434 | 13.0k | self.nodes.push(node.clone()); |
435 | 13.0k | } |
436 | 14.0k | return Ok(node); |
437 | | } |
438 | 0 | _ => unreachable!("unexpected event in document"), |
439 | | }; |
440 | | |
441 | 11.6M | let is_start = matches!(node, Node::Start { .. }); |
442 | 11.6M | if anchor.is_some() || (capture && is_start) || !self.open.is_empty() { |
443 | 3.23M | let index = self.nodes.len(); |
444 | 3.23M | self.nodes.push(node.clone()); |
445 | 3.23M | if is_start && (anchor.is_some() || capture) { |
446 | 143k | self.open.push(OpenNode { |
447 | 143k | anchor, |
448 | 143k | start: index, |
449 | 143k | depth: self.depth, |
450 | 143k | capture, |
451 | 143k | }); |
452 | 3.08M | } else if let Some(name) = anchor { |
453 | 188k | self.anchors.insert(name, (index, index + 1)); |
454 | 2.89M | } |
455 | 8.44M | } |
456 | 11.6M | Ok(node) |
457 | 14.1M | } |
458 | | |
459 | | /// Returns the index after the recorded node that starts at `index`. |
460 | 190k | fn node_end(&self, index: usize) -> usize { |
461 | 190k | if !matches!(self.nodes[index], Node::Start { .. }) { |
462 | 137k | return index + 1; |
463 | 52.5k | } |
464 | 52.5k | let mut depth = 0; |
465 | 1.38M | for (offset, node) in self.nodes[index..].iter().enumerate() { |
466 | 1.38M | match node { |
467 | 268k | Node::Start { .. } => depth += 1, |
468 | | Node::End { .. } => { |
469 | 268k | depth -= 1; |
470 | 268k | if depth == 0 { |
471 | 52.5k | return index + offset + 1; |
472 | 215k | } |
473 | | } |
474 | 852k | _ => {} |
475 | | } |
476 | | } |
477 | 0 | unreachable!("unbalanced recording"); |
478 | 190k | } |
479 | | |
480 | | /// Follows a recorded alias to the range of the node it refers to. |
481 | 135k | fn resolve_range(&self, mut range: (usize, usize)) -> (usize, usize) { |
482 | 135k | while let Node::Alias { range: target } = self.nodes[range.0] { |
483 | 0 | range = target; |
484 | 0 | } |
485 | 135k | range |
486 | 135k | } |
487 | | |
488 | | /// Returns the ranges of the items of a recorded collection. |
489 | 45.3k | fn items(&self, range: (usize, usize)) -> impl Iterator<Item = (usize, usize)> + '_ { |
490 | 45.3k | let mut index = range.0 + 1; |
491 | 265k | std::iter::from_fn(move || { |
492 | 265k | if index + 1 >= range.1 { |
493 | 77.0k | return None; |
494 | 188k | } |
495 | 188k | let item = (index, self.node_end(index)); |
496 | 188k | index = item.1; |
497 | 188k | Some(item) |
498 | 265k | }) |
499 | 45.3k | } |
500 | | } |
501 | | |
502 | | /// The identity of a map key for the purpose of merge keys. |
503 | | /// |
504 | | /// Only scalar keys are compared. Two keys are the same if they resolve to |
505 | | /// the same value (so `1` and `0x1` are the same key). |
506 | | #[derive(PartialEq, Eq, Hash)] |
507 | | enum KeyId<'a> { |
508 | | Null, |
509 | | Bool(bool), |
510 | | /// An integer as sign and magnitude. |
511 | | Int(bool, u128), |
512 | | Float(u64), |
513 | | Str(Cow<'a, str>), |
514 | | Bytes(Vec<u8>), |
515 | | Tagged(Cow<'a, str>, Cow<'a, str>), |
516 | | } |
517 | | |
518 | | impl<'a> KeyId<'a> { |
519 | 2.36M | fn of_scalar( |
520 | 2.36M | tag: &Option<Cow<'a, str>>, |
521 | 2.36M | style: ScalarStyle, |
522 | 2.36M | value: &Cow<'a, str>, |
523 | 2.36M | version: Version, |
524 | 2.36M | ) -> Option<KeyId<'a>> { |
525 | 2.22M | let atom = match tag { |
526 | 2.22M | None if style == ScalarStyle::Plain => resolve_plain(value.clone(), version), |
527 | 464k | None => return Some(KeyId::Str(value.clone())), |
528 | 139k | Some(tag) => match classify_tag(tag) { |
529 | 9.98k | ScalarTag::Str => return Some(KeyId::Str(value.clone())), |
530 | 5.93k | ScalarTag::Standard(name) => resolve_standard(name, value.clone(), version).ok()?, |
531 | 123k | ScalarTag::Custom => return Some(KeyId::Tagged(tag.clone(), value.clone())), |
532 | | }, |
533 | | }; |
534 | 1.76M | Some(match atom { |
535 | 255k | Atom::Null => KeyId::Null, |
536 | 7.52k | Atom::Bool(value) => KeyId::Bool(value), |
537 | 35.4k | Atom::U64(value) => KeyId::Int(false, value.into()), |
538 | 24.4k | Atom::I64(value) => KeyId::Int(value < 0, value.unsigned_abs().into()), |
539 | 32.2k | Atom::F64(value) => KeyId::Float(value.to_bits()), |
540 | 1.39M | Atom::Str(value) => KeyId::Str(value.into_cow()), |
541 | 2.30k | Atom::Bytes(value) => KeyId::Bytes(value.into_owned()), |
542 | 17.8k | Atom::Ext(ref ext) => { |
543 | 17.8k | if let Some(&value) = ext.downcast_ref::<u128>() { |
544 | 2.57k | KeyId::Int(false, value) |
545 | 15.3k | } else if let Some(&value) = ext.downcast_ref::<i128>() { |
546 | 15.3k | KeyId::Int(value < 0, value.unsigned_abs()) |
547 | | } else { |
548 | 0 | return None; |
549 | | } |
550 | | } |
551 | 0 | _ => return None, |
552 | | }) |
553 | 2.36M | } |
554 | | } |
555 | | |
556 | 2.39M | fn is_merge_key(tag: &Option<Cow<'_, str>>, style: ScalarStyle, value: &str) -> bool { |
557 | 2.39M | tag.is_none() && style == ScalarStyle::Plain && value == "<<" |
558 | 2.39M | } |
559 | | |
560 | | /// Something that is emitted before the next event from the parser. |
561 | | enum Pending<'a> { |
562 | | /// A range of recorded nodes (for aliases and merged entries). |
563 | | Range(usize, usize), |
564 | | /// A single node. |
565 | | Node(Node<'a>), |
566 | | } |
567 | | |
568 | | /// An open collection while merge keys are tracked. |
569 | | struct Frame<'a> { |
570 | | is_map: bool, |
571 | | /// For maps: the next node is a key. |
572 | | expect_key: bool, |
573 | | /// The keys that were emitted so far. |
574 | | keys: HashSet<KeyId<'a>>, |
575 | | /// The ranges of the merge key values. |
576 | | sources: Vec<(usize, usize)>, |
577 | | } |
578 | | |
579 | | impl<'a> Deserializer<'a> { |
580 | | /// Creates a new deserializer for a string. |
581 | | #[allow(clippy::should_implement_trait)] |
582 | 12.5k | pub fn from_str(input: &'a str) -> Deserializer<'a> { |
583 | 12.5k | Deserializer::from_str_with_config(input, DeserializerConfig::new()) |
584 | 12.5k | } |
585 | | |
586 | | /// Creates a new deserializer for a string with the given configuration. |
587 | 37.6k | pub fn from_str_with_config(input: &'a str, config: DeserializerConfig) -> Deserializer<'a> { |
588 | 37.6k | let track_merges = config.merge_keys && input.contains("<<"); |
589 | 37.6k | Deserializer { |
590 | 37.6k | input, |
591 | 37.6k | parser: Parser::new(input), |
592 | 37.6k | peeked: None, |
593 | 37.6k | started: false, |
594 | 37.6k | pending_error: None, |
595 | 37.6k | failed: false, |
596 | 37.6k | config, |
597 | 37.6k | track_merges, |
598 | 37.6k | source: None, |
599 | 37.6k | doc: Document::default(), |
600 | 37.6k | } |
601 | 37.6k | } |
602 | | |
603 | | /// Creates a new deserializer for a byte slice. |
604 | | /// |
605 | | /// The input must be UTF-8, otherwise deserializing fails. |
606 | 0 | pub fn from_slice(input: &'a [u8]) -> Deserializer<'a> { |
607 | 0 | Deserializer::from_slice_with_config(input, DeserializerConfig::new()) |
608 | 0 | } |
609 | | |
610 | | /// Creates a new deserializer for a byte slice with the given |
611 | | /// configuration. |
612 | | /// |
613 | | /// The input must be UTF-8, otherwise deserializing fails. |
614 | 0 | pub fn from_slice_with_config(input: &'a [u8], config: DeserializerConfig) -> Deserializer<'a> { |
615 | 0 | match str_from_utf8(input) { |
616 | 0 | Ok(input) => Deserializer::from_str_with_config(input, config), |
617 | 0 | Err(err) => { |
618 | 0 | let mut rv = Deserializer::from_str_with_config("", config); |
619 | 0 | rv.pending_error = Some(err); |
620 | 0 | rv.failed = true; |
621 | 0 | rv |
622 | | } |
623 | | } |
624 | 0 | } |
625 | | |
626 | | /// Returns the configuration. |
627 | 0 | pub fn config(&self) -> &DeserializerConfig { |
628 | 0 | &self.config |
629 | 0 | } |
630 | | |
631 | | /// Returns `true` if there are no more documents. |
632 | | /// |
633 | | /// If the input is malformed this returns `false` and the next call to |
634 | | /// [`deserialize`](Self::deserialize) reports the error. |
635 | 160k | pub fn is_end(&mut self) -> bool { |
636 | 160k | if self.failed { |
637 | 0 | return self.pending_error.is_none(); |
638 | 160k | } |
639 | 160k | match self.peek_event() { |
640 | 157k | Ok(event) => event.kind == EventKind::StreamEnd, |
641 | 2.84k | Err(err) => { |
642 | 2.84k | self.pending_error = Some(err); |
643 | 2.84k | false |
644 | | } |
645 | | } |
646 | 160k | } |
647 | | |
648 | | /// Fails if there are more documents. |
649 | 15.3k | pub fn end(&mut self) -> Result<(), Error> { |
650 | 15.3k | if self.is_end() { |
651 | 11.0k | Ok(()) |
652 | 4.26k | } else if let Some(err) = self.pending_error.take() { |
653 | 16 | Err(err) |
654 | | } else { |
655 | 4.24k | Err(Error::new( |
656 | 4.24k | ErrorKind::Syntax, |
657 | 4.24k | "expected a single document, found more", |
658 | 4.24k | )) |
659 | | } |
660 | 15.3k | } |
661 | | |
662 | | /// Deserializes the next document. |
663 | | /// |
664 | | /// Fails with [`ErrorKind::EndOfFile`] if there are no more documents. |
665 | | /// If a document fails to deserialize (for instance because it does not |
666 | | /// match the type), the rest of the document is skipped and the next |
667 | | /// call continues with the next document. Syntax errors end the stream. |
668 | | /// |
669 | | /// To configure the deserialization (for instance to add layers) use |
670 | | /// [`deserialize_with`](Self::deserialize_with). |
671 | 113k | pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> { |
672 | 113k | de::Deserializer::deserialize(self) |
673 | 113k | } <deser_yaml::de::Deserializer>::deserialize::<deser_value::value::Value> Line | Count | Source | 671 | 113k | pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> { | 672 | 113k | de::Deserializer::deserialize(self) | 673 | 113k | } |
Unexecuted instantiation: <deser_yaml::de::Deserializer>::deserialize::<_> |
674 | | |
675 | | /// Deserializes the next value with a configured driver. |
676 | | /// |
677 | | /// The callback is invoked with the driver before the value is |
678 | | /// deserialized, for instance to add [`Layer`](deser_core::de::Layer)s. |
679 | 0 | pub fn deserialize_with<T, F>(&mut self, setup: F) -> Result<T, Error> |
680 | 0 | where |
681 | 0 | T: Deserialize<'a>, |
682 | 0 | F: FnOnce(&mut DeserializeDriver<'_, 'a>), |
683 | | { |
684 | 0 | de::Deserializer::deserialize_with(self, setup) |
685 | 0 | } |
686 | | |
687 | | /// Returns an iterator over the remaining documents. |
688 | | /// |
689 | | /// The iterator stops after the first error. |
690 | | /// |
691 | | /// ``` |
692 | | /// let mut de = deser_yaml::Deserializer::from_str("--- 1\n--- 2\n--- 3\n"); |
693 | | /// let docs = de.iter::<u32>().collect::<Result<Vec<_>, _>>().unwrap(); |
694 | | /// assert_eq!(docs, [1, 2, 3]); |
695 | | /// ``` |
696 | 12.5k | pub fn iter<T: Deserialize<'a>>(&mut self) -> Iter<'_, 'a, T> { |
697 | 12.5k | Iter { |
698 | 12.5k | de: self, |
699 | 12.5k | failed: false, |
700 | 12.5k | _marker: PhantomData, |
701 | 12.5k | } |
702 | 12.5k | } <deser_yaml::de::Deserializer>::iter::<deser_value::value::Value> Line | Count | Source | 696 | 12.5k | pub fn iter<T: Deserialize<'a>>(&mut self) -> Iter<'_, 'a, T> { | 697 | 12.5k | Iter { | 698 | 12.5k | de: self, | 699 | 12.5k | failed: false, | 700 | 12.5k | _marker: PhantomData, | 701 | 12.5k | } | 702 | 12.5k | } |
Unexecuted instantiation: <deser_yaml::de::Deserializer>::iter::<_> |
703 | | |
704 | | /// Parses the next document and feeds the events into the given driver. |
705 | | /// |
706 | | /// This is useful to deserialize into a custom |
707 | | /// [`Sink`](deser_core::de::Sink). See also [`deserialize_with`](Self::deserialize_with). |
708 | | /// Errors carry the location in the input (see [`Error::line`]). |
709 | | /// |
710 | | /// The context of the configuration is given to the driver (values that |
711 | | /// the context of the driver has take precedence, see |
712 | | /// [`DeserializeDriver::set_default_context`]). |
713 | 138k | pub fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> { |
714 | 138k | if !self.config.context.is_empty() { |
715 | 0 | driver.set_default_context(self.config.context.clone()); |
716 | 138k | } |
717 | 138k | if let Some(err) = self.pending_error.take() { |
718 | 2.83k | return Err(err); |
719 | 135k | } |
720 | 135k | if self.failed { |
721 | 0 | return Err(Error::new( |
722 | 0 | ErrorKind::InvalidState, |
723 | 0 | "cannot continue after a syntax error", |
724 | 0 | )); |
725 | 135k | } |
726 | | |
727 | 135k | let event = self.next_event()?; |
728 | 135k | let version = match event.kind { |
729 | 135k | EventKind::DocumentStart { version, .. } => match version { |
730 | 0 | Some((1, minor)) if minor < 2 => Version::V1_1, |
731 | 0 | Some(_) => Version::V1_2, |
732 | 135k | None => self.config.version, |
733 | | }, |
734 | | EventKind::StreamEnd => { |
735 | | // stay at the end of the stream |
736 | 0 | self.peeked = Some(event); |
737 | 0 | return Err(Error::new(ErrorKind::EndOfFile, "no more documents")); |
738 | | } |
739 | 0 | _ => unreachable!("expected document start"), |
740 | | }; |
741 | 135k | self.doc.reset(version); |
742 | | |
743 | 135k | if TrackLocations::of(driver.state()) { |
744 | 0 | let source = self.source.get_or_insert_with(|| self.input.into()); |
745 | 0 | Source(source.clone()).set(driver.state_mut()); |
746 | 135k | } |
747 | 135k | let input = self.input; |
748 | 135k | let rv = self.drive_document(driver).map_err(|mut err| { |
749 | 13.1k | err.resolve_position(input.as_bytes()); |
750 | 13.1k | err |
751 | 13.1k | }); |
752 | | |
753 | 135k | if rv.is_err() && !self.failed { |
754 | | // skip the rest of the document so that the next one can be read |
755 | 3.72k | if let Err(err) = self.skip_document() { |
756 | 2.52k | self.pending_error = Some(err); |
757 | 2.52k | } |
758 | 131k | } |
759 | 135k | rv |
760 | 138k | } |
761 | | |
762 | 15.2M | fn ensure_started(&mut self) -> Result<(), Error> { |
763 | 15.2M | if !self.started { |
764 | 37.6k | self.started = true; |
765 | 37.6k | let event = self.parser_event()?; |
766 | 37.6k | debug_assert_eq!(event.kind, EventKind::StreamStart); |
767 | 15.1M | } |
768 | 15.2M | Ok(()) |
769 | 15.2M | } |
770 | | |
771 | 15.1M | fn parser_event(&mut self) -> Result<YamlEvent<'a>, Error> { |
772 | 15.1M | self.parser.next_event().inspect_err(|_| { |
773 | 14.7k | self.failed = true; |
774 | 14.7k | }) |
775 | 15.1M | } |
776 | | |
777 | 15.2M | fn next_event(&mut self) -> Result<YamlEvent<'a>, Error> { |
778 | 15.2M | self.ensure_started()?; |
779 | 15.2M | match self.peeked.take() { |
780 | 135k | Some(event) => Ok(event), |
781 | 15.1M | None => self.parser_event(), |
782 | | } |
783 | 15.2M | } |
784 | | |
785 | 160k | fn peek_event(&mut self) -> Result<&YamlEvent<'a>, Error> { |
786 | 160k | if self.peeked.is_none() { |
787 | 160k | let event = self.next_event()?; |
788 | 157k | self.peeked = Some(event); |
789 | 0 | } |
790 | 157k | Ok(self.peeked.as_ref().unwrap()) |
791 | 160k | } |
792 | | |
793 | 3.72k | fn skip_document(&mut self) -> Result<(), Error> { |
794 | | loop { |
795 | 679k | if let EventKind::DocumentEnd { .. } = self.next_event()?.kind { |
796 | 1.20k | return Ok(()); |
797 | 675k | } |
798 | | } |
799 | 3.72k | } |
800 | | |
801 | 135k | fn drive_document(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> { |
802 | | // nodes that are emitted before the next event from the parser |
803 | 135k | let mut pending: Vec<Pending<'a>> = Vec::new(); |
804 | | // the number of nodes produced by aliases and merges |
805 | 135k | let mut replayed = 0; |
806 | | // merge keys need to know the keys of all open maps. This is only |
807 | | // done if the input can contain merge keys. |
808 | 135k | let track_merges = self.track_merges; |
809 | 135k | let mut frames: Vec<Frame<'a>> = Vec::new(); |
810 | 135k | let mut merge_value_follows = false; |
811 | | |
812 | | loop { |
813 | 13.6M | let (node, index) = |
814 | 13.8M | match self.next_node(&mut pending, &mut replayed, merge_value_follows)? { |
815 | 13.6M | Some(rv) => rv, |
816 | 122k | None => return Ok(()), |
817 | | }; |
818 | | |
819 | 13.6M | if merge_value_follows { |
820 | 24.3k | merge_value_follows = false; |
821 | 24.3k | let range = self.merge_source(node, index, &mut pending)?; |
822 | 24.0k | let frame = frames.last_mut().unwrap(); |
823 | 24.0k | frame.sources.push(range); |
824 | 24.0k | frame.expect_key = true; |
825 | 24.0k | continue; |
826 | 13.6M | } |
827 | | |
828 | 13.6M | if track_merges |
829 | 7.65M | && let Some(frame) = frames.last_mut() |
830 | 7.63M | && frame.is_map |
831 | | { |
832 | 6.05M | if frame.expect_key |
833 | | && let Node::Scalar { |
834 | 2.31M | ref tag, |
835 | 2.31M | style, |
836 | 2.31M | ref value, |
837 | | .. |
838 | 3.62M | } = node |
839 | | { |
840 | 2.31M | if is_merge_key(tag, style, value) { |
841 | 24.3k | frame.expect_key = false; |
842 | 24.3k | merge_value_follows = true; |
843 | 24.3k | continue; |
844 | 2.29M | } |
845 | 2.29M | if let Some(id) = KeyId::of_scalar(tag, style, value, self.doc.version) { |
846 | 2.29M | frame.keys.insert(id); |
847 | 2.29M | } |
848 | 3.73M | } |
849 | | // aliases are replayed, their nodes are counted |
850 | 6.02M | if !matches!(node, Node::Alias { .. } | Node::End { .. }) { |
851 | 5.55M | frame.expect_key = !frame.expect_key; |
852 | 5.55M | } |
853 | 7.60M | } |
854 | | |
855 | 13.6M | match node { |
856 | | Node::Scalar { |
857 | 6.81M | tag, |
858 | 6.81M | style, |
859 | 6.81M | value, |
860 | 6.81M | start, |
861 | 6.81M | end, |
862 | | } => { |
863 | 6.81M | let version = self.doc.version; |
864 | 6.81M | emit_scalar(driver, tag, style, value, version, start, end)?; |
865 | | } |
866 | | Node::Start { |
867 | 4.48M | tag, |
868 | 4.48M | is_map, |
869 | 4.48M | flow, |
870 | 4.48M | start, |
871 | 4.48M | end, |
872 | | } => { |
873 | | // flow collections are compact so that they stay flow |
874 | | // collections when they are serialized again |
875 | 4.48M | if flow { |
876 | 2.54M | Layout::Compact.set(driver.state_mut()); |
877 | 2.54M | } |
878 | 4.48M | if track_merges { |
879 | 2.51M | frames.push(Frame { |
880 | 2.51M | is_map, |
881 | 2.51M | expect_key: true, |
882 | 2.51M | keys: HashSet::new(), |
883 | 2.51M | sources: Vec::new(), |
884 | 2.51M | }); |
885 | 2.51M | } |
886 | 4.48M | let event = if is_map { |
887 | 2.78M | Event::map_start() |
888 | | } else { |
889 | 1.69M | Event::seq_start() |
890 | | }; |
891 | 4.48M | driver.state_mut().set_input_range(start.offset, end); |
892 | 4.48M | match tag { |
893 | 80.6k | Some(tag) => match is_collection_tag(&tag, is_map) { |
894 | 21.2k | Ok(true) => driver.emit(event)?, |
895 | 59.3k | Ok(false) => emit_tagged(driver, &tag, event)?, |
896 | 28 | Err(msg) => return Err(error_at(start, msg)), |
897 | | }, |
898 | 4.40M | None => driver.emit(event)?, |
899 | | } |
900 | | } |
901 | 2.32M | Node::End { is_map, start, end } => { |
902 | 2.32M | if track_merges { |
903 | 577k | let frame = frames.last_mut().unwrap(); |
904 | 577k | if !frame.sources.is_empty() { |
905 | | // emit the merged entries before the end of the |
906 | | // map, the end is emitted again afterwards |
907 | 3.13k | let sources = std::mem::take(&mut frame.sources); |
908 | 2.93k | let entries = |
909 | 3.13k | self.merged_entries(&sources, &mut frame.keys, &mut replayed)?; |
910 | 2.93k | pending.push(Pending::Node(Node::End { is_map, start, end })); |
911 | 27.3k | for (key, value) in entries.into_iter().rev() { |
912 | 27.3k | pending.push(Pending::Range(value.0, value.1)); |
913 | 27.3k | pending.push(Pending::Range(key.0, key.1)); |
914 | 27.3k | } |
915 | 2.93k | continue; |
916 | 574k | } |
917 | 574k | frames.pop(); |
918 | 1.74M | } |
919 | 2.32M | let event = if is_map { Event::MapEnd } else { Event::SeqEnd }; |
920 | 2.32M | driver.state_mut().set_input_range(start.offset, end); |
921 | 2.32M | driver.emit(event)?; |
922 | | } |
923 | 13.8k | Node::Alias { range } => pending.push(Pending::Range(range.0, range.1)), |
924 | | } |
925 | | } |
926 | 135k | } |
927 | | |
928 | | /// Returns the next node and its index if it was recorded. Returns |
929 | | /// `None` at the end of the document. |
930 | 13.8M | fn next_node( |
931 | 13.8M | &mut self, |
932 | 13.8M | pending: &mut Vec<Pending<'a>>, |
933 | 13.8M | replayed: &mut usize, |
934 | 13.8M | capture: bool, |
935 | 13.8M | ) -> Result<Option<(Node<'a>, Option<usize>)>, Error> { |
936 | | loop { |
937 | 13.8M | let (node, index) = match pending.last_mut() { |
938 | 298k | Some(Pending::Range(start, end)) => { |
939 | 298k | if start == end { |
940 | 60.4k | pending.pop(); |
941 | 60.4k | continue; |
942 | 237k | } |
943 | 237k | let index = *start; |
944 | 237k | *start += 1; |
945 | 237k | (self.doc.nodes[index].clone(), Some(index)) |
946 | | } |
947 | 2.51k | Some(Pending::Node(_)) => match pending.pop() { |
948 | 2.51k | Some(Pending::Node(node)) => return Ok(Some((node, None))), |
949 | 0 | _ => unreachable!(), |
950 | | }, |
951 | | None => { |
952 | 13.5M | let event = self.next_event()?; |
953 | 13.5M | if let EventKind::DocumentEnd { .. } = event.kind { |
954 | 122k | return Ok(None); |
955 | 13.4M | } |
956 | 13.4M | return Ok(Some((self.doc.record(event, capture)?, None))); |
957 | | } |
958 | | }; |
959 | 237k | self.count_replayed(replayed, 1)?; |
960 | 237k | return Ok(Some((node, index))); |
961 | | } |
962 | 13.8M | } |
963 | | |
964 | 269k | fn count_replayed(&self, replayed: &mut usize, count: usize) -> Result<(), Error> { |
965 | 269k | *replayed += count; |
966 | 269k | if *replayed > self.config.alias_limit { |
967 | 0 | Err(Error::new( |
968 | 0 | ErrorKind::LimitExceeded, |
969 | 0 | "aliases expand to too many events", |
970 | 0 | )) |
971 | | } else { |
972 | 269k | Ok(()) |
973 | | } |
974 | 269k | } |
975 | | |
976 | | /// Consumes the value of a merge key and returns the range of its |
977 | | /// recorded nodes. |
978 | 24.3k | fn merge_source( |
979 | 24.3k | &mut self, |
980 | 24.3k | node: Node<'a>, |
981 | 24.3k | index: Option<usize>, |
982 | 24.3k | pending: &mut [Pending<'a>], |
983 | 24.3k | ) -> Result<(usize, usize), Error> { |
984 | 24.3k | match node { |
985 | 0 | Node::Alias { range } => Ok(range), |
986 | 24.2k | Node::Start { .. } => match index { |
987 | | // the value is replayed, skip it |
988 | 1.99k | Some(index) => { |
989 | 1.99k | let end = self.doc.node_end(index); |
990 | 1.99k | if let Some(Pending::Range(start, _)) = pending.last_mut() { |
991 | 1.99k | *start = end; |
992 | 1.99k | } |
993 | 1.99k | Ok((index, end)) |
994 | | } |
995 | | // the value comes from the parser, record it without |
996 | | // emitting it |
997 | | None => { |
998 | 707k | while self.doc.captured.is_none() { |
999 | 685k | let event = self.next_event()?; |
1000 | 685k | self.doc.record(event, false)?; |
1001 | | } |
1002 | 22.0k | Ok(self.doc.captured.take().unwrap()) |
1003 | | } |
1004 | | }, |
1005 | 63 | Node::Scalar { start, .. } | Node::End { start, .. } => Err(error_at( |
1006 | 63 | start, |
1007 | 63 | "the value of a merge key must be a mapping or a sequence of mappings", |
1008 | 63 | )), |
1009 | | } |
1010 | 24.3k | } |
1011 | | |
1012 | | /// Returns the entries that the merge keys of a map add. |
1013 | | /// |
1014 | | /// `keys` holds the keys the map already has, the merged keys are added. |
1015 | | /// Earlier sources take precedence over later ones, the merge keys of the |
1016 | | /// sources are applied recursively. |
1017 | | #[allow(clippy::type_complexity)] |
1018 | 3.13k | fn merged_entries( |
1019 | 3.13k | &self, |
1020 | 3.13k | sources: &[(usize, usize)], |
1021 | 3.13k | keys: &mut HashSet<KeyId<'a>>, |
1022 | 3.13k | replayed: &mut usize, |
1023 | 3.13k | ) -> Result<Vec<((usize, usize), (usize, usize))>, Error> { |
1024 | 3.13k | let mut entries = Vec::new(); |
1025 | | // the mappings to merge in reverse order |
1026 | 3.13k | let mut stack = Vec::new(); |
1027 | 3.13k | self.push_merge_sources(sources, &mut stack); |
1028 | | |
1029 | 34.8k | while let Some(range) = stack.pop() { |
1030 | 31.9k | match self.doc.nodes[range.0] { |
1031 | 31.7k | Node::Start { is_map: true, .. } => {} |
1032 | 168 | Node::Start { start, .. } | Node::Scalar { start, .. } => { |
1033 | 203 | return Err(error_at( |
1034 | 203 | start, |
1035 | 203 | "merge keys can only merge mappings or sequences of mappings", |
1036 | 203 | )); |
1037 | | } |
1038 | 0 | _ => unreachable!(), |
1039 | | } |
1040 | 31.7k | self.count_replayed(replayed, range.1 - range.0)?; |
1041 | | |
1042 | 31.7k | let mut nested = Vec::new(); |
1043 | 31.7k | let mut items = self.doc.items(range); |
1044 | 110k | while let (Some(key), Some(value)) = (items.next(), items.next()) { |
1045 | | if let Node::Scalar { |
1046 | 77.1k | tag: ref key_tag, |
1047 | 77.1k | style, |
1048 | 77.1k | value: ref key_value, |
1049 | | .. |
1050 | 78.6k | } = self.doc.nodes[self.doc.resolve_range(key).0] |
1051 | | { |
1052 | 77.1k | if is_merge_key(key_tag, style, key_value) { |
1053 | 2.63k | nested.push(value); |
1054 | 2.63k | continue; |
1055 | 74.5k | } |
1056 | 74.5k | let version = self.doc.version; |
1057 | 74.5k | if let Some(id) = KeyId::of_scalar(key_tag, style, key_value, version) |
1058 | 72.7k | && !keys.insert(id) |
1059 | | { |
1060 | | // the map (or an earlier source) has the key |
1061 | 47.9k | continue; |
1062 | 26.6k | } |
1063 | 1.51k | } |
1064 | 28.1k | entries.push((key, value)); |
1065 | | } |
1066 | 31.7k | self.push_merge_sources(&nested, &mut stack); |
1067 | | } |
1068 | 2.93k | Ok(entries) |
1069 | 3.13k | } |
1070 | | |
1071 | | /// Adds the mappings of merge key values to the stack (in reverse order, |
1072 | | /// so that the first mapping is processed first). |
1073 | 34.8k | fn push_merge_sources(&self, sources: &[(usize, usize)], stack: &mut Vec<(usize, usize)>) { |
1074 | 34.8k | for &source in sources.iter().rev() { |
1075 | 26.0k | let source = self.doc.resolve_range(source); |
1076 | 26.0k | match self.doc.nodes[source.0] { |
1077 | | Node::Start { is_map: false, .. } => { |
1078 | 13.6k | let items: Vec<_> = self |
1079 | 13.6k | .doc |
1080 | 13.6k | .items(source) |
1081 | 31.0k | .map(|item| self.doc.resolve_range(item)) |
1082 | 13.6k | .collect(); |
1083 | 13.6k | stack.extend(items.into_iter().rev()); |
1084 | | } |
1085 | 12.4k | _ => stack.push(source), |
1086 | | } |
1087 | | } |
1088 | 34.8k | } |
1089 | | } |
1090 | | |
1091 | | #[inline] |
1092 | | /// |
1093 | | /// Scalars are emitted borrowed as they are slices of the input unless they |
1094 | | /// had to be unescaped or folded. |
1095 | 6.81M | fn emit_scalar<'a>( |
1096 | 6.81M | driver: &mut DeserializeDriver<'_, 'a>, |
1097 | 6.81M | tag: Option<Cow<'_, str>>, |
1098 | 6.81M | style: ScalarStyle, |
1099 | 6.81M | value: Cow<'a, str>, |
1100 | 6.81M | version: Version, |
1101 | 6.81M | start: Mark, |
1102 | 6.81M | end: usize, |
1103 | 6.81M | ) -> Result<(), Error> { |
1104 | 6.81M | driver.state_mut().set_input_range(start.offset, end); |
1105 | 6.60M | let tag = match tag { |
1106 | 6.60M | None if style == ScalarStyle::Plain => { |
1107 | 5.92M | return driver.emit_borrowed(resolve_plain_implicit(value, version)); |
1108 | | } |
1109 | 682k | None => return driver.emit_borrowed(Atom::Str(value.into())), |
1110 | 204k | Some(tag) => tag, |
1111 | | }; |
1112 | 204k | match classify_tag(&tag) { |
1113 | 28.3k | ScalarTag::Str => driver.emit_borrowed(Atom::Str(value.into())), |
1114 | 6.33k | ScalarTag::Standard(name) => match resolve_standard(name, value, version) { |
1115 | 5.47k | Ok(atom) => driver.emit_borrowed(atom), |
1116 | 862 | Err(msg) => Err(error_at(start, msg)), |
1117 | | }, |
1118 | 169k | ScalarTag::Custom => emit_tagged(driver, &tag, Atom::Str(value.into())), |
1119 | | } |
1120 | 6.81M | } |
1121 | | |
1122 | | /// Emits an event with a tag attached to it. |
1123 | | #[cold] |
1124 | 228k | fn emit_tagged<'a, E: Into<Event<'a>>>( |
1125 | 228k | driver: &mut DeserializeDriver<'_, 'a>, |
1126 | 228k | tag: &str, |
1127 | 228k | event: E, |
1128 | 228k | ) -> Result<(), Error> { |
1129 | 228k | driver.state_mut().event_mut::<NodeTag>().0 = Some(tag.to_string()); |
1130 | 228k | driver.emit_borrowed(event) |
1131 | 228k | } deser_yaml::de::emit_tagged::<deser_core::event::Atom> Line | Count | Source | 1124 | 169k | fn emit_tagged<'a, E: Into<Event<'a>>>( | 1125 | 169k | driver: &mut DeserializeDriver<'_, 'a>, | 1126 | 169k | tag: &str, | 1127 | 169k | event: E, | 1128 | 169k | ) -> Result<(), Error> { | 1129 | 169k | driver.state_mut().event_mut::<NodeTag>().0 = Some(tag.to_string()); | 1130 | 169k | driver.emit_borrowed(event) | 1131 | 169k | } |
deser_yaml::de::emit_tagged::<deser_core::event::Event> Line | Count | Source | 1124 | 59.3k | fn emit_tagged<'a, E: Into<Event<'a>>>( | 1125 | 59.3k | driver: &mut DeserializeDriver<'_, 'a>, | 1126 | 59.3k | tag: &str, | 1127 | 59.3k | event: E, | 1128 | 59.3k | ) -> Result<(), Error> { | 1129 | 59.3k | driver.state_mut().event_mut::<NodeTag>().0 = Some(tag.to_string()); | 1130 | 59.3k | driver.emit_borrowed(event) | 1131 | 59.3k | } |
|
1132 | | |
1133 | 0 | fn str_from_utf8(bytes: &[u8]) -> Result<&str, Error> { |
1134 | | #[cfg(feature = "speedups")] |
1135 | | { |
1136 | 0 | if simdutf8::basic::from_utf8(bytes).is_ok() { |
1137 | | // SAFETY: validated above |
1138 | 0 | return Ok(unsafe { std::str::from_utf8_unchecked(bytes) }); |
1139 | 0 | } |
1140 | | } |
1141 | 0 | std::str::from_utf8(bytes) |
1142 | 0 | .map_err(|err| Error::with_offset(ErrorKind::Syntax, "invalid UTF-8", err.valid_up_to())) |
1143 | 0 | } |
1144 | | |
1145 | | /// An iterator over the documents of a YAML stream. |
1146 | | /// |
1147 | | /// See [`Deserializer::iter`]. |
1148 | | pub struct Iter<'b, 'a, T> { |
1149 | | de: &'b mut Deserializer<'a>, |
1150 | | failed: bool, |
1151 | | _marker: PhantomData<fn() -> T>, |
1152 | | } |
1153 | | |
1154 | | impl<'b, 'a, T: Deserialize<'a>> Iterator for Iter<'b, 'a, T> { |
1155 | | type Item = Result<T, Error>; |
1156 | | |
1157 | 119k | fn next(&mut self) -> Option<Self::Item> { |
1158 | 119k | if self.failed || self.de.is_end() { |
1159 | 6.22k | return None; |
1160 | 113k | } |
1161 | 113k | let rv = self.de.deserialize(); |
1162 | 113k | self.failed = rv.is_err(); |
1163 | 113k | Some(rv) |
1164 | 119k | } <deser_yaml::de::Iter<deser_value::value::Value> as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 1157 | 119k | fn next(&mut self) -> Option<Self::Item> { | 1158 | 119k | if self.failed || self.de.is_end() { | 1159 | 6.22k | return None; | 1160 | 113k | } | 1161 | 113k | let rv = self.de.deserialize(); | 1162 | 113k | self.failed = rv.is_err(); | 1163 | 113k | Some(rv) | 1164 | 119k | } |
Unexecuted instantiation: <deser_yaml::de::Iter<_> as core::iter::traits::iterator::Iterator>::next |
1165 | | } |
1166 | | |
1167 | | impl<'a> de::Deserializer<'a> for Deserializer<'a> { |
1168 | 138k | fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> { |
1169 | 138k | Deserializer::drive(self, driver) |
1170 | 138k | } |
1171 | | } |
1172 | | |
1173 | | /// Deserializes a value from YAML. |
1174 | | /// |
1175 | | /// The input must contain at most one document. An empty stream (no |
1176 | | /// document at all, for instance an empty file) is deserialized as null. |
1177 | | /// This uses the default [`DeserializerConfig`]. |
1178 | 25.1k | pub fn from_str<'de, T: Deserialize<'de>>(s: &'de str) -> Result<T, Error> { |
1179 | 25.1k | DeserializerConfig::new().from_str(s) |
1180 | 25.1k | } deser_yaml::de::from_str::<deser_value::value::Value> Line | Count | Source | 1178 | 25.1k | pub fn from_str<'de, T: Deserialize<'de>>(s: &'de str) -> Result<T, Error> { | 1179 | 25.1k | DeserializerConfig::new().from_str(s) | 1180 | 25.1k | } |
Unexecuted instantiation: deser_yaml::de::from_str::<_> |
1181 | | |
1182 | | /// Deserializes a value from YAML in a byte slice. |
1183 | | /// |
1184 | | /// The input must be UTF-8. Otherwise this works like [`from_str`]. This |
1185 | | /// uses the default [`DeserializerConfig`]. |
1186 | 0 | pub fn from_slice<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T, Error> { |
1187 | 0 | DeserializerConfig::new().from_slice(bytes) |
1188 | 0 | } |
1189 | | |
1190 | | /// Deserializes the single document of a stream into the sink of a value |
1191 | | /// and checks that no other document follows. |
1192 | 25.1k | fn drive_single<'de>( |
1193 | 25.1k | mut deserializer: Deserializer<'de>, |
1194 | 25.1k | driver: &mut DeserializeDriver<'_, 'de>, |
1195 | 25.1k | ) -> Result<(), Error> { |
1196 | 25.1k | if deserializer.is_end() { |
1197 | 150 | return de::Deserializer::drive(&mut EmptyDocument, driver); |
1198 | 24.9k | } |
1199 | 24.9k | de::Deserializer::drive(&mut deserializer, driver)?; |
1200 | 15.3k | deserializer.end() |
1201 | 25.1k | } |
1202 | | |
1203 | | /// The deserializer of an empty document, which is an empty plain scalar. |
1204 | | struct EmptyDocument; |
1205 | | |
1206 | | impl<'de> de::Deserializer<'de> for EmptyDocument { |
1207 | 150 | fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'de>) -> Result<(), Error> { |
1208 | 150 | driver.emit(Atom::Implicit(Implicit::new("", ImplicitValue::Null))) |
1209 | 150 | } |
1210 | | } |