mod id; mod tag; #[cfg(test)] mod tests; mod value;
/// The RON deserializer. /// /// If you just want to simply deserialize a value, /// you can use the [`from_str`] convenience function. pubstruct Deserializer<'de> { pub(crate) parser: Parser<'de>,
newtype_variant: bool,
serde_content_newtype: bool,
last_identifier: Option<&'de str>,
recursion_limit: Option<usize>,
}
impl<'de> Deserializer<'de> { // Cannot implement trait here since output is tied to input lifetime 'de. #[allow(clippy::should_implement_trait)] pubfn from_str(input: &'de str) -> SpannedResult<Self> { Self::from_str_with_options(input, &Options::default())
}
// FIXME: panic is not actually possible, remove once utf8_chunks is stabilized #[allow(clippy::missing_panics_doc)] pubfn from_bytes_with_options(input: &'de [u8], options: &Options) -> SpannedResult<Self> { let err = match str::from_utf8(input) {
Ok(input) => returnSelf::from_str_with_options(input, options),
Err(err) => err,
};
// FIXME: use [`utf8_chunks`](https://github.com/rust-lang/rust/issues/99543) once stabilised #[allow(clippy::expect_used)] let valid_input =
str::from_utf8(&input[..err.valid_up_to()]).expect("source is valid up to error");
/// A convenience function for building a deserializer /// and deserializing a value of type `T` from a reader. #[cfg(feature = "std")] pubfn from_reader<R, T>(rdr: R) -> SpannedResult<T> where
R: io::Read,
T: de::DeserializeOwned,
{
Options::default().from_reader(rdr)
}
/// A convenience function for building a deserializer /// and deserializing a value of type `T` from a string. pubfn from_str<'a, T>(s: &'a str) -> SpannedResult<T> where
T: de::Deserialize<'a>,
{
Options::default().from_str(s)
}
/// A convenience function for building a deserializer /// and deserializing a value of type `T` from bytes. pubfn from_bytes<'a, T>(s: &'a [u8]) -> SpannedResult<T> where
T: de::Deserialize<'a>,
{
Options::default().from_bytes(s)
}
/// Called from [`deserialize_any`][serde::Deserializer::deserialize_any] /// when a struct was detected. Decides if there is a unit, tuple or usual /// struct and deserializes it accordingly. /// /// This method assumes there is no identifier left. fn handle_any_struct<V>(&mutself, visitor: V, ident: Option<&str>) -> Result<V::Value> where
V: Visitor<'de>,
{ // HACK: switch to JSON enum semantics for JSON content // Robust impl blocked on https://github.com/serde-rs/serde/issues/1183 let is_serde_content =
is_serde_content::<V::Value>() || is_serde_tag_or_content::<V::Value>();
let old_serde_content_newtype = self.serde_content_newtype; self.serde_content_newtype = false;
match ( self.parser.check_struct_type(
NewtypeMode::NoParensMeanUnit, if old_serde_content_newtype {
TupleMode::DifferentiateNewtype // separate match on NewtypeOrTuple below
} else {
TupleMode::ImpreciseTupleOrNewtype // Tuple and NewtypeOrTuple match equally
},
)?,
ident,
) {
(StructType::Unit, Some(ident)) if is_serde_content => { // serde's Content type needs the ident for unit variants
visitor.visit_str(ident)
}
(StructType::Unit, _) => visitor.visit_unit(),
(_, Some(ident)) if is_serde_content => { // serde's Content type uses a singleton map encoding for enums
visitor.visit_map(SerdeEnumContent {
de: self,
ident: Some(ident),
})
}
(StructType::Named, _) => { // giving no name results in worse errors but is necessary here self.handle_struct_after_name("", visitor)
}
(StructType::NewtypeTuple, _) if old_serde_content_newtype => { // deserialize a newtype struct or variant self.parser.consume_char('('); self.parser.skip_ws()?; let result = self.deserialize_any(visitor); self.parser.skip_ws()?; self.parser.consume_char(')');
result
}
(
StructType::AnyTuple
| StructType::EmptyTuple
| StructType::NewtypeTuple
| StructType::NonNewtypeTuple,
_,
) => { // first argument is technically incorrect, but ignored anyway self.deserialize_tuple(0, visitor)
}
}
}
/// Called from /// [`deserialize_struct`][serde::Deserializer::deserialize_struct], /// [`struct_variant`][serde::de::VariantAccess::struct_variant], and /// [`handle_any_struct`][Self::handle_any_struct]. Handles /// deserialising the enclosing parentheses and everything in between. /// /// This method assumes there is no struct name identifier left. fn handle_struct_after_name<V>(
&mutself,
name_for_pretty_errors_only: &'static str,
visitor: V,
) -> Result<V::Value> where
V: Visitor<'de>,
{ ifself.newtype_variant || self.parser.consume_char('(') { let old_newtype_variant = self.newtype_variant; self.newtype_variant = false;
let value = guard_recursion! { self =>
visitor
.visit_map(CommaSeparated::new(Terminator::Struct, self))
.map_err(|err| {
struct_error_name(
err, if !old_newtype_variant && !name_for_pretty_errors_only.is_empty() {
Some(name_for_pretty_errors_only)
} else {
None
},
)
})?
};
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value> where
V: Visitor<'de>,
{ ifself.newtype_variant { ifself.parser.check_char(')') { // newtype variant wraps the unit type / a unit struct without name returnself.deserialize_unit(visitor);
}
#[allow(clippy::wildcard_in_or_patterns)] matchself
.parser
.check_struct_type(NewtypeMode::InsideNewtype, TupleMode::DifferentiateNewtype)?
{
StructType::Named => { // newtype variant wraps a named struct // giving no name results in worse errors but is necessary here returnself.handle_struct_after_name("", visitor);
}
StructType::EmptyTuple | StructType::NonNewtypeTuple => { // newtype variant wraps a tuple (struct) // first argument is technically incorrect, but ignored anyway returnself.deserialize_tuple(0, visitor);
} // StructType::Unit is impossible with NewtypeMode::InsideNewtype // StructType::AnyTuple is impossible with TupleMode::DifferentiateNewtype
StructType::NewtypeTuple | _ => { // continue as usual with the inner content of the newtype variant self.newtype_variant = false;
}
}
}
// In Serde, unit means an anonymous value containing no data. fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value> where
V: Visitor<'de>,
{ ifself.newtype_variant || self.parser.consume_str("()") { self.newtype_variant = false;
self.deserialize_tuple(len, visitor).map_err(|e| match e {
Error::ExpectedStructLike if !name.is_empty() => Error::ExpectedNamedStructLike(name),
e => e,
})
}
match ( self.had_comma,
!self.de.parser.check_char(self.terminator.as_char()),
) { // Trailing comma, maybe has a next element
(true, has_element) => Ok(has_element), // No trailing comma but terminator
(false, false) => Ok(false), // No trailing comma or terminator
(false, true) => Err(Error::ExpectedComma),
}
}
}
impl<'de, 'a> de::SeqAccess<'de> for CommaSeparated<'a, 'de> { type Error = Error;
fn next_element_seed<T>(&mutself, seed: T) -> Result<Option<T::Value>> where
T: DeserializeSeed<'de>,
{ ifself.has_element()? { let res = guard_recursion! { self.de => seed.deserialize(&mut *self.de)? };
self.had_comma = self.de.parser.comma()?;
Ok(Some(res))
} else {
Ok(None)
}
}
}
impl<'de, 'a> de::MapAccess<'de> for CommaSeparated<'a, 'de> { type Error = Error;
let old_serde_content_newtype = self.de.serde_content_newtype; self.de.serde_content_newtype = true; let result = seed.deserialize(&mut *self.de); self.de.serde_content_newtype = old_serde_content_newtype;
result
}
}
fn is_serde_content<T>() -> bool { #[derive(serde_derive::Deserialize)] enum A {} type B = A;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.