#[cfg(feature = "deserialize")]
pub(crate) mod base64;
#[cfg(feature = "deserialize")]
pub mod budget;
#[cfg(feature = "deserialize")]
pub(crate) mod buffered_input;
#[cfg(feature = "deserialize")]
pub(crate) mod error;
#[cfg(feature = "figment")]
pub mod figment;
#[cfg(feature = "deserialize")]
pub(crate) mod include;
#[cfg(all(feature = "deserialize", feature = "include"))]
pub(crate) mod include_stack;
#[cfg(feature = "deserialize")]
pub(crate) mod indentation;
#[cfg(feature = "deserialize")]
pub(crate) mod input_source;
#[cfg(any(feature = "garde", feature = "validator"))]
pub(crate) mod lib_validate;
#[cfg(feature = "deserialize")]
pub(crate) mod live_events;
#[cfg(feature = "deserialize")]
pub mod localizer;
#[cfg(feature = "miette")]
pub mod miette;
#[cfg(feature = "deserialize")]
pub(crate) mod message_formatters;
#[cfg(feature = "deserialize")]
pub mod options;
#[cfg(any(feature = "garde", feature = "validator"))]
pub mod path_map;
#[cfg(feature = "properties")]
pub mod properties;
#[cfg(feature = "deserialize")]
pub(crate) mod properties_redaction;
#[cfg(feature = "robotics")]
pub mod robotics;
#[cfg(feature = "deserialize")]
pub(crate) mod ring_reader;
#[cfg(all(feature = "deserialize", feature = "include_fs"))]
pub(crate) mod safe_resolver;
#[cfg(feature = "deserialize")]
pub(crate) mod snippet;
#[cfg(feature = "deserialize")]
pub(crate) mod tags;
pub use crate::budget::Budget;
pub use self::error::Error;
pub use crate::location::Location;
use crate::anchor_store::{self, AnchorKind};
use self::base64::decode_base64_yaml;
use self::error::{MissingFieldLocationGuard, TransformReason};
use crate::parse_scalars::{
leading_zero_decimal, maybe_not_string, parse_int_signed, parse_int_unsigned,
parse_yaml11_bool, parse_yaml12_float, scalar_is_nullish, scalar_is_nullish_for_option,
};
#[cfg(feature = "properties")]
use crate::properties::interpolate_compose_style;
use crate::properties_redaction::{
ScalarRedactionCtx, ScalarRedactionGuard, with_interp_redaction_scope,
};
use ahash::{HashSetExt, RandomState};
use saphyr_parser::ScalarStyle;
use serde::de::{self, Deserializer as _, IntoDeserializer, Visitor};
use std::borrow::Cow;
#[cfg(feature = "properties")]
use std::collections::HashMap;
use std::collections::{HashSet, VecDeque};
use std::mem;
#[cfg(feature = "properties")]
use std::rc::Rc;
pub mod with_deserializer;
pub use with_deserializer::{
with_deserializer_from_reader, with_deserializer_from_reader_with_options,
with_deserializer_from_slice, with_deserializer_from_slice_with_options,
with_deserializer_from_str, with_deserializer_from_str_with_options,
};
type FastHashSet<T> = HashSet<T, RandomState>;
use crate::location::Locations;
#[inline]
fn attach_alias_locations_if_missing(
err: Error,
reference_location: Location,
defined_location: Location,
) -> Error {
if reference_location != Location::UNKNOWN
&& defined_location != Location::UNKNOWN
&& reference_location != defined_location
{
Error::AliasError {
msg: err.to_string(),
locations: Locations {
reference_location,
defined_location,
},
}
} else if err.location().is_some() {
err
} else {
let loc = if reference_location != Location::UNKNOWN {
reference_location
} else {
defined_location
};
err.with_location(loc)
}
}
mod spanned_deser;
pub use crate::options::{AliasLimits, DuplicateKeyPolicy, Options};
use crate::tags::SfTag;
#[cfg(any(feature = "garde", feature = "validator"))]
use self::path_map::PathRecorder;
#[derive(Copy, Clone)]
pub(crate) struct Cfg {
pub(crate) dup_policy: DuplicateKeyPolicy,
pub(crate) legacy_octal_numbers: bool,
pub(crate) strict_booleans: bool,
pub(crate) angle_conversions: bool,
pub(crate) ignore_binary_tag_for_string: bool,
pub(crate) no_schema: bool,
}
impl Cfg {
#[inline]
#[allow(deprecated)]
pub(crate) fn from_options(options: &Options) -> Self {
Self {
dup_policy: options.duplicate_keys,
legacy_octal_numbers: options.legacy_octal_numbers,
strict_booleans: options.strict_booleans,
angle_conversions: options.angle_conversions,
ignore_binary_tag_for_string: options.ignore_binary_tag_for_string,
no_schema: options.no_schema,
}
}
}
#[derive(Clone, Debug)]
pub(crate) enum Ev<'a> {
Scalar {
value: Cow<'a, str>,
tag: SfTag,
raw_tag: Option<Cow<'a, str>>,
style: ScalarStyle,
anchor: usize,
location: Location,
},
SeqStart {
anchor: usize,
tag: SfTag,
raw_tag: Option<Cow<'a, str>>,
location: Location,
},
SeqEnd { location: Location },
MapStart { anchor: usize, location: Location },
MapEnd { location: Location },
Taken { location: Location },
}
impl Default for Ev<'_> {
fn default() -> Self {
Ev::Taken {
location: Location::UNKNOWN,
}
}
}
impl Ev<'_> {
pub(crate) fn location(&self) -> Location {
match self {
Ev::Scalar { location, .. }
| Ev::SeqStart { location, .. }
| Ev::SeqEnd { location }
| Ev::MapStart { location, .. }
| Ev::MapEnd { location }
| Ev::Taken { location } => *location,
}
}
}
fn simple_tagged_enum_name(raw_tag: &Option<Cow<'_, str>>, tag: &SfTag) -> Option<String> {
if !matches!(tag, SfTag::Other) {
return None;
}
let raw = raw_tag.as_deref()?;
let mut candidate =
if let Some(inner) = raw.strip_prefix("!<").and_then(|s| s.strip_suffix('>')) {
inner
} else {
raw
};
if let Some(stripped) = candidate.strip_prefix("tag:yaml.org,2002:") {
candidate = stripped;
}
candidate = candidate.trim_start_matches('!');
if candidate.is_empty() || candidate.contains([':', '!']) {
return None;
}
Some(candidate.to_owned())
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
enum KeyFingerprint {
Scalar { value: String, tag: SfTag },
Sequence(Vec<KeyFingerprint>),
Mapping(Vec<(KeyFingerprint, KeyFingerprint)>),
#[default]
Default,
}
fn canonical_scalar_key_tag(tag: SfTag) -> SfTag {
if tag.can_parse_into_string() || tag == SfTag::NonSpecific {
SfTag::String
} else {
tag
}
}
impl KeyFingerprint {
fn stringy_scalar_value(&self) -> Option<&str> {
match self {
KeyFingerprint::Scalar { value, tag } => {
if tag.can_parse_into_string() && tag != &SfTag::Binary {
Some(value.as_str())
} else {
None
}
}
_ => None,
}
}
}
enum KeyNode<'a> {
Fingerprinted {
fingerprint: KeyFingerprint,
events: Vec<Ev<'a>>,
location: Location,
},
Scalar {
events: Vec<Ev<'a>>,
location: Location,
},
}
impl<'a> KeyNode<'a> {
fn fingerprint(&self) -> Cow<'_, KeyFingerprint> {
match self {
KeyNode::Fingerprinted { fingerprint, .. } => Cow::Borrowed(fingerprint),
KeyNode::Scalar { events, .. } => {
if let Some(Ev::Scalar { tag, value, .. }) = events.first() {
Cow::Owned(KeyFingerprint::Scalar {
tag: canonical_scalar_key_tag(*tag),
value: value.to_string(),
})
} else {
unreachable!()
}
}
}
}
fn events(&self) -> &[Ev<'a>] {
match self {
KeyNode::Fingerprinted { events, .. } => events,
KeyNode::Scalar { events, .. } => events,
}
}
fn take_events(&mut self) -> Vec<Ev<'a>> {
match self {
KeyNode::Fingerprinted { events, .. } => mem::take(events),
KeyNode::Scalar { events, .. } => mem::take(events),
}
}
fn take_fingerprint(&mut self) -> KeyFingerprint {
match self {
KeyNode::Fingerprinted { fingerprint, .. } => mem::take(fingerprint),
KeyNode::Scalar { .. } => self.fingerprint().into_owned(),
}
}
fn location(&self) -> Location {
let location = match self {
KeyNode::Fingerprinted { location, .. } => location,
KeyNode::Scalar { location, .. } => location,
};
*location
}
}
struct PendingEntry<'a> {
key: KeyNode<'a>,
value: KeyNode<'a>,
reference_location: Location,
}
fn one_entry_map_spans<'a>(events: &[Ev<'a>]) -> Option<(usize, usize, usize, usize)> {
if events.len() < 4 {
return None;
}
match events.first()? {
Ev::MapStart { .. } => {}
_ => return None,
}
match events.last()? {
Ev::MapEnd { .. } => {}
_ => return None,
}
let mut i = 1; let key_start = i;
i += skip_one_node_len(events, i)?;
let key_end = i;
let val_start = i;
i += skip_one_node_len(events, i)?;
let val_end = i;
if i != events.len() - 1 {
return None;
}
Some((key_start, key_end, val_start, val_end))
}
fn skip_one_node_len<'a>(events: &[Ev<'a>], mut i: usize) -> Option<usize> {
match events.get(i)? {
Ev::Scalar { .. } => Some(1),
Ev::SeqStart { .. } => {
let start = i;
let mut depth = 1i32;
i += 1;
while i < events.len() {
match events.get(i)? {
Ev::SeqStart { .. } => depth += 1,
Ev::SeqEnd { .. } => {
depth -= 1;
if depth == 0 {
return Some(i - start + 1);
}
}
Ev::MapStart { .. } => depth += 1,
Ev::MapEnd { .. } => {
depth -= 1;
}
Ev::Scalar { .. } => {}
Ev::Taken { .. } => return None,
}
i += 1;
}
None
}
Ev::MapStart { .. } => {
let start = i;
let mut depth = 1i32;
i += 1;
while i < events.len() {
match events.get(i)? {
Ev::MapStart { .. } => depth += 1,
Ev::MapEnd { .. } => {
depth -= 1;
if depth == 0 {
return Some(i - start + 1);
}
}
Ev::SeqStart { .. } => depth += 1,
Ev::SeqEnd { .. } => {
depth -= 1;
}
Ev::Scalar { .. } => {}
Ev::Taken { .. } => return None,
}
i += 1;
}
None
}
Ev::SeqEnd { .. } | Ev::MapEnd { .. } => None,
Ev::Taken { .. } => None,
}
}
fn capture_node<'a>(ev: &mut dyn Events<'a>) -> Result<KeyNode<'a>, Error> {
let Some(event) = ev.next()? else {
return Err(Error::eof().with_location(ev.last_location()));
};
match event {
Ev::Scalar {
value,
tag,
raw_tag,
style,
anchor,
location,
} => {
let scalar_ev = Ev::Scalar {
value,
tag,
raw_tag,
style,
anchor,
location,
};
Ok(KeyNode::Scalar {
events: vec![scalar_ev],
location,
})
}
Ev::SeqStart {
anchor,
tag,
raw_tag,
location,
} => {
let mut events = vec![Ev::SeqStart {
anchor,
tag,
raw_tag,
location,
}];
let mut elements = Vec::new();
loop {
match ev.peek()? {
Some(Ev::SeqEnd { location: end_loc }) => {
let end_loc = *end_loc;
let _ = ev.next()?;
events.push(Ev::SeqEnd { location: end_loc });
break;
}
Some(_) => {
let mut child = capture_node(ev)?; let fp = child.take_fingerprint();
let child_events = child.take_events();
elements.push(fp);
events.reserve(child_events.len());
events.extend(child_events);
}
None => {
return Err(Error::eof().with_location(ev.last_location()));
}
}
}
Ok(KeyNode::Fingerprinted {
fingerprint: KeyFingerprint::Sequence(elements),
events,
location,
})
}
Ev::MapStart { anchor, location } => {
let mut events = vec![Ev::MapStart { anchor, location }];
let mut entries = Vec::new();
loop {
match ev.peek()? {
Some(Ev::MapEnd { location: end_loc }) => {
let end_loc = *end_loc;
let _ = ev.next()?;
events.push(Ev::MapEnd { location: end_loc });
break;
}
Some(_) => {
let mut key = capture_node(ev)?; let key_fp = key.take_fingerprint();
let mut value = capture_node(ev)?; let value_fp = value.take_fingerprint();
entries.push((key_fp, value_fp));
let key_events = key.take_events();
let value_events = value.take_events();
events.reserve(key_events.len() + value_events.len());
events.extend(key_events);
events.extend(value_events);
}
None => {
return Err(Error::eof().with_location(ev.last_location()));
}
}
}
Ok(KeyNode::Fingerprinted {
fingerprint: KeyFingerprint::Mapping(entries),
events,
location,
})
}
Ev::SeqEnd { location } | Ev::MapEnd { location } => {
Err(Error::UnexpectedContainerEndWhileReadingKeyNode { location })
}
Ev::Taken { location } => Err(Error::unexpected("consumed event").with_location(location)),
}
}
#[inline]
fn is_merge_key(node: &KeyNode) -> bool {
let events = node.events();
if events.len() != 1 {
return false;
}
matches!(
events.first(),
Some(Ev::Scalar {
value,
tag,
style: ScalarStyle::Plain,
..
}) if tag == &SfTag::None && value.as_ref() == "<<"
)
}
fn pending_entries_from_events<'a>(
events: Vec<Ev<'a>>,
location: Location,
reference_location: Location,
#[cfg(feature = "properties")] property_map: Option<Rc<HashMap<String, String>>>,
) -> Result<Vec<PendingEntry<'a>>, Error> {
let mut replay = ReplayEvents::with_reference(
events,
reference_location,
#[cfg(feature = "properties")]
property_map.clone(),
);
match replay.peek()? {
Some(Ev::Scalar { value, style, .. }) if scalar_is_nullish(value.as_ref(), style) => {
Ok(Vec::new())
}
Some(Ev::Scalar { location, .. }) => Err(Error::MergeValueNotMapOrSeqOfMaps {
location: *location,
}),
Some(Ev::MapStart { .. }) => collect_entries_from_map(&mut replay, reference_location),
Some(Ev::SeqStart { .. }) => {
let mut batches = Vec::new();
let _ = replay.next()?; loop {
match replay.peek()? {
Some(Ev::SeqEnd { .. }) => {
let _ = replay.next()?;
break;
}
Some(_) => {
let _ = replay.peek()?;
let element_ref_loc = replay.reference_location();
let mut element = capture_node(&mut replay)?;
batches.push(pending_entries_from_events(
element.take_events(),
element.location(),
element_ref_loc,
#[cfg(feature = "properties")]
property_map.clone(),
)?); }
None => {
return Err(Error::eof().with_location(replay.last_location()));
}
}
}
let mut merged = Vec::new();
while let Some(mut nested) = batches.pop() {
merged.append(&mut nested);
}
Ok(merged)
}
Some(other) => Err(Error::MergeValueNotMapOrSeqOfMaps {
location: other.location(),
}),
None => Err(Error::eof().with_location(location)),
}
}
fn pending_entries_from_live_events<'a>(
ev: &mut dyn Events<'a>,
merge_reference_location: Location,
) -> Result<Vec<PendingEntry<'a>>, Error> {
#[cfg(feature = "properties")]
let property_map = ev.property_map().map(Rc::clone);
match ev.peek()? {
Some(Ev::Scalar { value, style, .. }) if scalar_is_nullish(value.as_ref(), style) => {
let _ = ev.next()?;
Ok(Vec::new())
}
Some(Ev::Scalar { location, .. }) => Err(Error::MergeValueNotMapOrSeqOfMaps {
location: *location,
}),
Some(Ev::MapStart { .. }) => {
let mut node = capture_node(ev)?;
pending_entries_from_events(
node.take_events(),
node.location(),
merge_reference_location,
#[cfg(feature = "properties")]
property_map,
)
}
Some(Ev::SeqStart { .. }) => {
let _ = ev.next()?; let mut batches = Vec::new();
loop {
match ev.peek()? {
Some(Ev::SeqEnd { .. }) => {
let _ = ev.next()?;
break;
}
Some(_) => {
let _ = ev.peek()?;
let element_ref_loc = ev.reference_location();
let mut element = capture_node(ev)?;
batches.push(pending_entries_from_events(
element.take_events(),
element.location(),
element_ref_loc,
#[cfg(feature = "properties")]
property_map.clone(),
)?);
}
None => return Err(Error::eof().with_location(ev.last_location())),
}
}
let mut merged = Vec::new();
while let Some(mut nested) = batches.pop() {
merged.append(&mut nested);
}
Ok(merged)
}
Some(other) => Err(Error::MergeValueNotMapOrSeqOfMaps {
location: other.location(),
}),
None => Err(Error::eof().with_location(ev.last_location())),
}
}
fn collect_entries_from_map<'a>(
ev: &mut dyn Events<'a>,
reference_location: Location,
) -> Result<Vec<PendingEntry<'a>>, Error> {
let Some(Ev::MapStart { .. }) = ev.next()? else {
return Err(Error::MergeValueNotMapOrSeqOfMaps {
location: ev.last_location(),
});
};
let mut fields = Vec::new();
let mut merges = Vec::new();
loop {
match ev.peek()? {
Some(Ev::MapEnd { .. }) => {
let _ = ev.next()?;
break;
}
Some(_) => {
let key = capture_node(ev)?;
if is_merge_key(&key) {
let _ = ev.peek()?;
let merge_ref_loc = ev.reference_location();
merges.push(pending_entries_from_live_events(ev, merge_ref_loc)?);
} else {
let value = capture_node(ev)?;
fields.push(PendingEntry {
key,
value,
reference_location,
});
}
}
None => {
return Err(Error::eof().with_location(ev.last_location()));
}
}
}
let mut entries = fields;
while let Some(mut nested) = merges.pop() {
entries.append(&mut nested);
}
Ok(entries)
}
pub(crate) trait Events<'de> {
fn next(&mut self) -> Result<Option<Ev<'de>>, Error>;
fn peek(&mut self) -> Result<Option<&Ev<'de>>, Error>;
fn last_location(&self) -> Location;
fn reference_location(&self) -> Location;
fn input_for_borrowing(&self) -> Option<&'de str> {
None }
#[cfg(feature = "properties")]
fn property_map(&self) -> Option<&Rc<HashMap<String, String>>> {
None
}
}
struct ReplayEvents<'a> {
buf: Vec<Ev<'a>>,
idx: usize,
ref_override: Option<Location>,
#[cfg(feature = "properties")]
property_map: Option<Rc<HashMap<String, String>>>,
}
impl<'a> ReplayEvents<'a> {
fn new(
buf: Vec<Ev<'a>>,
#[cfg(feature = "properties")] property_map: Option<Rc<HashMap<String, String>>>,
) -> Self {
Self {
buf,
idx: 0,
ref_override: None,
#[cfg(feature = "properties")]
property_map,
}
}
fn with_reference(
buf: Vec<Ev<'a>>,
reference: Location,
#[cfg(feature = "properties")] property_map: Option<Rc<HashMap<String, String>>>,
) -> Self {
Self {
buf,
idx: 0,
ref_override: Some(reference),
#[cfg(feature = "properties")]
property_map,
}
}
}
impl<'a> Events<'a> for ReplayEvents<'a> {
fn next(&mut self) -> Result<Option<Ev<'a>>, Error> {
if self.idx >= self.buf.len() {
return Ok(None);
}
let location = self.buf[self.idx].location();
let ev = mem::replace(&mut self.buf[self.idx], Ev::Taken { location });
self.idx += 1;
Ok(Some(ev))
}
fn peek(&mut self) -> Result<Option<&Ev<'a>>, Error> {
Ok(self.buf.get(self.idx))
}
fn last_location(&self) -> Location {
let last = self.idx.saturating_sub(1);
self.buf
.get(last)
.map(|e| e.location())
.unwrap_or(Location::UNKNOWN)
}
fn reference_location(&self) -> Location {
if let Some(loc) = self.ref_override {
return loc;
}
self.buf
.get(self.idx)
.map(|e| e.location())
.unwrap_or_else(|| self.last_location())
}
#[cfg(feature = "properties")]
fn property_map(&self) -> Option<&Rc<HashMap<String, String>>> {
self.property_map.as_ref()
}
}
pub struct YamlDeserializer<'de, 'e> {
ev: &'e mut dyn Events<'de>,
cfg: Cfg,
in_key: bool,
key_empty_map_node: bool,
#[cfg(any(feature = "garde", feature = "validator"))]
garde: Option<&'e mut PathRecorder>,
}
#[derive(Clone)]
struct ScalarView<'de> {
raw: Cow<'de, str>,
effective: Cow<'de, str>,
tag: SfTag,
style: ScalarStyle,
location: Location,
interpolated: bool,
}
type EffectiveScalar<'de> = (Cow<'de, str>, SfTag, ScalarStyle, Location);
impl<'de> ScalarView<'de> {
fn redaction_ctx(&self) -> Option<ScalarRedactionCtx> {
self.interpolated.then(|| ScalarRedactionCtx {
raw: self.raw.as_ref().to_owned(),
effective: self.effective.as_ref().to_owned(),
})
}
}
fn with_scalar_redaction<T>(
ctx: Option<ScalarRedactionCtx>,
f: impl FnOnce() -> Result<T, Error>,
) -> Result<T, Error> {
let _guard = ctx.map(ScalarRedactionGuard::new);
f()
}
fn with_subtree_redaction<T>(
ctx: Option<ScalarRedactionCtx>,
f: impl FnOnce() -> Result<T, Error>,
) -> Result<T, Error> {
with_interp_redaction_scope(|| with_scalar_redaction(ctx, f))
}
#[cfg(feature = "properties")]
pub(crate) fn with_root_redaction<'de, 'e, T>(
mut de: YamlDeserializer<'de, 'e>,
f: impl FnOnce(YamlDeserializer<'de, 'e>) -> Result<T, Error>,
) -> Result<T, Error> {
let redaction_ctx = de.peek_scalar_redaction_ctx()?;
with_subtree_redaction(redaction_ctx, || f(de))
}
#[cfg(not(feature = "properties"))]
pub(crate) fn with_root_redaction<'de, 'e, T>(
de: YamlDeserializer<'de, 'e>,
f: impl FnOnce(YamlDeserializer<'de, 'e>) -> Result<T, Error>,
) -> Result<T, Error> {
f(de)
}
struct EnumScalarId<'de> {
raw: Cow<'de, str>,
effective: Cow<'de, str>,
interpolated: bool,
location: Location,
}
impl<'de> EnumScalarId<'de> {
fn from_view(view: ScalarView<'de>) -> Self {
Self {
raw: view.raw,
effective: view.effective,
interpolated: view.interpolated,
location: view.location,
}
}
fn redaction_ctx(&self) -> Option<ScalarRedactionCtx> {
self.interpolated.then(|| ScalarRedactionCtx {
raw: self.raw.as_ref().to_owned(),
effective: self.effective.as_ref().to_owned(),
})
}
}
impl<'de> IntoDeserializer<'de, Error> for EnumScalarId<'de> {
type Deserializer = Self;
fn into_deserializer(self) -> Self::Deserializer {
self
}
}
impl<'de> de::Deserializer<'de> for EnumScalarId<'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_identifier(visitor)
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let ctx = self.redaction_ctx();
let location = self.location;
let effective = self.effective;
with_scalar_redaction(ctx, move || match effective {
Cow::Borrowed(value) => visitor.visit_borrowed_str(value),
Cow::Owned(value) => visitor.visit_string(value),
})
.map_err(|err| err.with_location(location))
}
serde::forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf
option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum
ignored_any
}
}
impl<'de, 'e> YamlDeserializer<'de, 'e> {
pub(crate) fn new(ev: &'e mut dyn Events<'de>, cfg: Cfg) -> Self {
Self {
ev,
cfg,
in_key: false,
key_empty_map_node: false,
#[cfg(any(feature = "garde", feature = "validator"))]
garde: None,
}
}
fn quoting_required_for_scalar(&self, view: &ScalarView<'de>) -> Error {
Error::quoting_required(view.raw.as_ref(), view.interpolated).with_location(view.location)
}
fn interpolation_possible(&self, tag: SfTag, style: ScalarStyle) -> bool {
if self.in_key || tag == SfTag::Binary || style != ScalarStyle::Plain {
return false;
}
#[cfg(not(feature = "properties"))]
{
false
}
#[cfg(feature = "properties")]
{
self.ev.property_map().is_some()
}
}
fn peek_scalar_redaction_ctx(&mut self) -> Result<Option<ScalarRedactionCtx>, Error> {
let Some((tag, style)) = (match self.ev.peek()? {
Some(Ev::Scalar { tag, style, .. }) => Some((*tag, *style)),
_ => None,
}) else {
return Ok(None);
};
if !self.interpolation_possible(tag, style) {
return Ok(None);
}
Ok(self
.peek_scalar_view()?
.and_then(|view| view.redaction_ctx()))
}
#[cfg(any(feature = "garde", feature = "validator"))]
pub(crate) fn new_with_path_recorder(
ev: &'e mut dyn Events<'de>,
cfg: Cfg,
garde: &'e mut PathRecorder,
) -> Self {
Self {
ev,
cfg,
in_key: false,
key_empty_map_node: false,
garde: Some(garde),
}
}
fn take_scalar_event(&mut self) -> Result<(String, SfTag, Location), Error> {
let view = self.take_scalar_view()?;
Ok((view.effective.into_owned(), view.tag, view.location))
}
fn take_scalar_cow_event(&mut self) -> Result<(Cow<'de, str>, SfTag, Location), Error> {
let view = self.take_scalar_view()?;
Ok((view.effective, view.tag, view.location))
}
fn take_scalar_view(&mut self) -> Result<ScalarView<'de>, Error> {
match self.ev.next()? {
Some(Ev::Scalar {
value,
tag,
style,
location,
..
}) => self.scalar_view_from_parts(value, tag, style, location),
Some(other) => Err(Error::unexpected("string scalar").with_location(other.location())),
None => Err(Error::eof().with_location(self.ev.last_location())),
}
}
fn take_peeked_scalar_view(&mut self, view: ScalarView<'de>) -> Result<ScalarView<'de>, Error> {
match self.ev.next()? {
Some(Ev::Scalar { .. }) => Ok(view),
Some(other) => Err(Error::unexpected("string scalar").with_location(other.location())),
None => Err(Error::eof().with_location(self.ev.last_location())),
}
}
fn take_scalar_cow_with_location(&mut self) -> Result<(Cow<'de, str>, SfTag, Location), Error> {
let (value, tag, location) = self.take_scalar_cow_event()?;
Ok((value, tag, location))
}
fn take_string_scalar(&mut self) -> Result<String, Error> {
let (value, tag, location) = self.take_scalar_event()?;
if tag == SfTag::Binary && !self.cfg.ignore_binary_tag_for_string {
let data = decode_base64_yaml(&value).map_err(|err| err.with_location(location))?;
let text = String::from_utf8(data).map_err(|_| Error::BinaryNotUtf8 { location })?;
return Ok(text);
}
if !tag.can_parse_into_string()
&& tag != SfTag::NonSpecific
&& !(self.cfg.ignore_binary_tag_for_string && tag == SfTag::Binary)
{
return Err(Error::TaggedScalarCannotDeserializeIntoString { location });
}
Ok(value)
}
fn expect_seq_start(&mut self) -> Result<(), Error> {
match self.ev.next()? {
Some(Ev::SeqStart { .. }) => Ok(()),
Some(other) => Err(Error::unexpected("sequence start").with_location(other.location())),
None => Err(Error::eof().with_location(self.ev.last_location())),
}
}
fn expect_map_start(&mut self) -> Result<(), Error> {
match self.ev.next()? {
Some(Ev::MapStart { .. }) => Ok(()),
Some(other) => Err(Error::unexpected("mapping start").with_location(other.location())),
None => Err(Error::eof().with_location(self.ev.last_location())),
}
}
fn peek_effective_scalar(&mut self) -> Result<Option<EffectiveScalar<'de>>, Error> {
let Some(view) = self.peek_scalar_view()? else {
return Ok(None);
};
Ok(Some((view.effective, view.tag, view.style, view.location)))
}
fn peek_scalar_view(&mut self) -> Result<Option<ScalarView<'de>>, Error> {
let (value, tag, style, location) = match self.ev.peek()? {
Some(Ev::Scalar {
value,
tag,
style,
location,
..
}) => (value.clone(), *tag, *style, *location),
_ => return Ok(None),
};
Ok(Some(
self.scalar_view_from_parts(value, tag, style, location)?,
))
}
fn scalar_view_from_parts(
&self,
raw: Cow<'de, str>,
tag: SfTag,
style: ScalarStyle,
location: Location,
) -> Result<ScalarView<'de>, Error> {
let effective = if self.interpolation_possible(tag, style) {
self.effective_scalar_value(raw.clone(), tag, style, location)?
} else {
raw.clone()
};
let interpolated = raw.as_ref() != effective.as_ref();
Ok(ScalarView {
raw,
effective,
tag,
style,
location,
interpolated,
})
}
fn effective_scalar_value(
&self,
value: Cow<'de, str>,
tag: SfTag,
style: ScalarStyle,
location: Location,
) -> Result<Cow<'de, str>, Error> {
if self.in_key || tag == SfTag::Binary || style != ScalarStyle::Plain {
return Ok(value);
}
#[cfg(not(feature = "properties"))]
{
let _ = location;
Ok(value)
}
#[cfg(feature = "properties")]
{
let Some(vars) = self.ev.property_map().map(|m| m.as_ref()) else {
return Ok(value);
};
match interpolate_compose_style(value, vars) {
Ok(value) => Ok(value),
Err(crate::properties::PropertyError::Unresolved(name)) => {
Err(Error::UnresolvedProperty { name, location })
}
Err(crate::properties::PropertyError::InvalidName(name)) => {
Err(Error::InvalidPropertyName { name, location })
}
}
}
}
fn peek_anchor_id(&mut self) -> Result<Option<usize>, Error> {
match self.ev.peek()? {
Some(Ev::Scalar { anchor, .. })
| Some(Ev::SeqStart { anchor, .. })
| Some(Ev::MapStart { anchor, .. }) => {
if *anchor == 0 {
Ok(None)
} else {
Ok(Some(*anchor))
}
}
_ => Ok(None),
}
}
}
impl<'de, 'e> de::Deserializer<'de> for YamlDeserializer<'de, 'e> {
type Error = Error;
fn deserialize_any<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
if let Some((value, tag, style, location)) = self.peek_effective_scalar()? {
if tag == SfTag::Null {
let _ = self.take_scalar_event()?; return visitor.visit_unit();
}
let is_plain = matches!(style, ScalarStyle::Plain);
if scalar_is_nullish(&value, &style) {
let _ = self.ev.next()?; return visitor.visit_unit();
}
if !is_plain
|| !tag.can_parse_into_string()
|| tag == SfTag::Binary
|| tag == SfTag::String
{
if tag == SfTag::Binary && !self.cfg.ignore_binary_tag_for_string {
return visitor.visit_string(self.take_string_scalar()?);
}
if !tag.can_parse_into_string()
&& tag != SfTag::NonSpecific
&& !(self.cfg.ignore_binary_tag_for_string && tag == SfTag::Binary)
{
return Err(Error::TaggedScalarCannotDeserializeIntoString { location });
}
let (cow, _tag2, _location) = self.take_scalar_cow_event()?;
return match cow {
Cow::Borrowed(b) => visitor.visit_borrowed_str(b),
Cow::Owned(s) => visitor.visit_string(s),
};
}
let (s, tag, location) = self.take_scalar_event()?;
if self.cfg.strict_booleans {
let tt = s.trim();
if tt.eq_ignore_ascii_case("true") {
return visitor.visit_bool(true);
} else if tt.eq_ignore_ascii_case("false") {
return visitor.visit_bool(false);
}
} else if let Ok(b) = parse_yaml11_bool(&s) {
return visitor.visit_bool(b);
}
let t = s.trim();
if t.starts_with('-') && !leading_zero_decimal(t) {
if let Ok(v) =
parse_int_signed::<i64>(t, "i64", location, self.cfg.legacy_octal_numbers)
{
return visitor.visit_i64(v);
}
} else {
if let Ok(v) =
parse_int_unsigned::<u64>(t, "u64", location, self.cfg.legacy_octal_numbers)
{
return visitor.visit_u64(v);
}
if let Ok(v) =
parse_int_signed::<i64>(t, "i64", location, self.cfg.legacy_octal_numbers)
{
return visitor.visit_i64(v);
}
}
if let Ok(v) = parse_yaml12_float::<f64>(&s, location, tag, self.cfg.angle_conversions)
{
if v.is_finite() {
return visitor.visit_f64(v);
} else {
let canon = if v.is_nan() {
".nan".to_string()
} else if v.is_sign_negative() {
"-.inf".to_string()
} else {
".inf".to_string()
};
return visitor.visit_string(canon);
}
}
return visitor.visit_string(s);
}
match self.ev.peek()? {
Some(Ev::SeqStart { .. }) => self.deserialize_seq(visitor),
Some(Ev::MapStart { .. }) => self.deserialize_map(visitor),
Some(Ev::SeqEnd { location }) => Err(Error::UnexpectedSequenceEnd {
location: *location,
}),
Some(Ev::MapEnd { location }) => Err(Error::UnexpectedMappingEnd {
location: *location,
}),
None => {
visitor.visit_unit()
}
Some(Ev::Taken { location }) => {
Err(Error::unexpected("consumed event").with_location(*location))
}
Some(Ev::Scalar { .. }) => unreachable!("handled above"),
}
}
fn deserialize_bool<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let s = s.as_ref();
let t = s.trim();
let b: bool = if self.cfg.strict_booleans {
if t.eq_ignore_ascii_case("true") {
true
} else if t.eq_ignore_ascii_case("false") {
false
} else {
return Err(Error::InvalidBooleanStrict { location });
}
} else {
parse_yaml11_bool(s).map_err(|_| Error::InvalidScalar {
ty: "boolean",
location,
})?
};
visitor.visit_bool(b)
}
fn deserialize_i8<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: i8 = parse_int_signed(s.as_ref(), "i8", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_i8(v)
}
fn deserialize_i16<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: i16 = parse_int_signed(s.as_ref(), "i16", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_i16(v)
}
fn deserialize_i32<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: i32 = parse_int_signed(s.as_ref(), "i32", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_i32(v)
}
fn deserialize_i64<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: i64 = parse_int_signed(s.as_ref(), "i64", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_i64(v)
}
fn deserialize_i128<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: i128 =
parse_int_signed(s.as_ref(), "i128", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_i128(v)
}
fn deserialize_u8<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: u8 = parse_int_unsigned(s.as_ref(), "u8", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_u8(v)
}
fn deserialize_u16<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: u16 =
parse_int_unsigned(s.as_ref(), "u16", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_u16(v)
}
fn deserialize_u32<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: u32 =
parse_int_unsigned(s.as_ref(), "u32", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_u32(v)
}
fn deserialize_u64<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: u64 =
parse_int_unsigned(s.as_ref(), "u64", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_u64(v)
}
fn deserialize_u128<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let v: u128 =
parse_int_unsigned(s.as_ref(), "u128", location, self.cfg.legacy_octal_numbers)?;
visitor.visit_u128(v)
}
fn deserialize_f32<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, tag, location) = self.take_scalar_cow_with_location()?;
let v: f32 = parse_yaml12_float(s.as_ref(), location, tag, self.cfg.angle_conversions)?;
visitor.visit_f32(v)
}
fn deserialize_f64<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let (s, tag, location) = self.take_scalar_cow_with_location()?;
let v: f64 = parse_yaml12_float(s.as_ref(), location, tag, self.cfg.angle_conversions)?;
visitor.visit_f64(v)
}
fn deserialize_char<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
if let Some(view) = self.peek_scalar_view()?
&& view.tag != SfTag::String
{
if view.tag == SfTag::Null || scalar_is_nullish(&view.effective, &view.style) {
let (_value, _tag, location) = self.take_scalar_event()?;
return Err(Error::InvalidCharNull { location });
} else if self.cfg.no_schema && maybe_not_string(&view.effective, &view.style) {
let view = self.take_scalar_view()?;
return Err(self.quoting_required_for_scalar(&view));
}
}
let (s, _tag, location) = self.take_scalar_cow_with_location()?;
let mut it = s.as_ref().chars();
match (it.next(), it.next()) {
(Some(c), None) => visitor.visit_char(c),
_ => Err(Error::InvalidCharNotSingleScalar { location }),
}
}
fn deserialize_str<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let view = match self.peek_scalar_view()? {
Some(view) => {
if (view.tag == SfTag::Null || scalar_is_nullish(&view.effective, &view.style))
&& view.tag != SfTag::String
{
let loc = view.location;
let _ = self.ev.next()?;
return Err(Error::NullIntoString { location: loc });
} else if self.cfg.no_schema
&& maybe_not_string(&view.effective, &view.style)
&& view.tag != SfTag::String
{
let view = self.take_scalar_view()?;
return Err(self.quoting_required_for_scalar(&view));
}
if view.tag == SfTag::Binary && !self.cfg.ignore_binary_tag_for_string {
let res: Result<V::Value, Self::Error> =
visitor.visit_string(self.take_string_scalar()?);
return match res {
Ok(v) => Ok(v),
Err(err) if err.to_string().contains("expected a borrowed string") => Err(
Error::cannot_borrow_transformed(TransformReason::ParserReturnedOwned)
.with_location(view.location),
),
Err(err) => Err(err),
};
}
if !view.tag.can_parse_into_string()
&& view.tag != SfTag::NonSpecific
&& !(self.cfg.ignore_binary_tag_for_string && view.tag == SfTag::Binary)
{
return Err(Error::TaggedScalarCannotDeserializeIntoString {
location: view.location,
});
}
view
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
};
let location = view.location;
let redaction_ctx = view.redaction_ctx();
let cannot_borrow_reason = if view.interpolated {
TransformReason::VariableInterpolation
} else if self.ev.input_for_borrowing().is_none() {
TransformReason::InputNotBorrowable
} else {
TransformReason::ParserReturnedOwned
};
let view = self.take_peeked_scalar_view(view)?;
if let Cow::Borrowed(b) = view.effective {
return visitor.visit_borrowed_str(b);
}
let res: Result<V::Value, Self::Error> = with_scalar_redaction(redaction_ctx, || {
visitor.visit_string(view.effective.into_owned())
});
match res {
Ok(v) => Ok(v),
Err(err) => {
let msg = err.to_string();
if msg.contains("expected a borrowed string") {
return Err(Error::cannot_borrow_transformed(cannot_borrow_reason)
.with_location(location));
}
Err(err)
}
}
}
fn deserialize_string<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
let view = if let Some(view) = self.peek_scalar_view()? {
if (view.tag == SfTag::Null || scalar_is_nullish(&view.effective, &view.style))
&& view.tag != SfTag::String
{
let (_value, _tag, location) = self.take_scalar_event()?;
return Err(Error::NullIntoString { location });
} else if self.cfg.no_schema
&& maybe_not_string(&view.effective, &view.style)
&& view.tag != SfTag::String
{
let view = self.take_scalar_view()?;
return Err(self.quoting_required_for_scalar(&view));
}
if view.tag == SfTag::Binary && !self.cfg.ignore_binary_tag_for_string {
return visitor.visit_string(self.take_string_scalar()?);
}
if !view.tag.can_parse_into_string()
&& view.tag != SfTag::NonSpecific
&& !(self.cfg.ignore_binary_tag_for_string && view.tag == SfTag::Binary)
{
return Err(Error::TaggedScalarCannotDeserializeIntoString {
location: view.location,
});
}
view
} else {
return visitor.visit_string(self.take_string_scalar()?);
};
let redaction_ctx = view.redaction_ctx();
let view = self.take_peeked_scalar_view(view)?;
match view.effective {
Cow::Borrowed(b) => {
with_scalar_redaction(redaction_ctx, || visitor.visit_borrowed_str(b))
}
Cow::Owned(s) => with_scalar_redaction(redaction_ctx, || visitor.visit_string(s)),
}
}
fn deserialize_bytes<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
if let Some((_value, tag, _style, location)) = self.peek_effective_scalar()? {
if tag == SfTag::Binary {
let (value, data_location) = match self.ev.next()? {
Some(Ev::Scalar {
value, location, ..
}) => (value, location),
_ => unreachable!(),
};
let data =
decode_base64_yaml(&value).map_err(|err| err.with_location(data_location))?;
return visitor.visit_byte_buf(data);
} else {
return Err(Error::BytesNotSupportedMissingBinaryTag { location });
}
}
match self.ev.peek()? {
Some(Ev::SeqStart { .. }) => {
self.expect_seq_start()?;
let mut out = Vec::new();
loop {
match self.ev.peek()? {
Some(Ev::SeqEnd { .. }) => {
let _ = self.ev.next()?; break;
}
Some(_) => {
let b: u8 = <u8 as serde::Deserialize>::deserialize(
YamlDeserializer::new(&mut *self.ev, self.cfg),
)?;
out.push(b);
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
}
}
visitor.visit_byte_buf(out)
}
Some(other) => Err(
Error::unexpected("scalar (!!binary) or sequence of 0..=255")
.with_location(other.location()),
),
None => Err(Error::eof().with_location(self.ev.last_location())),
}
}
fn deserialize_byte_buf<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
self.deserialize_bytes(visitor)
}
fn deserialize_option<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
if self.in_key && self.key_empty_map_node {
match self.ev.next()? {
Some(Ev::MapStart { .. }) => {}
Some(other) => {
return Err(
Error::unexpected("empty mapping start").with_location(other.location())
);
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
}
match self.ev.next()? {
Some(Ev::MapEnd { .. }) => {}
Some(other) => {
return Err(
Error::unexpected("empty mapping end").with_location(other.location())
);
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
}
return visitor.visit_none();
}
if let Some((value, tag, style, _location)) = self.peek_effective_scalar()?
&& (tag == SfTag::Null || scalar_is_nullish_for_option(&value, &style))
{
let _ = self.ev.next()?; return visitor.visit_none();
}
match self.ev.peek()? {
None => visitor.visit_none(),
Some(Ev::MapEnd { .. }) | Some(Ev::SeqEnd { .. }) => visitor.visit_none(),
Some(_) => visitor.visit_some(self),
}
}
fn deserialize_unit<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
if let Some((value, _tag, style, _location)) = self.peek_effective_scalar()?
&& scalar_is_nullish(&value, &style)
{
let _ = self.ev.next()?; return visitor.visit_unit();
}
match self.ev.peek()? {
None => visitor.visit_unit(),
Some(Ev::MapEnd { .. }) | Some(Ev::SeqEnd { .. }) => visitor.visit_unit(),
Some(other) => Err(Error::UnexpectedValueForUnit {
location: other.location(),
}),
}
}
fn deserialize_unit_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error> {
match self.ev.peek()? {
Some(Ev::MapStart { .. }) => {
let _ = self.ev.next()?; match self.ev.peek()? {
Some(Ev::MapEnd { .. }) => {
let _ = self.ev.next()?; visitor.visit_unit()
}
Some(other) => Err(Error::ExpectedEmptyMappingForUnitStruct {
location: other.location(),
}),
None => Err(Error::eof().with_location(self.ev.last_location())),
}
}
_ => self.deserialize_unit(visitor),
}
}
fn deserialize_newtype_struct<V: Visitor<'de>>(
mut self,
n: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error> {
match n {
"__yaml_spanned" => spanned_deser::deserialize_yaml_spanned(self, visitor),
"__yaml_rc_anchor" => {
let anchor = self.peek_anchor_id()?;
anchor_store::with_anchor_context(AnchorKind::Rc, anchor, || {
visitor.visit_newtype_struct(self)
})
}
"__yaml_arc_anchor" => {
let anchor = self.peek_anchor_id()?;
anchor_store::with_anchor_context(AnchorKind::Arc, anchor, || {
visitor.visit_newtype_struct(self)
})
}
"__yaml_rc_recursive" => {
let anchor = self.peek_anchor_id()?;
anchor_store::with_anchor_context(AnchorKind::RcRecursive, anchor, || {
visitor.visit_newtype_struct(self)
})
}
"__yaml_arc_recursive" => {
let anchor = self.peek_anchor_id()?;
anchor_store::with_anchor_context(AnchorKind::ArcRecursive, anchor, || {
visitor.visit_newtype_struct(self)
})
}
"__yaml_rc_weak_anchor" => {
let anchor = self.peek_anchor_id()?;
anchor_store::with_anchor_context(AnchorKind::Rc, anchor, || {
visitor.visit_newtype_struct(self)
})
}
"__yaml_arc_weak_anchor" => {
let anchor = self.peek_anchor_id()?;
anchor_store::with_anchor_context(AnchorKind::Arc, anchor, || {
visitor.visit_newtype_struct(self)
})
}
"__yaml_rc_recursion" => {
let anchor = self.peek_anchor_id()?;
anchor_store::with_anchor_context(AnchorKind::RcRecursive, anchor, || {
visitor.visit_newtype_struct(self)
})
}
"__yaml_arc_recursion" => {
let anchor = self.peek_anchor_id()?;
anchor_store::with_anchor_context(AnchorKind::ArcRecursive, anchor, || {
visitor.visit_newtype_struct(self)
})
}
_ => visitor.visit_newtype_struct(self),
}
}
fn deserialize_seq<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
if let Some((s, tag, style, _location)) = self.peek_effective_scalar()? {
if tag == SfTag::Null || scalar_is_nullish(&s, &style) {
let _ = self.ev.next()?; struct EmptySeq;
impl<'de> de::SeqAccess<'de> for EmptySeq {
type Error = Error;
fn next_element_seed<T>(&mut self, _seed: T) -> Result<Option<T::Value>, Error>
where
T: de::DeserializeSeed<'de>,
{
Ok(None)
}
}
return visitor.visit_seq(EmptySeq);
}
if tag == SfTag::Binary {
let (scalar, data_location) = match self.ev.next()? {
Some(Ev::Scalar {
value, location, ..
}) => (value, location),
_ => unreachable!(),
};
let data =
decode_base64_yaml(&scalar).map_err(|err| err.with_location(data_location))?;
struct ByteSeq {
data: Vec<u8>,
idx: usize,
}
impl<'de> de::SeqAccess<'de> for ByteSeq {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where
T: de::DeserializeSeed<'de>,
{
if self.idx >= self.data.len() {
return Ok(None);
}
let b = self.data[self.idx];
self.idx += 1;
let deser = serde::de::value::U8Deserializer::<Error>::new(b);
seed.deserialize(deser).map(Some)
}
}
return visitor.visit_seq(ByteSeq { data, idx: 0 });
}
}
self.expect_seq_start()?;
struct SA<'de, 'e> {
ev: &'e mut dyn Events<'de>,
cfg: Cfg,
#[cfg(any(feature = "garde", feature = "validator"))]
garde: Option<&'e mut PathRecorder>,
#[cfg(any(feature = "garde", feature = "validator"))]
idx: usize,
}
impl<'de, 'e> de::SeqAccess<'de> for SA<'de, 'e> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where
T: de::DeserializeSeed<'de>,
{
let (is_end, defined_location) = {
let peeked = self.ev.peek()?;
match peeked {
Some(Ev::SeqEnd { .. }) => (true, Location::UNKNOWN),
Some(ev) => (false, ev.location()),
None => return Err(Error::eof().with_location(self.ev.last_location())),
}
};
if is_end {
return Ok(None);
}
let reference_location = self.ev.reference_location();
let _missing_field_guard = MissingFieldLocationGuard::new(reference_location);
#[cfg(any(feature = "garde", feature = "validator"))]
{
if let Some(garde_ref) = self.garde.as_mut() {
let recorder: &mut PathRecorder = garde_ref;
let prev = recorder.current.take();
let now = prev.clone().join(self.idx);
recorder.current = now.clone();
recorder.map.insert(
now,
Locations {
reference_location,
defined_location,
},
);
let mut de =
YamlDeserializer::new_with_path_recorder(self.ev, self.cfg, recorder);
let redaction_ctx = de.peek_scalar_redaction_ctx()?;
let res = with_subtree_redaction(redaction_ctx, || seed.deserialize(de))
.map(Some)
.map_err(|e| {
attach_alias_locations_if_missing(
e,
reference_location,
defined_location,
)
});
recorder.current = prev;
self.idx += 1;
return res;
}
}
let mut de = YamlDeserializer::new(self.ev, self.cfg);
let redaction_ctx = de.peek_scalar_redaction_ctx()?;
with_subtree_redaction(redaction_ctx, || seed.deserialize(de))
.map(Some)
.map_err(|e| {
attach_alias_locations_if_missing(e, reference_location, defined_location)
})
}
}
#[cfg(any(feature = "garde", feature = "validator"))]
let garde = self.garde;
let result = visitor.visit_seq(SA {
ev: self.ev,
cfg: self.cfg,
#[cfg(any(feature = "garde", feature = "validator"))]
garde,
#[cfg(any(feature = "garde", feature = "validator"))]
idx: 0,
})?;
if let Some(Ev::SeqEnd { .. }) = self.ev.peek()? {
let _ = self.ev.next()?;
}
Ok(result)
}
fn deserialize_tuple<V: Visitor<'de>>(
self,
_len: usize,
visitor: V,
) -> Result<V::Value, Self::Error> {
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value, Self::Error> {
self.deserialize_seq(visitor)
}
fn deserialize_map<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error> {
if let Some((s, tag, style, _location)) = self.peek_effective_scalar()?
&& (tag == SfTag::Null || scalar_is_nullish(&s, &style))
{
let _ = self.ev.next()?; struct EmptyMap;
impl<'de> de::MapAccess<'de> for EmptyMap {
type Error = Error;
fn next_key_seed<K>(&mut self, _seed: K) -> Result<Option<K::Value>, Error>
where
K: de::DeserializeSeed<'de>,
{
Ok(None)
}
fn next_value_seed<Vv>(&mut self, _seed: Vv) -> Result<Vv::Value, Error>
where
Vv: de::DeserializeSeed<'de>,
{
unreachable!("no values in empty map")
}
}
return visitor.visit_map(EmptyMap);
}
self.expect_map_start()?;
let _missing_field_guard = MissingFieldLocationGuard::new(self.ev.reference_location());
#[cfg(any(feature = "garde", feature = "validator"))]
if let Some(recorder) = self.garde.as_mut() {
let path = recorder.current.clone();
recorder.map.insert(
path,
Locations {
reference_location: self.ev.reference_location(),
defined_location: self.ev.last_location(),
},
);
}
struct MA<'de, 'e> {
ev: &'e mut dyn Events<'de>,
cfg: Cfg,
have_key: bool,
fallback_guard: Option<MissingFieldLocationGuard>,
#[cfg(any(feature = "garde", feature = "validator"))]
garde: Option<&'e mut PathRecorder>,
#[cfg(any(feature = "garde", feature = "validator"))]
pending_path_segment: Option<String>,
seen: FastHashSet<KeyFingerprint>,
pending: VecDeque<PendingEntry<'de>>,
merge_stack: Vec<Vec<PendingEntry<'de>>>,
flushing_merges: bool,
pending_value: Option<(Vec<Ev<'de>>, Location)>,
}
impl<'de, 'e> MA<'de, 'e> {
fn skip_one_node(&mut self) -> Result<(), Error> {
let mut depth; match self.ev.next()? {
Some(Ev::Scalar { .. }) => return Ok(()),
Some(Ev::SeqStart { .. }) | Some(Ev::MapStart { .. }) => depth = 1,
Some(Ev::SeqEnd { location }) | Some(Ev::MapEnd { location }) => {
return Err(Error::UnexpectedContainerEndWhileSkippingNode { location });
}
Some(Ev::Taken { location }) => {
return Err(Error::unexpected("consumed event").with_location(location));
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
}
while depth != 0 {
match self.ev.next()? {
Some(Ev::SeqStart { .. }) | Some(Ev::MapStart { .. }) => depth += 1,
Some(Ev::SeqEnd { .. }) | Some(Ev::MapEnd { .. }) => depth -= 1,
Some(Ev::Scalar { .. }) => {}
Some(Ev::Taken { location }) => {
return Err(Error::unexpected("consumed event").with_location(location));
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
}
}
Ok(())
}
fn deserialize_recorded_key<'de2, K>(
&mut self,
seed: K,
events: Vec<Ev<'de2>>,
kemn: bool,
) -> Result<K::Value, Error>
where
K: de::DeserializeSeed<'de2>,
{
let mut replay = ReplayEvents::new(
events,
#[cfg(feature = "properties")]
self.ev.property_map().cloned(),
);
let location = replay.reference_location();
let de = YamlDeserializer::<'de2, '_> {
ev: &mut replay,
cfg: self.cfg,
in_key: true,
key_empty_map_node: kemn,
#[cfg(any(feature = "garde", feature = "validator"))]
garde: None,
};
seed.deserialize(de).map_err(|e| {
if e.location().is_none() {
e.with_location(location)
} else {
e
}
})
}
fn enqueue_entries(&mut self, entries: Vec<PendingEntry<'de>>) {
self.pending.reserve(entries.len());
for entry in entries.into_iter().rev() {
self.pending.push_front(entry);
}
}
fn enqueue_next_merge_batch(&mut self) -> bool {
while let Some(entries) = self.merge_stack.pop() {
if entries.is_empty() {
continue;
}
self.enqueue_entries(entries);
return true;
}
false
}
}
impl<'de, 'e> de::MapAccess<'de> for MA<'de, 'e> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where
K: de::DeserializeSeed<'de>,
{
let mut seed = Some(seed);
loop {
if let Some(entry) = self.pending.pop_front() {
let PendingEntry {
mut key,
mut value,
reference_location,
} = entry;
let fingerprint = key.take_fingerprint();
let location = key.location();
let mut events = key.take_events();
let is_duplicate = self.seen.contains(&fingerprint);
if self.flushing_merges {
if is_duplicate {
continue;
}
} else {
match self.cfg.dup_policy {
DuplicateKeyPolicy::Error => {
if is_duplicate {
let key = fingerprint
.stringy_scalar_value()
.map(|s| s.to_owned());
return Err(Error::DuplicateMappingKey { key, location });
}
}
DuplicateKeyPolicy::FirstWins => {
if is_duplicate {
continue;
}
}
DuplicateKeyPolicy::LastWins => {}
}
}
let mut value_events = value.take_events();
let kemn_direct =
matches!(fingerprint, KeyFingerprint::Mapping(ref v) if v.is_empty());
let mut kemn = kemn_direct;
if !kemn
&& let KeyFingerprint::Mapping(ref pairs) = fingerprint
&& pairs.len() == 1
&& let (
KeyFingerprint::Scalar {
value: sv,
tag: stag,
},
_,
) = &pairs[0]
{
let is_nullish = *stag == SfTag::Null
|| sv.is_empty()
|| sv == "~"
|| sv.eq_ignore_ascii_case("null");
if is_nullish {
if let Some((_ks, _ke, vs, ve)) = one_entry_map_spans(&events) {
value_events = events.drain(vs..ve).collect();
let start = match events.first() {
Some(Ev::MapStart { anchor, location }) => Ev::MapStart {
anchor: *anchor,
location: *location,
},
Some(other) => other.clone(),
None => {
return Err(Error::unexpected("mapping start")
.with_location(location));
}
};
let end = match events.last() {
Some(Ev::MapEnd { location }) => Ev::MapEnd {
location: *location,
},
Some(other) => other.clone(),
None => {
return Err(Error::unexpected("mapping end")
.with_location(location));
}
};
events = vec![start, end];
kemn = true;
}
}
}
let key_seed = match seed.take() {
Some(s) => s,
None => {
return Err(Error::InternalSeedReusedForMapKey { location });
}
};
match &mut self.fallback_guard {
Some(guard) => guard.replace_location(location),
None => {
self.fallback_guard = Some(MissingFieldLocationGuard::new(location))
}
}
let key_value = self.deserialize_recorded_key(key_seed, events, kemn)?;
self.have_key = true;
self.pending_value = Some((value_events, reference_location));
#[cfg(any(feature = "garde", feature = "validator"))]
{
self.pending_path_segment =
fingerprint.stringy_scalar_value().map(|s| s.to_owned());
}
self.seen.insert(fingerprint);
return Ok(Some(key_value));
}
if self.flushing_merges {
if self.enqueue_next_merge_batch() {
continue;
}
self.flushing_merges = false;
return Ok(None);
}
match self.ev.peek()? {
Some(Ev::MapEnd { .. }) => {
let _ = self.ev.next()?; if self.merge_stack.is_empty() {
return Ok(None);
}
self.flushing_merges = true;
if self.enqueue_next_merge_batch() {
continue;
}
self.flushing_merges = false;
return Ok(None);
}
Some(_) => {
let mut key_node = capture_node(self.ev)?;
if is_merge_key(&key_node) {
let _ = self.ev.peek()?;
let merge_ref_loc = self.ev.reference_location();
let entries =
pending_entries_from_live_events(self.ev, merge_ref_loc)?;
if !entries.is_empty() {
self.merge_stack.push(entries);
}
continue;
}
let fingerprint = key_node.fingerprint();
let is_duplicate = self.seen.contains(&fingerprint);
match self.cfg.dup_policy {
DuplicateKeyPolicy::Error => {
if is_duplicate {
let location = key_node.location();
let key = key_node
.fingerprint()
.stringy_scalar_value()
.map(|s| s.to_owned());
return Err(Error::DuplicateMappingKey { key, location });
}
}
DuplicateKeyPolicy::FirstWins => {
if is_duplicate {
self.skip_one_node()?;
continue;
}
}
DuplicateKeyPolicy::LastWins => {}
}
let kemn_direct = matches!(*fingerprint, KeyFingerprint::Mapping(ref v) if v.is_empty());
let kemn_one_entry_nullish = match &*fingerprint {
KeyFingerprint::Mapping(pairs) if pairs.len() == 1 => {
if let (
KeyFingerprint::Scalar {
value: sv,
tag: stag,
},
_,
) = &pairs[0]
{
*stag == SfTag::Null
|| sv.is_empty()
|| sv == "~"
|| sv.eq_ignore_ascii_case("null")
} else {
false
}
}
_ => false,
};
if kemn_one_entry_nullish {
let _ = self.ev.peek()?;
let reference_location = self.ev.reference_location();
let value_node = capture_node(self.ev)?;
self.enqueue_entries(vec![PendingEntry {
key: key_node,
value: value_node,
reference_location,
}]);
continue;
} else {
let fingerprint = fingerprint.into_owned();
let location = key_node.location();
let events = key_node.take_events();
let key_seed = match seed.take() {
Some(s) => s,
None => {
return Err(Error::InternalSeedReusedForMapKey {
location,
});
}
};
match &mut self.fallback_guard {
Some(guard) => guard.replace_location(location),
None => {
self.fallback_guard =
Some(MissingFieldLocationGuard::new(location))
}
}
let key_value =
self.deserialize_recorded_key(key_seed, events, kemn_direct)?;
self.have_key = true;
self.pending_value = None;
#[cfg(any(feature = "garde", feature = "validator"))]
{
self.pending_path_segment =
fingerprint.stringy_scalar_value().map(|s| s.to_owned());
}
self.seen.insert(fingerprint);
return Ok(Some(key_value));
}
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
}
}
}
fn next_value_seed<Vv>(&mut self, seed: Vv) -> Result<Vv::Value, Error>
where
Vv: de::DeserializeSeed<'de>,
{
if !self.have_key {
return Err(Error::ValueRequestedBeforeKey {
location: self.ev.last_location(),
});
}
self.have_key = false;
#[cfg(any(feature = "garde", feature = "validator"))]
let pending_segment = self.pending_path_segment.take();
if let Some(events) = self.pending_value.take() {
let (events, reference_location) = events;
let mut replay = ReplayEvents::with_reference(
events,
reference_location,
#[cfg(feature = "properties")]
self.ev.property_map().cloned(),
);
let defined_location = replay
.peek()?
.map(|ev| ev.location())
.unwrap_or_else(|| replay.last_location());
#[cfg(any(feature = "garde", feature = "validator"))]
{
if let (Some(seg), Some(garde_ref)) = (pending_segment, self.garde.as_mut())
{
let recorder: &mut PathRecorder = garde_ref;
let prev = recorder.current.take();
let now = prev.clone().join(seg.as_str());
recorder.current = now.clone();
recorder.map.insert(
now,
Locations {
reference_location,
defined_location,
},
);
let mut de = YamlDeserializer::new_with_path_recorder(
&mut replay,
self.cfg,
recorder,
);
let redaction_ctx = de.peek_scalar_redaction_ctx()?;
let res =
with_subtree_redaction(redaction_ctx, || seed.deserialize(de))
.map_err(|e| {
attach_alias_locations_if_missing(
e,
reference_location,
defined_location,
)
});
recorder.current = prev;
return res;
}
}
let mut de = YamlDeserializer::new(&mut replay, self.cfg);
let redaction_ctx = de.peek_scalar_redaction_ctx()?;
with_subtree_redaction(redaction_ctx, || seed.deserialize(de)).map_err(|e| {
attach_alias_locations_if_missing(e, reference_location, defined_location)
})
} else {
let defined_location = self
.ev
.peek()?
.map(|ev: &Ev| ev.location())
.unwrap_or_else(|| self.ev.last_location());
let reference_location = self.ev.reference_location();
#[cfg(any(feature = "garde", feature = "validator"))]
{
if let (Some(seg), Some(garde_ref)) = (pending_segment, self.garde.as_mut())
{
let recorder: &mut PathRecorder = garde_ref;
let prev = recorder.current.take();
let now = prev.clone().join(seg.as_str());
recorder.current = now.clone();
recorder.map.insert(
now,
Locations {
reference_location,
defined_location,
},
);
let mut de = YamlDeserializer::new_with_path_recorder(
self.ev, self.cfg, recorder,
);
let redaction_ctx = de.peek_scalar_redaction_ctx()?;
let res =
with_subtree_redaction(redaction_ctx, || seed.deserialize(de))
.map_err(|e| {
attach_alias_locations_if_missing(
e,
reference_location,
defined_location,
)
});
recorder.current = prev;
return res;
}
}
let mut de = YamlDeserializer::new(self.ev, self.cfg);
let redaction_ctx = de.peek_scalar_redaction_ctx()?;
with_scalar_redaction(redaction_ctx, || seed.deserialize(de)).map_err(|e| {
attach_alias_locations_if_missing(e, reference_location, defined_location)
})
}
}
}
#[cfg(any(feature = "garde", feature = "validator"))]
let garde = self.garde;
visitor.visit_map(MA {
ev: self.ev,
cfg: self.cfg,
have_key: false,
fallback_guard: None,
#[cfg(any(feature = "garde", feature = "validator"))]
garde,
#[cfg(any(feature = "garde", feature = "validator"))]
pending_path_segment: None,
seen: FastHashSet::with_capacity(8),
pending: VecDeque::new(),
merge_stack: Vec::new(),
flushing_merges: false,
pending_value: None,
})
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error> {
self.deserialize_map(visitor)
}
fn deserialize_enum<V: Visitor<'de>>(
mut self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error> {
enum Mode<'de, 'a> {
Unit(EnumScalarId<'de>),
Map(String, Location),
TaggedNewtype(EnumScalarId<'de>, Vec<Ev<'a>>),
}
let mut tagged_enum = None;
let peeked_ev = self.ev.peek()?.cloned();
let mode = match peeked_ev {
Some(Ev::Scalar {
tag,
style,
value: _,
raw_tag,
location,
..
}) => {
if let Some(tag_name) = simple_tagged_enum_name(&raw_tag, &tag) {
tagged_enum = Some((tag_name, location));
}
let view = self.peek_scalar_view()?.unwrap();
if self.cfg.no_schema
&& tag != SfTag::String
&& maybe_not_string(&view.effective, &style)
{
let view = self.take_scalar_view()?;
return Err(self.quoting_required_for_scalar(&view));
}
if let Some((ref tag_name, tag_loc)) = tagged_enum {
if _variants.contains(&tag_name.as_str()) {
let variant_name = EnumScalarId {
raw: Cow::Owned(tag_name.clone()),
effective: Cow::Owned(tag_name.clone()),
interpolated: false,
location: tag_loc,
};
let ev = self.ev.next()?.unwrap();
let replay = match ev {
Ev::Scalar {
value,
style,
location,
anchor,
..
} => {
vec![Ev::Scalar {
value,
tag: SfTag::String,
raw_tag: None,
style,
location,
anchor,
}]
}
other => vec![other],
};
tagged_enum = None; Mode::TaggedNewtype(variant_name, replay)
} else {
let view = self.take_scalar_view()?;
Mode::Unit(EnumScalarId::from_view(view))
}
} else {
let view = self.take_scalar_view()?;
Mode::Unit(EnumScalarId::from_view(view))
}
}
Some(Ev::MapStart { .. }) => {
self.expect_map_start()?;
let mut key_de = YamlDeserializer::new(&mut *self.ev, self.cfg);
key_de.in_key = true;
if let Some(view) = key_de.peek_scalar_view()? {
if self.cfg.no_schema
&& view.tag != SfTag::String
&& maybe_not_string(&view.raw, &view.style)
{
let view = key_de.take_scalar_view()?;
return Err(self.quoting_required_for_scalar(&view));
}
let view = key_de.take_scalar_view()?;
Mode::Map(view.raw.into_owned(), view.location)
} else {
match self.ev.next()? {
Some(other) => {
return Err(Error::ExpectedStringKeyForExternallyTaggedEnum {
location: other.location(),
});
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
}
}
}
Some(Ev::SeqStart {
tag,
raw_tag,
location,
..
}) => {
if let Some(tag_name) = simple_tagged_enum_name(&raw_tag, &tag)
&& _variants.contains(&tag_name.as_str())
{
let seq_start = self.ev.next()?.unwrap();
let start_loc = seq_start.location();
let mut replay_events: Vec<Ev<'de>> = Vec::new();
if let Ev::SeqStart {
anchor, location, ..
} = seq_start
{
replay_events.push(Ev::SeqStart {
anchor,
tag: SfTag::None,
raw_tag: None,
location,
});
}
let mut depth = 1usize;
while depth > 0 {
match self.ev.next()? {
Some(ev @ Ev::SeqStart { .. }) => {
depth += 1;
replay_events.push(ev);
}
Some(ev @ Ev::SeqEnd { .. }) => {
depth -= 1;
replay_events.push(ev);
}
Some(ev @ Ev::MapStart { .. }) => {
depth += 1;
replay_events.push(ev);
}
Some(ev @ Ev::MapEnd { .. }) => {
depth -= 1;
replay_events.push(ev);
}
Some(ev) => {
replay_events.push(ev);
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
}
}
let replay = Box::new(ReplayEvents::new(
replay_events,
#[cfg(feature = "properties")]
self.ev.property_map().cloned(),
));
return visitor.visit_enum(TaggedEA {
replay,
cfg: self.cfg,
variant: EnumScalarId {
raw: Cow::Owned(tag_name.clone()),
effective: Cow::Owned(tag_name),
interpolated: false,
location: start_loc,
},
});
}
return Err(Error::ExternallyTaggedEnumExpectedScalarOrMapping { location });
}
Some(Ev::SeqEnd { location }) => {
return Err(Error::UnexpectedSequenceEnd { location });
}
Some(Ev::MapEnd { location }) => {
return Err(Error::UnexpectedMappingEnd { location });
}
Some(Ev::Taken { location }) => {
return Err(Error::unexpected("consumed event").with_location(location));
}
None => return Err(Error::eof().with_location(self.ev.last_location())),
};
if let Some((tag_name, location)) = tagged_enum
&& tag_name != _name
{
return Err(Error::TaggedEnumMismatch {
tagged: tag_name,
target: _name,
location,
});
}
struct EA<'de, 'e> {
ev: &'e mut dyn Events<'de>,
cfg: Cfg,
variant: EnumScalarId<'de>,
map_mode: bool,
}
impl<'de, 'e> de::EnumAccess<'de> for EA<'de, 'e> {
type Error = Error;
type Variant = VA<'de, 'e>;
fn variant_seed<Vv>(self, seed: Vv) -> Result<(Vv::Value, Self::Variant), Error>
where
Vv: de::DeserializeSeed<'de>,
{
let EA {
ev,
cfg,
variant,
map_mode,
} = self;
let v = seed.deserialize(variant.into_deserializer())?;
Ok((v, VA { ev, cfg, map_mode }))
}
}
struct VA<'de, 'e> {
ev: &'e mut dyn Events<'de>,
cfg: Cfg,
map_mode: bool,
}
impl<'de, 'e> VA<'de, 'e> {
fn expect_map_end(&mut self) -> Result<(), Error> {
match self.ev.next()? {
Some(Ev::MapEnd { .. }) => Ok(()),
Some(other) => Err(Error::ExpectedMappingEndAfterEnumVariantValue {
location: other.location(),
}),
None => Err(Error::eof().with_location(self.ev.last_location())),
}
}
}
impl<'de, 'e> de::VariantAccess<'de> for VA<'de, 'e> {
type Error = Error;
fn unit_variant(mut self) -> Result<(), Error> {
if self.map_mode {
match self.ev.peek()? {
Some(Ev::MapEnd { .. }) => {
let _ = self.ev.next()?;
Ok(())
}
Some(Ev::Scalar {
value: s, style, ..
}) if scalar_is_nullish(s, style) => {
let _ = self.ev.next()?; self.expect_map_end()
}
Some(other) => Err(Error::UnexpectedValueForUnitEnumVariant {
location: other.location(),
}),
None => Err(Error::eof().with_location(self.ev.last_location())),
}
} else {
Ok(())
}
}
fn newtype_variant_seed<T>(mut self, seed: T) -> Result<T::Value, Error>
where
T: de::DeserializeSeed<'de>,
{
let defined_location = self
.ev
.peek()?
.map(|ev: &Ev| ev.location())
.unwrap_or_else(|| self.ev.last_location());
let reference_location = self.ev.reference_location();
let mut de = YamlDeserializer::new(self.ev, self.cfg);
let redaction_ctx = de.peek_scalar_redaction_ctx()?;
let value = with_subtree_redaction(redaction_ctx, || seed.deserialize(de))
.map_err(|e| {
attach_alias_locations_if_missing(e, reference_location, defined_location)
})?;
if self.map_mode {
self.expect_map_end()?;
}
Ok(value)
}
fn tuple_variant<Vv>(mut self, len: usize, visitor: Vv) -> Result<Vv::Value, Error>
where
Vv: Visitor<'de>,
{
let result =
YamlDeserializer::new(self.ev, self.cfg).deserialize_tuple(len, visitor)?;
if self.map_mode {
self.expect_map_end()?;
}
Ok(result)
}
fn struct_variant<Vv>(
mut self,
fields: &'static [&'static str],
visitor: Vv,
) -> Result<Vv::Value, Error>
where
Vv: Visitor<'de>,
{
let result = YamlDeserializer::new(self.ev, self.cfg)
.deserialize_struct("", fields, visitor)?;
if self.map_mode {
self.expect_map_end()?;
}
Ok(result)
}
}
struct TaggedEA<'de> {
replay: Box<ReplayEvents<'de>>,
cfg: Cfg,
variant: EnumScalarId<'de>,
}
impl<'de> de::EnumAccess<'de> for TaggedEA<'de> {
type Error = Error;
type Variant = TaggedVA<'de>;
fn variant_seed<Vv>(self, seed: Vv) -> Result<(Vv::Value, Self::Variant), Error>
where
Vv: de::DeserializeSeed<'de>,
{
let v = seed.deserialize(self.variant.into_deserializer())?;
Ok((
v,
TaggedVA {
replay: self.replay,
cfg: self.cfg,
},
))
}
}
struct TaggedVA<'de> {
replay: Box<ReplayEvents<'de>>,
cfg: Cfg,
}
impl<'de> de::VariantAccess<'de> for TaggedVA<'de> {
type Error = Error;
fn unit_variant(self) -> Result<(), Error> {
Ok(())
}
fn newtype_variant_seed<T>(mut self, seed: T) -> Result<T::Value, Error>
where
T: de::DeserializeSeed<'de>,
{
let mut de = YamlDeserializer::new(&mut *self.replay, self.cfg);
let redaction_ctx = de.peek_scalar_redaction_ctx()?;
with_subtree_redaction(redaction_ctx, || seed.deserialize(de))
}
fn tuple_variant<Vv>(mut self, len: usize, visitor: Vv) -> Result<Vv::Value, Error>
where
Vv: Visitor<'de>,
{
YamlDeserializer::new(&mut *self.replay, self.cfg).deserialize_tuple(len, visitor)
}
fn struct_variant<Vv>(
mut self,
fields: &'static [&'static str],
visitor: Vv,
) -> Result<Vv::Value, Error>
where
Vv: Visitor<'de>,
{
YamlDeserializer::new(&mut *self.replay, self.cfg)
.deserialize_struct("", fields, visitor)
}
}
let access = match mode {
Mode::Unit(variant) => EA {
ev: self.ev,
cfg: self.cfg,
variant,
map_mode: false,
},
Mode::Map(variant, variant_location) => EA {
ev: self.ev,
cfg: self.cfg,
variant: EnumScalarId {
raw: Cow::Owned(variant.clone()),
effective: Cow::Owned(variant),
interpolated: false,
location: variant_location,
},
map_mode: true,
},
Mode::TaggedNewtype(variant, replay_buf) => {
let replay = Box::new(ReplayEvents::new(
replay_buf,
#[cfg(feature = "properties")]
self.ev.property_map().cloned(),
));
return visitor.visit_enum(TaggedEA {
replay,
cfg: self.cfg,
variant,
});
}
};
visitor.visit_enum(access)
}
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
self.deserialize_str(visitor)
}
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
self.deserialize_any(visitor)
}
}