use crate::error::{self, Error, ErrorImpl}; use crate::libyaml::error::Mark; use crate::libyaml::parser::{MappingStart, Scalar, ScalarStyle, SequenceStart}; use crate::libyaml::tag::Tag; use crate::loader::{Document, Loader}; use crate::path::Path; use serde::de::value::StrDeserializer; use serde::de::{ self, Deserialize, DeserializeOwned, DeserializeSeed, Expected, IgnoredAny, Unexpected, Visitor, }; use std::fmt; use std::io; use std::mem; use std::num::ParseIntError; use std::str; use std::sync::Arc; type Result = std::result::Result; /// A structure that deserializes YAML into Rust values. /// /// # Examples /// /// Deserializing a single document: /// /// ``` /// use anyhow::Result; /// use serde::Deserialize; /// use serde_yaml::Value; /// /// fn main() -> Result<()> { /// let input = "k: 107\n"; /// let de = serde_yaml::Deserializer::from_str(input); /// let value = Value::deserialize(de)?; /// println!("{:?}", value); /// Ok(()) /// } /// ``` /// /// Deserializing multi-doc YAML: /// /// ``` /// use anyhow::Result; /// use serde::Deserialize; /// use serde_yaml::Value; /// /// fn main() -> Result<()> { /// let input = "---\nk: 107\n...\n---\nj: 106\n"; /// /// for document in serde_yaml::Deserializer::from_str(input) { /// let value = Value::deserialize(document)?; /// println!("{:?}", value); /// } /// /// Ok(()) /// } /// ``` pub struct Deserializer<'de> { progress: Progress<'de>, } pub(crate) enum Progress<'de> { Str(&'de str), Slice(&'de [u8]), Read(Box), Iterable(Loader<'de>), Document(Document<'de>), Fail(Arc), } impl<'de> Deserializer<'de> { /// Creates a YAML deserializer from a `&str`. pub fn from_str(s: &'de str) -> Self { let progress = Progress::Str(s); Deserializer { progress } } /// Creates a YAML deserializer from a `&[u8]`. pub fn from_slice(v: &'de [u8]) -> Self { let progress = Progress::Slice(v); Deserializer { progress } } /// Creates a YAML deserializer from an `io::Read`. /// /// Reader-based deserializers do not support deserializing borrowed types /// like `&str`, since the `std::io::Read` trait has no non-copying methods /// -- everything it does involves copying bytes out of the data source. pub fn from_reader(rdr: R) -> Self where R: io::Read + 'de, { let progress = Progress::Read(Box::new(rdr)); Deserializer { progress } } fn de( self, f: impl for<'document> FnOnce(&mut DeserializerFromEvents<'de, 'document>) -> Result, ) -> Result { let mut pos = 0; let mut jumpcount = 0; match self.progress { Progress::Iterable(_) => return Err(error::new(ErrorImpl::MoreThanOneDocument)), Progress::Document(document) => { let t = f(&mut DeserializerFromEvents { document: &document, pos: &mut pos, jumpcount: &mut jumpcount, path: Path::Root, remaining_depth: 128, current_enum: None, })?; if let Some(parse_error) = document.error { return Err(error::shared(parse_error)); } return Ok(t); } _ => {} } let mut loader = Loader::new(self.progress)?; let document = match loader.next_document() { Some(document) => document, None => return Err(error::new(ErrorImpl::EndOfStream)), }; let t = f(&mut DeserializerFromEvents { document: &document, pos: &mut pos, jumpcount: &mut jumpcount, path: Path::Root, remaining_depth: 128, current_enum: None, })?; if let Some(parse_error) = document.error { return Err(error::shared(parse_error)); } if loader.next_document().is_none() { Ok(t) } else { Err(error::new(ErrorImpl::MoreThanOneDocument)) } } } impl<'de> Iterator for Deserializer<'de> { type Item = Self; fn next(&mut self) -> Option { match &mut self.progress { Progress::Iterable(loader) => { let document = loader.next_document()?; return Some(Deserializer { progress: Progress::Document(document), }); } Progress::Document(_) => return None, Progress::Fail(err) => { return Some(Deserializer { progress: Progress::Fail(Arc::clone(err)), }); } _ => {} } let dummy = Progress::Str(""); let input = mem::replace(&mut self.progress, dummy); match Loader::new(input) { Ok(loader) => { self.progress = Progress::Iterable(loader); self.next() } Err(err) => { let fail = err.shared(); self.progress = Progress::Fail(Arc::clone(&fail)); Some(Deserializer { progress: Progress::Fail(fail), }) } } } } impl<'de> de::Deserializer<'de> for Deserializer<'de> { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_any(visitor)) } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_bool(visitor)) } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i8(visitor)) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i16(visitor)) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i32(visitor)) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i64(visitor)) } fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i128(visitor)) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u8(visitor)) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u16(visitor)) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u32(visitor)) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u64(visitor)) } fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u128(visitor)) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_f32(visitor)) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_f64(visitor)) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_char(visitor)) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_str(visitor)) } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_string(visitor)) } fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_bytes(visitor)) } fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_byte_buf(visitor)) } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_option(visitor)) } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_unit(visitor)) } fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_unit_struct(name, visitor)) } fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_newtype_struct(name, visitor)) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_seq(visitor)) } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_tuple(len, visitor)) } fn deserialize_tuple_struct( self, name: &'static str, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_tuple_struct(name, len, visitor)) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_map(visitor)) } fn deserialize_struct( self, name: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_struct(name, fields, visitor)) } fn deserialize_enum( self, name: &'static str, variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_enum(name, variants, visitor)) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_identifier(visitor)) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_ignored_any(visitor)) } } #[derive(Debug)] pub(crate) enum Event<'de> { Alias(usize), Scalar(Scalar<'de>), SequenceStart(SequenceStart), SequenceEnd, MappingStart(MappingStart), MappingEnd, Void, } struct DeserializerFromEvents<'de, 'document> { document: &'document Document<'de>, pos: &'document mut usize, jumpcount: &'document mut usize, path: Path<'document>, remaining_depth: u8, current_enum: Option>, } #[derive(Copy, Clone)] struct CurrentEnum<'document> { name: Option<&'static str>, tag: &'document str, } impl<'de, 'document> DeserializerFromEvents<'de, 'document> { fn peek_event(&self) -> Result<&'document Event<'de>> { self.peek_event_mark().map(|(event, _mark)| event) } fn peek_event_mark(&self) -> Result<(&'document Event<'de>, Mark)> { match self.document.events.get(*self.pos) { Some((event, mark)) => Ok((event, *mark)), None => Err(match &self.document.error { Some(parse_error) => error::shared(Arc::clone(parse_error)), None => error::new(ErrorImpl::EndOfStream), }), } } fn next_event(&mut self) -> Result<&'document Event<'de>> { self.next_event_mark().map(|(event, _mark)| event) } fn next_event_mark(&mut self) -> Result<(&'document Event<'de>, Mark)> { self.peek_event_mark().map(|(event, mark)| { *self.pos += 1; self.current_enum = None; (event, mark) }) } fn jump<'anchor>( &'anchor mut self, pos: &'anchor mut usize, ) -> Result> { *self.jumpcount += 1; if *self.jumpcount > self.document.events.len() * 100 { return Err(error::new(ErrorImpl::RepetitionLimitExceeded)); } match self.document.aliases.get(pos) { Some(found) => { *pos = *found; Ok(DeserializerFromEvents { document: self.document, pos, jumpcount: self.jumpcount, path: Path::Alias { parent: &self.path }, remaining_depth: self.remaining_depth, current_enum: None, }) } None => panic!("unresolved alias: {}", *pos), } } fn ignore_any(&mut self) -> Result<()> { enum Nest { Sequence, Mapping, } let mut stack = Vec::new(); loop { match self.next_event()? { Event::Alias(_) | Event::Scalar(_) | Event::Void => {} Event::SequenceStart(_) => { stack.push(Nest::Sequence); } Event::MappingStart(_) => { stack.push(Nest::Mapping); } Event::SequenceEnd => match stack.pop() { Some(Nest::Sequence) => {} None | Some(Nest::Mapping) => { panic!("unexpected end of sequence"); } }, Event::MappingEnd => match stack.pop() { Some(Nest::Mapping) => {} None | Some(Nest::Sequence) => { panic!("unexpected end of mapping"); } }, } if stack.is_empty() { return Ok(()); } } } fn visit_sequence(&mut self, visitor: V, mark: Mark) -> Result where V: Visitor<'de>, { let (value, len) = self.recursion_check(mark, |de| { let mut seq = SeqAccess { empty: false, de, len: 0, }; let value = visitor.visit_seq(&mut seq)?; Ok((value, seq.len)) })?; self.end_sequence(len)?; Ok(value) } fn visit_mapping(&mut self, visitor: V, mark: Mark) -> Result where V: Visitor<'de>, { let (value, len) = self.recursion_check(mark, |de| { let mut map = MapAccess { empty: false, de, len: 0, key: None, }; let value = visitor.visit_map(&mut map)?; Ok((value, map.len)) })?; self.end_mapping(len)?; Ok(value) } fn end_sequence(&mut self, len: usize) -> Result<()> { let total = { let mut seq = SeqAccess { empty: false, de: self, len, }; while de::SeqAccess::next_element::(&mut seq)?.is_some() {} seq.len }; match self.next_event()? { Event::SequenceEnd | Event::Void => {} _ => panic!("expected a SequenceEnd event"), } if total == len { Ok(()) } else { struct ExpectedSeq(usize); impl Expected for ExpectedSeq { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { write!(formatter, "sequence of 1 element") } else { write!(formatter, "sequence of {} elements", self.0) } } } Err(de::Error::invalid_length(total, &ExpectedSeq(len))) } } fn end_mapping(&mut self, len: usize) -> Result<()> { let total = { let mut map = MapAccess { empty: false, de: self, len, key: None, }; while de::MapAccess::next_entry::(&mut map)?.is_some() {} map.len }; match self.next_event()? { Event::MappingEnd | Event::Void => {} _ => panic!("expected a MappingEnd event"), } if total == len { Ok(()) } else { struct ExpectedMap(usize); impl Expected for ExpectedMap { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { write!(formatter, "map containing 1 entry") } else { write!(formatter, "map containing {} entries", self.0) } } } Err(de::Error::invalid_length(total, &ExpectedMap(len))) } } fn recursion_check Result, T>( &mut self, mark: Mark, f: F, ) -> Result { let previous_depth = self.remaining_depth; self.remaining_depth = match previous_depth.checked_sub(1) { Some(depth) => depth, None => return Err(error::new(ErrorImpl::RecursionLimitExceeded(mark))), }; let result = f(self); self.remaining_depth = previous_depth; result } } struct SeqAccess<'de, 'document, 'seq> { empty: bool, de: &'seq mut DeserializerFromEvents<'de, 'document>, len: usize, } impl<'de, 'document, 'seq> de::SeqAccess<'de> for SeqAccess<'de, 'document, 'seq> { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result> where T: DeserializeSeed<'de>, { if self.empty { return Ok(None); } match self.de.peek_event()? { Event::SequenceEnd | Event::Void => Ok(None), _ => { let mut element_de = DeserializerFromEvents { document: self.de.document, pos: self.de.pos, jumpcount: self.de.jumpcount, path: Path::Seq { parent: &self.de.path, index: self.len, }, remaining_depth: self.de.remaining_depth, current_enum: None, }; self.len += 1; seed.deserialize(&mut element_de).map(Some) } } } } struct MapAccess<'de, 'document, 'map> { empty: bool, de: &'map mut DeserializerFromEvents<'de, 'document>, len: usize, key: Option<&'document [u8]>, } impl<'de, 'document, 'map> de::MapAccess<'de> for MapAccess<'de, 'document, 'map> { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result> where K: DeserializeSeed<'de>, { if self.empty { return Ok(None); } match self.de.peek_event()? { Event::MappingEnd | Event::Void => Ok(None), Event::Scalar(scalar) => { self.len += 1; self.key = Some(&scalar.value); seed.deserialize(&mut *self.de).map(Some) } _ => { self.len += 1; self.key = None; seed.deserialize(&mut *self.de).map(Some) } } } fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>, { let mut value_de = DeserializerFromEvents { document: self.de.document, pos: self.de.pos, jumpcount: self.de.jumpcount, path: if let Some(key) = self.key.and_then(|key| str::from_utf8(key).ok()) { Path::Map { parent: &self.de.path, key, } } else { Path::Unknown { parent: &self.de.path, } }, remaining_depth: self.de.remaining_depth, current_enum: None, }; seed.deserialize(&mut value_de) } } struct EnumAccess<'de, 'document, 'variant> { de: &'variant mut DeserializerFromEvents<'de, 'document>, name: Option<&'static str>, tag: &'document str, } impl<'de, 'document, 'variant> de::EnumAccess<'de> for EnumAccess<'de, 'document, 'variant> { type Error = Error; type Variant = DeserializerFromEvents<'de, 'variant>; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> where V: DeserializeSeed<'de>, { let str_de = StrDeserializer::::new(self.tag); let variant = seed.deserialize(str_de)?; let visitor = DeserializerFromEvents { document: self.de.document, pos: self.de.pos, jumpcount: self.de.jumpcount, path: self.de.path, remaining_depth: self.de.remaining_depth, current_enum: Some(CurrentEnum { name: self.name, tag: self.tag, }), }; Ok((variant, visitor)) } } impl<'de, 'document> de::VariantAccess<'de> for DeserializerFromEvents<'de, 'document> { type Error = Error; fn unit_variant(mut self) -> Result<()> { Deserialize::deserialize(&mut self) } fn newtype_variant_seed(mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { seed.deserialize(&mut self) } fn tuple_variant(mut self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { de::Deserializer::deserialize_seq(&mut self, visitor) } fn struct_variant(mut self, fields: &'static [&'static str], visitor: V) -> Result where V: Visitor<'de>, { de::Deserializer::deserialize_struct(&mut self, "", fields, visitor) } } struct UnitVariantAccess<'de, 'document, 'variant> { de: &'variant mut DeserializerFromEvents<'de, 'document>, } impl<'de, 'document, 'variant> de::EnumAccess<'de> for UnitVariantAccess<'de, 'document, 'variant> { type Error = Error; type Variant = Self; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> where V: DeserializeSeed<'de>, { Ok((seed.deserialize(&mut *self.de)?, self)) } } impl<'de, 'document, 'variant> de::VariantAccess<'de> for UnitVariantAccess<'de, 'document, 'variant> { type Error = Error; fn unit_variant(self) -> Result<()> { Ok(()) } fn newtype_variant_seed(self, _seed: T) -> Result where T: DeserializeSeed<'de>, { Err(de::Error::invalid_type( Unexpected::UnitVariant, &"newtype variant", )) } fn tuple_variant(self, _len: usize, _visitor: V) -> Result where V: Visitor<'de>, { Err(de::Error::invalid_type( Unexpected::UnitVariant, &"tuple variant", )) } fn struct_variant(self, _fields: &'static [&'static str], _visitor: V) -> Result where V: Visitor<'de>, { Err(de::Error::invalid_type( Unexpected::UnitVariant, &"struct variant", )) } } fn visit_scalar<'de, V>(visitor: V, scalar: &Scalar<'de>, tagged_already: bool) -> Result where V: Visitor<'de>, { let v = match str::from_utf8(&scalar.value) { Ok(v) => v, Err(_) => { return Err(de::Error::invalid_type( Unexpected::Bytes(&scalar.value), &visitor, )) } }; if let (Some(tag), false) = (&scalar.tag, tagged_already) { if tag == Tag::BOOL { return match parse_bool(v) { Some(v) => visitor.visit_bool(v), None => Err(de::Error::invalid_value(Unexpected::Str(v), &"a boolean")), }; } else if tag == Tag::INT { return match visit_int(visitor, v) { Ok(result) => result, Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"an integer")), }; } else if tag == Tag::FLOAT { return match parse_f64(v) { Some(v) => visitor.visit_f64(v), None => Err(de::Error::invalid_value(Unexpected::Str(v), &"a float")), }; } else if tag == Tag::NULL { return match parse_null(v.as_bytes()) { Some(()) => visitor.visit_unit(), None => Err(de::Error::invalid_value(Unexpected::Str(v), &"null")), }; } else if tag.starts_with("!") && scalar.style == ScalarStyle::Plain { return visit_untagged_scalar(visitor, v, scalar.repr, scalar.style); } } else if scalar.style == ScalarStyle::Plain { return visit_untagged_scalar(visitor, v, scalar.repr, scalar.style); } if let Some(borrowed) = parse_borrowed_str(v, scalar.repr, scalar.style) { visitor.visit_borrowed_str(borrowed) } else { visitor.visit_str(v) } } fn parse_borrowed_str<'de>( utf8_value: &str, repr: Option<&'de [u8]>, style: ScalarStyle, ) -> Option<&'de str> { let borrowed_repr = repr?; let expected_offset = match style { ScalarStyle::Plain => 0, ScalarStyle::SingleQuoted | ScalarStyle::DoubleQuoted => 1, ScalarStyle::Literal | ScalarStyle::Folded => return None, }; let expected_end = borrowed_repr.len().checked_sub(expected_offset)?; let expected_start = expected_end.checked_sub(utf8_value.len())?; let borrowed_bytes = borrowed_repr.get(expected_start..expected_end)?; if borrowed_bytes == utf8_value.as_bytes() { return Some(unsafe { str::from_utf8_unchecked(borrowed_bytes) }); } None } fn parse_null(scalar: &[u8]) -> Option<()> { match scalar { b"null" | b"Null" | b"NULL" | b"~" => Some(()), _ => None, } } fn parse_bool(scalar: &str) -> Option { match scalar { "true" | "True" | "TRUE" => Some(true), "false" | "False" | "FALSE" => Some(false), _ => None, } } fn parse_unsigned_int( scalar: &str, from_str_radix: fn(&str, radix: u32) -> Result, ) -> Option { let unpositive = scalar.strip_prefix('+').unwrap_or(scalar); if let Some(rest) = unpositive.strip_prefix("0x") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 16) { return Some(int); } } if let Some(rest) = unpositive.strip_prefix("0o") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 8) { return Some(int); } } if let Some(rest) = unpositive.strip_prefix("0b") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 2) { return Some(int); } } if unpositive.starts_with(['+', '-']) { return None; } if digits_but_not_number(scalar) { return None; } from_str_radix(unpositive, 10).ok() } fn parse_signed_int( scalar: &str, from_str_radix: fn(&str, radix: u32) -> Result, ) -> Option { let unpositive = if let Some(unpositive) = scalar.strip_prefix('+') { if unpositive.starts_with(['+', '-']) { return None; } unpositive } else { scalar }; if let Some(rest) = unpositive.strip_prefix("0x") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 16) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0x") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 16) { return Some(int); } } if let Some(rest) = unpositive.strip_prefix("0o") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 8) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0o") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 8) { return Some(int); } } if let Some(rest) = unpositive.strip_prefix("0b") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 2) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0b") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 2) { return Some(int); } } if digits_but_not_number(scalar) { return None; } from_str_radix(unpositive, 10).ok() } fn parse_negative_int( scalar: &str, from_str_radix: fn(&str, radix: u32) -> Result, ) -> Option { if let Some(rest) = scalar.strip_prefix("-0x") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 16) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0o") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 8) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0b") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 2) { return Some(int); } } if digits_but_not_number(scalar) { return None; } from_str_radix(scalar, 10).ok() } pub(crate) fn parse_f64(scalar: &str) -> Option { let unpositive = if let Some(unpositive) = scalar.strip_prefix('+') { if unpositive.starts_with(['+', '-']) { return None; } unpositive } else { scalar }; if let ".inf" | ".Inf" | ".INF" = unpositive { return Some(f64::INFINITY); } if let "-.inf" | "-.Inf" | "-.INF" = scalar { return Some(f64::NEG_INFINITY); } if let ".nan" | ".NaN" | ".NAN" = scalar { return Some(f64::NAN.copysign(1.0)); } if let Ok(float) = unpositive.parse::() { if float.is_finite() { return Some(float); } } None } pub(crate) fn digits_but_not_number(scalar: &str) -> bool { // Leading zero(s) followed by numeric characters is a string according to // the YAML 1.2 spec. https://yaml.org/spec/1.2/spec.html#id2761292 let scalar = scalar.strip_prefix(['-', '+']).unwrap_or(scalar); scalar.len() > 1 && scalar.starts_with('0') && scalar[1..].bytes().all(|b| b.is_ascii_digit()) } pub(crate) fn visit_int<'de, V>(visitor: V, v: &str) -> Result, V> where V: Visitor<'de>, { if let Some(int) = parse_unsigned_int(v, u64::from_str_radix) { return Ok(visitor.visit_u64(int)); } if let Some(int) = parse_negative_int(v, i64::from_str_radix) { return Ok(visitor.visit_i64(int)); } if let Some(int) = parse_unsigned_int(v, u128::from_str_radix) { return Ok(visitor.visit_u128(int)); } if let Some(int) = parse_negative_int(v, i128::from_str_radix) { return Ok(visitor.visit_i128(int)); } Err(visitor) } pub(crate) fn visit_untagged_scalar<'de, V>( visitor: V, v: &str, repr: Option<&'de [u8]>, style: ScalarStyle, ) -> Result where V: Visitor<'de>, { if v.is_empty() || parse_null(v.as_bytes()) == Some(()) { return visitor.visit_unit(); } if let Some(boolean) = parse_bool(v) { return visitor.visit_bool(boolean); } let visitor = match visit_int(visitor, v) { Ok(result) => return result, Err(visitor) => visitor, }; if !digits_but_not_number(v) { if let Some(float) = parse_f64(v) { return visitor.visit_f64(float); } } if let Some(borrowed) = parse_borrowed_str(v, repr, style) { visitor.visit_borrowed_str(borrowed) } else { visitor.visit_str(v) } } fn is_plain_or_tagged_literal_scalar( expected: &str, scalar: &Scalar, tagged_already: bool, ) -> bool { match (scalar.style, &scalar.tag, tagged_already) { (ScalarStyle::Plain, _, _) => true, (ScalarStyle::Literal, Some(tag), false) => tag == expected, _ => false, } } fn invalid_type(event: &Event, exp: &dyn Expected) -> Error { enum Void {} struct InvalidType<'a> { exp: &'a dyn Expected, } impl<'de, 'a> Visitor<'de> for InvalidType<'a> { type Value = Void; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.exp.fmt(formatter) } } match event { Event::Alias(_) => unreachable!(), Event::Scalar(scalar) => { let get_type = InvalidType { exp }; match visit_scalar(get_type, scalar, false) { Ok(void) => match void {}, Err(invalid_type) => invalid_type, } } Event::SequenceStart(_) => de::Error::invalid_type(Unexpected::Seq, exp), Event::MappingStart(_) => de::Error::invalid_type(Unexpected::Map, exp), Event::SequenceEnd => panic!("unexpected end of sequence"), Event::MappingEnd => panic!("unexpected end of mapping"), Event::Void => error::new(ErrorImpl::EndOfStream), } } fn parse_tag(libyaml_tag: &Option) -> Option<&str> { let mut bytes: &[u8] = libyaml_tag.as_ref()?; if let (b'!', rest) = bytes.split_first()? { if !rest.is_empty() { bytes = rest; } str::from_utf8(bytes).ok() } else { None } } impl<'de, 'document> de::Deserializer<'de> for &mut DeserializerFromEvents<'de, 'document> { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; fn enum_tag(tag: &Option, tagged_already: bool) -> Option<&str> { if tagged_already { return None; } parse_tag(tag) } loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_any(visitor), Event::Scalar(scalar) => { if let Some(tag) = enum_tag(&scalar.tag, tagged_already) { *self.pos -= 1; break visitor.visit_enum(EnumAccess { de: self, name: None, tag, }); } break visit_scalar(visitor, scalar, tagged_already); } Event::SequenceStart(sequence) => { if let Some(tag) = enum_tag(&sequence.tag, tagged_already) { *self.pos -= 1; break visitor.visit_enum(EnumAccess { de: self, name: None, tag, }); } break self.visit_sequence(visitor, mark); } Event::MappingStart(mapping) => { if let Some(tag) = enum_tag(&mapping.tag, tagged_already) { *self.pos -= 1; break visitor.visit_enum(EnumAccess { de: self, name: None, tag, }); } break self.visit_mapping(visitor, mark); } Event::SequenceEnd => panic!("unexpected end of sequence"), Event::MappingEnd => panic!("unexpected end of mapping"), Event::Void => break visitor.visit_none(), } } // The de::Error impl creates errors with unknown line and column. Fill // in the position here by looking at the current index in the input. .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_bool(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::BOOL, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(boolean) = parse_bool(value) { break visitor.visit_bool(boolean); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_i64(visitor) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_i64(visitor) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_i64(visitor) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_i64(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::INT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(int) = parse_signed_int(value, i64::from_str_radix) { break visitor.visit_i64(int); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_i128(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::INT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(int) = parse_signed_int(value, i128::from_str_radix) { break visitor.visit_i128(int); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_u64(visitor) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_u64(visitor) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_u64(visitor) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_u64(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::INT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(int) = parse_unsigned_int(value, u64::from_str_radix) { break visitor.visit_u64(int); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_u128(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::INT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(int) = parse_unsigned_int(value, u128::from_str_radix) { break visitor.visit_u128(int); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_f64(visitor) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_f64(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::FLOAT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(float) = parse_f64(value) { break visitor.visit_f64(float); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { let (next, mark) = self.next_event_mark()?; match next { Event::Scalar(scalar) => { if let Ok(v) = str::from_utf8(&scalar.value) { if let Some(borrowed) = parse_borrowed_str(v, scalar.repr, scalar.style) { visitor.visit_borrowed_str(borrowed) } else { visitor.visit_str(v) } } else { Err(invalid_type(next, &visitor)) } } Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_str(visitor), other => Err(invalid_type(other, &visitor)), } .map_err(|err: Error| error::fix_mark(err, mark, self.path)) } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_bytes(self, _visitor: V) -> Result where V: Visitor<'de>, { Err(error::new(ErrorImpl::BytesUnsupported)) } fn deserialize_byte_buf(self, _visitor: V) -> Result where V: Visitor<'de>, { Err(error::new(ErrorImpl::BytesUnsupported)) } /// Parses `null` as None and any other values as `Some(...)`. fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { let is_some = match self.peek_event()? { Event::Alias(mut pos) => { *self.pos += 1; return self.jump(&mut pos)?.deserialize_option(visitor); } Event::Scalar(scalar) => { let tagged_already = self.current_enum.is_some(); if scalar.style != ScalarStyle::Plain { true } else if let (Some(tag), false) = (&scalar.tag, tagged_already) { if tag == Tag::NULL { if let Some(()) = parse_null(&scalar.value) { false } else if let Ok(v) = str::from_utf8(&scalar.value) { return Err(de::Error::invalid_value(Unexpected::Str(v), &"null")); } else { return Err(de::Error::invalid_value( Unexpected::Bytes(&scalar.value), &"null", )); } } else { true } } else { !scalar.value.is_empty() && parse_null(&scalar.value).is_none() } } Event::SequenceStart(_) | Event::MappingStart(_) => true, Event::SequenceEnd => panic!("unexpected end of sequence"), Event::MappingEnd => panic!("unexpected end of mapping"), Event::Void => false, }; if is_some { visitor.visit_some(self) } else { *self.pos += 1; self.current_enum = None; visitor.visit_none() } } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; match next { Event::Scalar(scalar) => { let is_null = if scalar.style != ScalarStyle::Plain { false } else if let (Some(tag), false) = (&scalar.tag, tagged_already) { tag == Tag::NULL && parse_null(&scalar.value).is_some() } else { scalar.value.is_empty() || parse_null(&scalar.value).is_some() }; if is_null { visitor.visit_unit() } else if let Ok(v) = str::from_utf8(&scalar.value) { Err(de::Error::invalid_value(Unexpected::Str(v), &"null")) } else { Err(de::Error::invalid_value( Unexpected::Bytes(&scalar.value), &"null", )) } } Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_unit(visitor), Event::Void => visitor.visit_unit(), other => Err(invalid_type(other, &visitor)), } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_unit(visitor) } /// Parses a newtype struct as the underlying value. fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { let (_event, mark) = self.peek_event_mark()?; self.recursion_check(mark, |de| visitor.visit_newtype_struct(de)) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { let (next, mark) = self.next_event_mark()?; match next { Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_seq(visitor), Event::SequenceStart(_) => self.visit_sequence(visitor, mark), other => { if match other { Event::Void => true, Event::Scalar(scalar) => { scalar.value.is_empty() && scalar.style == ScalarStyle::Plain } _ => false, } { visitor.visit_seq(SeqAccess { empty: true, de: self, len: 0, }) } else { Err(invalid_type(other, &visitor)) } } } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_tuple(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_tuple_struct( self, _name: &'static str, _len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { let (next, mark) = self.next_event_mark()?; match next { Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_map(visitor), Event::MappingStart(_) => self.visit_mapping(visitor, mark), other => { if match other { Event::Void => true, Event::Scalar(scalar) => { scalar.value.is_empty() && scalar.style == ScalarStyle::Plain } _ => false, } { visitor.visit_map(MapAccess { empty: true, de: self, len: 0, key: None, }) } else { Err(invalid_type(other, &visitor)) } } } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_struct( self, _name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_map(visitor) } /// Parses an enum as a single key:value pair where the key identifies the /// variant and the value gives the content. A String will also parse correctly /// to a unit enum value. fn deserialize_enum( self, name: &'static str, variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { let (next, mark) = self.peek_event_mark()?; loop { if let Some(current_enum) = self.current_enum { if let Event::Scalar(scalar) = next { if !scalar.value.is_empty() { break visitor.visit_enum(UnitVariantAccess { de: self }); } } let message = if let Some(name) = current_enum.name { format!( "deserializing nested enum in {}::{} from YAML is not supported yet", name, current_enum.tag, ) } else { format!( "deserializing nested enum in !{} from YAML is not supported yet", current_enum.tag, ) }; break Err(error::new(ErrorImpl::Message(message, None))); } break match next { Event::Alias(mut pos) => { *self.pos += 1; self.jump(&mut pos)? .deserialize_enum(name, variants, visitor) } Event::Scalar(scalar) => { if let Some(tag) = parse_tag(&scalar.tag) { return visitor.visit_enum(EnumAccess { de: self, name: Some(name), tag, }); } visitor.visit_enum(UnitVariantAccess { de: self }) } Event::MappingStart(mapping) => { if let Some(tag) = parse_tag(&mapping.tag) { return visitor.visit_enum(EnumAccess { de: self, name: Some(name), tag, }); } let err = de::Error::invalid_type(Unexpected::Map, &"a YAML tag starting with '!'"); Err(error::fix_mark(err, mark, self.path)) } Event::SequenceStart(sequence) => { if let Some(tag) = parse_tag(&sequence.tag) { return visitor.visit_enum(EnumAccess { de: self, name: Some(name), tag, }); } let err = de::Error::invalid_type(Unexpected::Seq, &"a YAML tag starting with '!'"); Err(error::fix_mark(err, mark, self.path)) } Event::SequenceEnd => panic!("unexpected end of sequence"), Event::MappingEnd => panic!("unexpected end of mapping"), Event::Void => Err(error::new(ErrorImpl::EndOfStream)), }; } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.ignore_any()?; visitor.visit_unit() } } /// Deserialize an instance of type `T` from a string of YAML text. /// /// This conversion can fail if the structure of the Value does not match the /// structure expected by `T`, for example if `T` is a struct type but the Value /// contains something other than a YAML map. It can also fail if the structure /// is correct but `T`'s implementation of `Deserialize` decides that something /// is wrong with the data, for example required struct fields are missing from /// the YAML map or some number is too big to fit in the expected primitive /// type. pub fn from_str<'de, T>(s: &'de str) -> Result where T: Deserialize<'de>, { T::deserialize(Deserializer::from_str(s)) } /// Deserialize an instance of type `T` from an IO stream of YAML. /// /// This conversion can fail if the structure of the Value does not match the /// structure expected by `T`, for example if `T` is a struct type but the Value /// contains something other than a YAML map. It can also fail if the structure /// is correct but `T`'s implementation of `Deserialize` decides that something /// is wrong with the data, for example required struct fields are missing from /// the YAML map or some number is too big to fit in the expected primitive /// type. pub fn from_reader(rdr: R) -> Result where R: io::Read, T: DeserializeOwned, { T::deserialize(Deserializer::from_reader(rdr)) } /// Deserialize an instance of type `T` from bytes of YAML text. /// /// This conversion can fail if the structure of the Value does not match the /// structure expected by `T`, for example if `T` is a struct type but the Value /// contains something other than a YAML map. It can also fail if the structure /// is correct but `T`'s implementation of `Deserialize` decides that something /// is wrong with the data, for example required struct fields are missing from /// the YAML map or some number is too big to fit in the expected primitive /// type. pub fn from_slice<'de, T>(v: &'de [u8]) -> Result where T: Deserialize<'de>, { T::deserialize(Deserializer::from_slice(v)) }