1use std::{borrow::Cow, cell::Cell, io::Read, rc::Rc, str};
2
3use serde::Deserializer as _;
4use serde::de::{
5 self, DeserializeOwned, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, VariantAccess,
6 Visitor,
7};
8use yaml_rt_core::{
9 NodeId, NonFiniteFloat, ResolvedScalar, SemanticKind, Span, YamlDoc, YamlScalarStyle,
10 resolve_scalar,
11};
12
13use crate::{Error, Result};
14
15const MAX_DEPTH: u8 = 128;
16
17struct Input<'de> {
18 doc: Option<YamlDoc>,
19 borrowed: Option<&'de str>,
20 error: Option<Error>,
21 semantic_len: usize,
22}
23
24impl<'de> Input<'de> {
25 fn parsed(text: String, borrowed: Option<&'de str>) -> Self {
26 match YamlDoc::parse_owned(text) {
27 Ok(doc) => {
28 let semantic_len = doc.events().count().max(1);
29 Self {
30 doc: Some(doc),
31 borrowed,
32 error: None,
33 semantic_len,
34 }
35 }
36 Err(error) => Self {
37 doc: None,
38 borrowed,
39 error: Some(error.into()),
40 semantic_len: 1,
41 },
42 }
43 }
44
45 fn failed(error: Error) -> Self {
46 Self {
47 doc: None,
48 borrowed: None,
49 error: Some(error),
50 semantic_len: 1,
51 }
52 }
53}
54
55pub struct Deserializer<'de> {
57 input: Rc<Input<'de>>,
58 selected: Option<usize>,
59 next_index: usize,
60 yielded_error: bool,
61}
62
63impl<'de> Deserializer<'de> {
64 #[must_use]
66 #[expect(
67 clippy::should_implement_trait,
68 reason = "FromStr cannot retain the borrowed input lifetime or this constructor's deferred errors"
69 )]
70 pub fn from_str(input: &'de str) -> Self {
71 Self::new(Input::parsed(input.to_owned(), Some(input)))
72 }
73
74 #[must_use]
76 pub fn from_slice(input: &'de [u8]) -> Self {
77 match str::from_utf8(input) {
78 Ok(input) => Self::from_str(input),
79 Err(error) => Self::new(Input::failed(Error::message(error.to_string()))),
80 }
81 }
82
83 fn new(input: Input<'de>) -> Self {
84 Self {
85 input: Rc::new(input),
86 selected: None,
87 next_index: 0,
88 yielded_error: false,
89 }
90 }
91
92 fn node_deserializer(&self) -> Result<NodeDeserializer<'_, 'de>> {
93 if let Some(error) = &self.input.error {
94 return Err(error.clone());
95 }
96 let doc = self
97 .input
98 .doc
99 .as_ref()
100 .expect("parsed input has a document");
101 let index = if let Some(index) = self.selected {
102 index
103 } else {
104 match doc.document_count() {
105 0 => return Err(Error::message("EOF while parsing a value")),
106 1 => 0,
107 _ => {
108 return Err(Error::message(
109 "deserializing from YAML containing more than one document is not supported",
110 ));
111 }
112 }
113 };
114 let node = doc.document_root(index).map_err(Error::from)?;
115 Ok(NodeDeserializer {
116 input: &self.input,
117 node,
118 path: ".".to_owned(),
119 depth: MAX_DEPTH,
120 alias_jumps: Rc::new(Cell::new(0)),
121 ignore_tag: false,
122 })
123 }
124}
125
126impl Deserializer<'static> {
127 #[must_use]
129 pub fn from_reader<R>(mut reader: R) -> Self
130 where
131 R: Read,
132 {
133 let mut input = String::new();
134 match reader.read_to_string(&mut input) {
135 Ok(_) => Self::new(Input::parsed(input, None)),
136 Err(error) => Self::new(Input::failed(Error::io(error))),
137 }
138 }
139}
140
141impl Iterator for Deserializer<'_> {
142 type Item = Self;
143
144 fn next(&mut self) -> Option<Self::Item> {
145 if self.input.error.is_some() {
146 if self.yielded_error {
147 return None;
148 }
149 self.yielded_error = true;
150 return Some(Self {
151 input: Rc::clone(&self.input),
152 selected: Some(0),
153 next_index: 0,
154 yielded_error: true,
155 });
156 }
157 let count = self.input.doc.as_ref()?.document_count();
158 if self.next_index >= count {
159 return None;
160 }
161 let selected = self.next_index;
162 self.next_index += 1;
163 Some(Self {
164 input: Rc::clone(&self.input),
165 selected: Some(selected),
166 next_index: 0,
167 yielded_error: false,
168 })
169 }
170}
171
172pub fn from_str<'de, T>(input: &'de str) -> Result<T>
179where
180 T: serde::Deserialize<'de>,
181{
182 T::deserialize(Deserializer::from_str(input))
183}
184
185pub fn from_slice<'de, T>(input: &'de [u8]) -> Result<T>
192where
193 T: serde::Deserialize<'de>,
194{
195 T::deserialize(Deserializer::from_slice(input))
196}
197
198pub fn from_reader<R, T>(reader: R) -> Result<T>
205where
206 R: Read,
207 T: DeserializeOwned,
208{
209 T::deserialize(Deserializer::from_reader(reader))
210}
211
212macro_rules! delegate_deserializer {
213 ($($method:ident $(($($arg:ident : $ty:ty),*))?;)+) => {
214 $(
215 fn $method<V>(self, $($($arg: $ty,)*)? visitor: V) -> Result<V::Value>
216 where
217 V: Visitor<'de>,
218 {
219 self.node_deserializer()?.$method($($($arg,)*)? visitor)
220 }
221 )+
222 };
223}
224
225impl<'de> de::Deserializer<'de> for Deserializer<'de> {
226 type Error = Error;
227
228 delegate_deserializer! {
229 deserialize_any;
230 deserialize_bool;
231 deserialize_i8;
232 deserialize_i16;
233 deserialize_i32;
234 deserialize_i64;
235 deserialize_i128;
236 deserialize_u8;
237 deserialize_u16;
238 deserialize_u32;
239 deserialize_u64;
240 deserialize_u128;
241 deserialize_f32;
242 deserialize_f64;
243 deserialize_char;
244 deserialize_str;
245 deserialize_string;
246 deserialize_bytes;
247 deserialize_byte_buf;
248 deserialize_option;
249 deserialize_unit;
250 deserialize_unit_struct(name: &'static str);
251 deserialize_newtype_struct(name: &'static str);
252 deserialize_seq;
253 deserialize_tuple(len: usize);
254 deserialize_tuple_struct(name: &'static str, len: usize);
255 deserialize_map;
256 deserialize_struct(name: &'static str, fields: &'static [&'static str]);
257 deserialize_enum(name: &'static str, variants: &'static [&'static str]);
258 deserialize_identifier;
259 deserialize_ignored_any;
260 }
261
262 fn is_human_readable(&self) -> bool {
263 true
264 }
265}
266
267#[derive(Clone)]
268struct NodeDeserializer<'input, 'de> {
269 input: &'input Input<'de>,
270 node: Option<NodeId>,
271 path: String,
272 depth: u8,
273 alias_jumps: Rc<Cell<usize>>,
274 ignore_tag: bool,
275}
276
277impl<'input, 'de> NodeDeserializer<'input, 'de> {
278 fn doc(&self) -> &'input YamlDoc {
279 self.input.doc.as_ref().expect("node input is parsed")
280 }
281
282 fn span(&self) -> Span {
283 self.node
284 .and_then(|node| self.doc().node(node).map(yaml_rt_core::Node::span))
285 .unwrap_or_else(|| Span::empty(0))
286 }
287
288 fn annotate<T>(&self, result: Result<T>) -> Result<T> {
289 result.map_err(|error| error.at(self.doc(), self.span()).with_path(&self.path))
290 }
291
292 fn descend(&self, node: Option<NodeId>, path: String) -> Result<Self> {
293 let depth = self
294 .depth
295 .checked_sub(1)
296 .ok_or_else(|| Error::message("recursion limit exceeded"));
297 let depth = self.annotate(depth)?;
298 Ok(Self {
299 input: self.input,
300 node,
301 path,
302 depth,
303 alias_jumps: Rc::clone(&self.alias_jumps),
304 ignore_tag: false,
305 })
306 }
307
308 fn resolved(mut self) -> Result<Self> {
309 let mut seen = Vec::new();
310 while let Some(node) = self.node {
311 if !matches!(self.doc().semantic_kind(node), Some(SemanticKind::Alias)) {
312 break;
313 }
314 if seen.contains(&node) {
315 return self.annotate(Err(Error::message("recursive alias")));
316 }
317 seen.push(node);
318 let jumps = self.alias_jumps.get().saturating_add(1);
319 self.alias_jumps.set(jumps);
320 if jumps > self.input.semantic_len.saturating_mul(100) {
321 return self.annotate(Err(Error::message("alias repetition limit exceeded")));
322 }
323 let target = self.doc().resolve_alias(node).ok_or_else(|| {
324 Error::message(format!(
325 "unknown anchor `{}`",
326 self.doc().alias_name(node).unwrap_or_default()
327 ))
328 });
329 self.node = Some(self.annotate(target)?);
330 }
331 Ok(self)
332 }
333
334 fn child(&self, node: Option<NodeId>, path: String) -> Result<Self> {
335 self.descend(node, path)
336 }
337
338 fn scalar(&self) -> Result<(NodeId, Cow<'input, str>)> {
339 let node = self
340 .node
341 .ok_or_else(|| Error::message("expected a scalar, found null"));
342 let node = self.annotate(node)?;
343 if !matches!(
344 self.doc().semantic_kind(node),
345 Some(SemanticKind::Scalar { .. })
346 ) {
347 return self.annotate(Err(Error::message("expected a scalar value")));
348 }
349 let value = self
350 .doc()
351 .scalar_value(node)
352 .map(|value| (node, value))
353 .map_err(Error::from);
354 self.annotate(value)
355 }
356
357 fn custom_tag(&self) -> Option<String> {
358 if self.ignore_tag {
359 return None;
360 }
361 let raw = self.node.and_then(|node| self.doc().raw_tag(node))?;
362 if raw.starts_with("!!") || raw.starts_with("!<") || !raw.starts_with('!') {
363 return None;
364 }
365 let tag = raw.strip_prefix('!')?;
366 (!tag.is_empty()).then(|| tag.to_owned())
367 }
368
369 fn scalar_kind(&self) -> Result<ScalarKind> {
370 let Some(node) = self.node else {
371 return Ok(ScalarKind::Null);
372 };
373 let Some(SemanticKind::Scalar { style }) = self.doc().semantic_kind(node) else {
374 return Err(Error::message("expected a scalar value"));
375 };
376 let value = self.doc().scalar_value(node).map_err(Error::from)?;
377 let tag = self
378 .doc()
379 .resolved_tag(node)
380 .map_err(Error::from)?
381 .map(Cow::into_owned);
382 let resolved = resolve_scalar(&value, style, tag.as_deref())
383 .map_err(|error| Error::message(error.to_string()))?;
384 self.annotate(scalar_kind_from_resolved(resolved))
385 }
386
387 fn borrowed_scalar(&self, node: NodeId) -> Option<&'de str> {
388 let source = self.input.borrowed?;
389 let span = self.doc().borrowable_scalar_span(node).ok()??;
390 source.get(span.start as usize..span.end as usize)
391 }
392
393 fn is_empty_plain(&self) -> bool {
394 let Some(node) = self.node else {
395 return true;
396 };
397 matches!(
398 self.doc().semantic_kind(node),
399 Some(SemanticKind::Scalar {
400 style: YamlScalarStyle::Plain
401 })
402 ) && self
403 .doc()
404 .scalar_value(node)
405 .is_ok_and(|value| value.is_empty())
406 }
407}
408
409#[derive(Clone, Copy)]
410enum ScalarKind {
411 Null,
412 Bool(bool),
413 Signed(i128),
414 Unsigned(u128),
415 Float(f64),
416 String,
417}
418
419fn scalar_kind_from_resolved(value: ResolvedScalar) -> Result<ScalarKind> {
420 match value {
421 ResolvedScalar::Null => Ok(ScalarKind::Null),
422 ResolvedScalar::Bool(value) => Ok(ScalarKind::Bool(value)),
423 ResolvedScalar::Number(number) if number.has_integer_syntax() => {
424 if let Some(value) = number.as_i128()
425 && value < 0
426 {
427 Ok(ScalarKind::Signed(value))
428 } else if let Some(value) = number.as_u128() {
429 Ok(ScalarKind::Unsigned(value))
430 } else if let Some(value) = number.as_i128() {
431 Ok(ScalarKind::Signed(value))
432 } else {
433 Err(Error::message("integer is outside the supported range"))
434 }
435 }
436 ResolvedScalar::Number(number) => number
437 .as_f64()
438 .map(ScalarKind::Float)
439 .ok_or_else(|| Error::message("float is outside the supported range")),
440 ResolvedScalar::NonFinite(NonFiniteFloat::PositiveInfinity) => {
441 Ok(ScalarKind::Float(f64::INFINITY))
442 }
443 ResolvedScalar::NonFinite(NonFiniteFloat::NegativeInfinity) => {
444 Ok(ScalarKind::Float(f64::NEG_INFINITY))
445 }
446 ResolvedScalar::NonFinite(NonFiniteFloat::NaN) => Ok(ScalarKind::Float(f64::NAN)),
447 ResolvedScalar::String => Ok(ScalarKind::String),
448 }
449}
450
451impl<'de> de::Deserializer<'de> for NodeDeserializer<'_, 'de> {
452 type Error = Error;
453
454 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
455 where
456 V: Visitor<'de>,
457 {
458 let this = self.resolved()?;
459 if let Some(variant) = this.custom_tag() {
460 return visitor.visit_enum(YamlEnumAccess { de: this, variant });
461 }
462 let result = match this.node.and_then(|node| this.doc().semantic_kind(node)) {
463 None => visitor.visit_unit(),
464 Some(SemanticKind::Scalar { .. }) => match this.scalar_kind()? {
465 ScalarKind::Null => visitor.visit_unit(),
466 ScalarKind::Bool(value) => visitor.visit_bool(value),
467 ScalarKind::Signed(value) => visitor.visit_i128(value),
468 ScalarKind::Unsigned(value) => visitor.visit_u128(value),
469 ScalarKind::Float(value) => visitor.visit_f64(value),
470 ScalarKind::String => this.clone().deserialize_str(visitor),
471 },
472 Some(SemanticKind::Sequence { .. }) => this.clone().deserialize_seq(visitor),
473 Some(SemanticKind::Mapping { .. }) => this.clone().deserialize_map(visitor),
474 Some(SemanticKind::Alias) => unreachable!("aliases were resolved"),
475 Some(SemanticKind::Document) => Err(Error::message("unexpected document node")),
476 };
477 this.annotate(result)
478 }
479
480 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
481 where
482 V: Visitor<'de>,
483 {
484 let this = self.resolved()?;
485 let result = match this.scalar_kind()? {
486 ScalarKind::Bool(value) => visitor.visit_bool(value),
487 _ => Err(Error::message("expected a boolean")),
488 };
489 this.annotate(result)
490 }
491
492 fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
493 where
494 V: Visitor<'de>,
495 {
496 deserialize_signed(self, visitor, |v| i8::try_from(v).ok(), Visitor::visit_i8)
497 }
498 fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
499 where
500 V: Visitor<'de>,
501 {
502 deserialize_signed(self, visitor, |v| i16::try_from(v).ok(), Visitor::visit_i16)
503 }
504 fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
505 where
506 V: Visitor<'de>,
507 {
508 deserialize_signed(self, visitor, |v| i32::try_from(v).ok(), Visitor::visit_i32)
509 }
510 fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
511 where
512 V: Visitor<'de>,
513 {
514 deserialize_signed(self, visitor, |v| i64::try_from(v).ok(), Visitor::visit_i64)
515 }
516 fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value>
517 where
518 V: Visitor<'de>,
519 {
520 deserialize_signed(self, visitor, Some, Visitor::visit_i128)
521 }
522 fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
523 where
524 V: Visitor<'de>,
525 {
526 deserialize_unsigned(self, visitor, |v| u8::try_from(v).ok(), Visitor::visit_u8)
527 }
528 fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
529 where
530 V: Visitor<'de>,
531 {
532 deserialize_unsigned(self, visitor, |v| u16::try_from(v).ok(), Visitor::visit_u16)
533 }
534 fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
535 where
536 V: Visitor<'de>,
537 {
538 deserialize_unsigned(self, visitor, |v| u32::try_from(v).ok(), Visitor::visit_u32)
539 }
540 fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
541 where
542 V: Visitor<'de>,
543 {
544 deserialize_unsigned(self, visitor, |v| u64::try_from(v).ok(), Visitor::visit_u64)
545 }
546 fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value>
547 where
548 V: Visitor<'de>,
549 {
550 deserialize_unsigned(self, visitor, Some, Visitor::visit_u128)
551 }
552
553 fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
554 where
555 V: Visitor<'de>,
556 {
557 deserialize_float(self, visitor, |visitor, value| {
558 let value = checked_f64_to_f32(value)
559 .ok_or_else(|| Error::message("expected an f32 in range"))?;
560 visitor.visit_f32(value)
561 })
562 }
563
564 fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
565 where
566 V: Visitor<'de>,
567 {
568 deserialize_float(self, visitor, Visitor::visit_f64)
569 }
570
571 fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
572 where
573 V: Visitor<'de>,
574 {
575 let this = self.resolved()?;
576 let (_, value) = this.scalar()?;
577 let mut chars = value.chars();
578 let value = chars
579 .next()
580 .filter(|_| chars.next().is_none())
581 .ok_or_else(|| Error::message("expected a single character"));
582 this.annotate(value.and_then(|value| visitor.visit_char(value)))
583 }
584
585 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
586 where
587 V: Visitor<'de>,
588 {
589 let this = self.resolved()?;
590 let (node, value) = this.scalar()?;
591 let result = if let Some(value) = this.borrowed_scalar(node) {
592 visitor.visit_borrowed_str(value)
593 } else {
594 match value {
595 Cow::Borrowed(value) => visitor.visit_str(value),
596 Cow::Owned(value) => visitor.visit_string(value),
597 }
598 };
599 this.annotate(result)
600 }
601
602 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
603 where
604 V: Visitor<'de>,
605 {
606 let this = self.resolved()?;
607 let (_, value) = this.scalar()?;
608 this.annotate(visitor.visit_string(value.into_owned()))
609 }
610
611 fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
612 where
613 V: Visitor<'de>,
614 {
615 Err(Error::message(
616 "serialization and deserialization of bytes in YAML is not implemented",
617 ))
618 }
619
620 fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value>
621 where
622 V: Visitor<'de>,
623 {
624 Err(Error::message(
625 "serialization and deserialization of bytes in YAML is not implemented",
626 ))
627 }
628
629 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
630 where
631 V: Visitor<'de>,
632 {
633 let this = self.resolved()?;
634 if matches!(this.scalar_kind(), Ok(ScalarKind::Null)) {
635 this.annotate(visitor.visit_none())
636 } else {
637 visitor.visit_some(this)
638 }
639 }
640
641 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
642 where
643 V: Visitor<'de>,
644 {
645 let this = self.resolved()?;
646 let result = if matches!(this.scalar_kind(), Ok(ScalarKind::Null)) {
647 visitor.visit_unit()
648 } else {
649 Err(Error::message("expected null"))
650 };
651 this.annotate(result)
652 }
653
654 fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
655 where
656 V: Visitor<'de>,
657 {
658 self.deserialize_unit(visitor)
659 }
660
661 fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
662 where
663 V: Visitor<'de>,
664 {
665 visitor.visit_newtype_struct(self)
666 }
667
668 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
669 where
670 V: Visitor<'de>,
671 {
672 let this = self.resolved()?;
673 if this.is_empty_plain() {
674 return this.annotate(visitor.visit_seq(EmptyAccess));
675 }
676 let node = this
677 .node
678 .ok_or_else(|| Error::message("expected a sequence"))?;
679 if !matches!(
680 this.doc().semantic_kind(node),
681 Some(SemanticKind::Sequence { .. })
682 ) {
683 return this.annotate(Err(Error::message("expected a sequence")));
684 }
685 let items = this.doc().sequence_items(node).collect::<Vec<_>>();
686 let context = this.clone();
687 context.annotate(visitor.visit_seq(YamlSeqAccess {
688 de: this,
689 items,
690 index: 0,
691 }))
692 }
693
694 fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
695 where
696 V: Visitor<'de>,
697 {
698 self.deserialize_seq(visitor)
699 }
700
701 fn deserialize_tuple_struct<V>(
702 self,
703 _name: &'static str,
704 _len: usize,
705 visitor: V,
706 ) -> Result<V::Value>
707 where
708 V: Visitor<'de>,
709 {
710 self.deserialize_seq(visitor)
711 }
712
713 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
714 where
715 V: Visitor<'de>,
716 {
717 let this = self.resolved()?;
718 if this.is_empty_plain() {
719 return this.annotate(visitor.visit_map(EmptyAccess));
720 }
721 let node = this
722 .node
723 .ok_or_else(|| Error::message("expected a mapping"))?;
724 if !matches!(
725 this.doc().semantic_kind(node),
726 Some(SemanticKind::Mapping { .. })
727 ) {
728 return this.annotate(Err(Error::message("expected a mapping")));
729 }
730 let entries = this.doc().mapping_entries(node).collect::<Vec<_>>();
731 let context = this.clone();
732 context.annotate(visitor.visit_map(YamlMapAccess {
733 de: this,
734 entries,
735 index: 0,
736 pending: None,
737 }))
738 }
739
740 fn deserialize_struct<V>(
741 self,
742 _name: &'static str,
743 _fields: &'static [&'static str],
744 visitor: V,
745 ) -> Result<V::Value>
746 where
747 V: Visitor<'de>,
748 {
749 self.deserialize_map(visitor)
750 }
751
752 fn deserialize_enum<V>(
753 self,
754 _name: &'static str,
755 _variants: &'static [&'static str],
756 visitor: V,
757 ) -> Result<V::Value>
758 where
759 V: Visitor<'de>,
760 {
761 let this = self.resolved()?;
762 let variant = if let Some(variant) = this.custom_tag() {
763 variant
764 } else {
765 let (_, value) = this.scalar()?;
766 value.into_owned()
767 };
768 let context = this.clone();
769 context.annotate(visitor.visit_enum(YamlEnumAccess { de: this, variant }))
770 }
771
772 fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
773 where
774 V: Visitor<'de>,
775 {
776 self.deserialize_str(visitor)
777 }
778
779 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
780 where
781 V: Visitor<'de>,
782 {
783 visitor.visit_unit()
784 }
785
786 fn is_human_readable(&self) -> bool {
787 true
788 }
789}
790
791fn signed_value(kind: ScalarKind) -> Option<i128> {
792 match kind {
793 ScalarKind::Signed(value) => Some(value),
794 ScalarKind::Unsigned(value) => i128::try_from(value).ok(),
795 _ => None,
796 }
797}
798
799fn unsigned_value(kind: ScalarKind) -> Option<u128> {
800 match kind {
801 ScalarKind::Unsigned(value) => Some(value),
802 ScalarKind::Signed(value) => u128::try_from(value).ok(),
803 _ => None,
804 }
805}
806
807fn deserialize_signed<'de, V, T>(
808 de: NodeDeserializer<'_, 'de>,
809 visitor: V,
810 convert: impl FnOnce(i128) -> Option<T>,
811 visit: impl FnOnce(V, T) -> Result<V::Value>,
812) -> Result<V::Value>
813where
814 V: Visitor<'de>,
815{
816 let de = de.resolved()?;
817 let value = signed_value(de.scalar_kind()?)
818 .and_then(convert)
819 .ok_or_else(|| Error::message("expected an integer in range"));
820 de.annotate(value.and_then(|value| visit(visitor, value)))
821}
822
823fn deserialize_unsigned<'de, V, T>(
824 de: NodeDeserializer<'_, 'de>,
825 visitor: V,
826 convert: impl FnOnce(u128) -> Option<T>,
827 visit: impl FnOnce(V, T) -> Result<V::Value>,
828) -> Result<V::Value>
829where
830 V: Visitor<'de>,
831{
832 let de = de.resolved()?;
833 let value = unsigned_value(de.scalar_kind()?)
834 .and_then(convert)
835 .ok_or_else(|| Error::message("expected an unsigned integer in range"));
836 de.annotate(value.and_then(|value| visit(visitor, value)))
837}
838
839fn deserialize_float<'de, V>(
840 de: NodeDeserializer<'_, 'de>,
841 visitor: V,
842 visit: impl FnOnce(V, f64) -> Result<V::Value>,
843) -> Result<V::Value>
844where
845 V: Visitor<'de>,
846{
847 let de = de.resolved()?;
848 let value = match de.scalar_kind()? {
849 ScalarKind::Float(value) => Some(value),
850 ScalarKind::Signed(value) => Some(i128_to_f64(value)),
851 ScalarKind::Unsigned(value) => Some(u128_to_f64(value)),
852 _ => None,
853 }
854 .ok_or_else(|| Error::message("expected a number"));
855 de.annotate(value.and_then(|value| visit(visitor, value)))
856}
857
858fn checked_f64_to_f32(value: f64) -> Option<f32> {
859 #[expect(
862 clippy::cast_possible_truncation,
863 reason = "f32 deserialization applies Rust narrowing and then rejects finite overflow"
864 )]
865 let converted = value as f32;
866 (!value.is_finite() || converted.is_finite()).then_some(converted)
867}
868
869fn i128_to_f64(value: i128) -> f64 {
870 #[expect(
873 clippy::cast_precision_loss,
874 reason = "Serde floating-point requests intentionally use Rust integer rounding semantics"
875 )]
876 let converted = value as f64;
877 converted
878}
879
880fn u128_to_f64(value: u128) -> f64 {
881 #[expect(
883 clippy::cast_precision_loss,
884 reason = "Serde floating-point requests intentionally use Rust integer rounding semantics"
885 )]
886 let converted = value as f64;
887 converted
888}
889
890struct EmptyAccess;
891
892impl<'de> SeqAccess<'de> for EmptyAccess {
893 type Error = Error;
894 fn next_element_seed<T>(&mut self, _seed: T) -> Result<Option<T::Value>>
895 where
896 T: DeserializeSeed<'de>,
897 {
898 Ok(None)
899 }
900}
901
902impl<'de> MapAccess<'de> for EmptyAccess {
903 type Error = Error;
904 fn next_key_seed<K>(&mut self, _seed: K) -> Result<Option<K::Value>>
905 where
906 K: DeserializeSeed<'de>,
907 {
908 Ok(None)
909 }
910 fn next_value_seed<V>(&mut self, _seed: V) -> Result<V::Value>
911 where
912 V: DeserializeSeed<'de>,
913 {
914 Err(Error::message("value requested without a key"))
915 }
916}
917
918struct YamlSeqAccess<'input, 'de> {
919 de: NodeDeserializer<'input, 'de>,
920 items: Vec<NodeId>,
921 index: usize,
922}
923
924impl<'de> SeqAccess<'de> for YamlSeqAccess<'_, 'de> {
925 type Error = Error;
926 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
927 where
928 T: DeserializeSeed<'de>,
929 {
930 let Some(node) = self.items.get(self.index).copied() else {
931 return Ok(None);
932 };
933 let index = self.index;
934 self.index += 1;
935 let child = self
936 .de
937 .child(Some(node), format!("{}[{index}]", self.de.path))?;
938 seed.deserialize(child).map(Some)
939 }
940 fn size_hint(&self) -> Option<usize> {
941 Some(self.items.len().saturating_sub(self.index))
942 }
943}
944
945struct YamlMapAccess<'input, 'de> {
946 de: NodeDeserializer<'input, 'de>,
947 entries: Vec<(NodeId, NodeId)>,
948 index: usize,
949 pending: Option<(NodeId, String)>,
950}
951
952impl<'de> MapAccess<'de> for YamlMapAccess<'_, 'de> {
953 type Error = Error;
954 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
955 where
956 K: DeserializeSeed<'de>,
957 {
958 let Some((key, value)) = self.entries.get(self.index).copied() else {
959 return Ok(None);
960 };
961 self.index += 1;
962 let key_name = self
963 .de
964 .doc()
965 .scalar_value(key)
966 .ok()
967 .map_or_else(|| "?".to_owned(), Cow::into_owned);
968 let path = if key_name
969 .chars()
970 .all(|c| c.is_alphanumeric() || c == '_' || c == '-')
971 {
972 format!("{}.{}", self.de.path.trim_end_matches('.'), key_name)
973 } else {
974 format!("{}[{:?}]", self.de.path, key_name)
975 };
976 self.pending = Some((value, path));
977 let child = self
978 .de
979 .child(Some(key), format!("{}.<key>", self.de.path))?;
980 seed.deserialize(child).map(Some)
981 }
982 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
983 where
984 V: DeserializeSeed<'de>,
985 {
986 let (node, path) = self
987 .pending
988 .take()
989 .ok_or_else(|| Error::message("value requested without a key"))?;
990 seed.deserialize(self.de.child(Some(node), path)?)
991 }
992 fn size_hint(&self) -> Option<usize> {
993 Some(self.entries.len().saturating_sub(self.index))
994 }
995}
996
997struct YamlEnumAccess<'input, 'de> {
998 de: NodeDeserializer<'input, 'de>,
999 variant: String,
1000}
1001
1002impl<'input, 'de> EnumAccess<'de> for YamlEnumAccess<'input, 'de> {
1003 type Error = Error;
1004 type Variant = YamlVariantAccess<'input, 'de>;
1005 fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
1006 where
1007 V: DeserializeSeed<'de>,
1008 {
1009 let variant = seed.deserialize(serde::de::value::StrDeserializer::<Error>::new(
1010 self.variant.as_str(),
1011 ))?;
1012 Ok((variant, YamlVariantAccess { de: self.de }))
1013 }
1014}
1015
1016struct YamlVariantAccess<'input, 'de> {
1017 de: NodeDeserializer<'input, 'de>,
1018}
1019
1020impl<'de> VariantAccess<'de> for YamlVariantAccess<'_, 'de> {
1021 type Error = Error;
1022 fn unit_variant(self) -> Result<()> {
1023 Ok(())
1024 }
1025 fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
1026 where
1027 T: DeserializeSeed<'de>,
1028 {
1029 let mut de = self.de;
1030 de.ignore_tag = true;
1031 seed.deserialize(de)
1032 }
1033 fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value>
1034 where
1035 V: Visitor<'de>,
1036 {
1037 let mut de = self.de;
1038 de.ignore_tag = true;
1039 de.deserialize_tuple(len, visitor)
1040 }
1041 fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
1042 where
1043 V: Visitor<'de>,
1044 {
1045 let mut de = self.de;
1046 de.ignore_tag = true;
1047 de.deserialize_struct("", fields, visitor)
1048 }
1049}