123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- // Copyright 2022 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- use crate::values::{DictValueRef, ListValueRef, ValueSlotRef};
- use serde::de::{DeserializeSeed, Deserializer, Error, MapAccess, SeqAccess, Visitor};
- use std::convert::TryFrom;
- use std::fmt;
- /// Struct to check we're not recursing too deeply.
- #[derive(Clone)]
- struct RecursionDepthCheck(usize);
- impl RecursionDepthCheck {
- /// Recurse a level and return an error if we've recursed too far.
- fn recurse<E: Error>(&self) -> Result<RecursionDepthCheck, E> {
- match self.0.checked_sub(1) {
- Some(recursion_limit) => Ok(RecursionDepthCheck(recursion_limit)),
- None => Err(Error::custom("recursion limit exceeded")),
- }
- }
- }
- /// What type of `base::Value` container we're deserializing into.
- enum DeserializationTarget<'elem, 'container> {
- /// Deserialize into a brand new root `base::Value`.
- NewValue { slot: ValueSlotRef<'container> },
- /// Deserialize by appending to a list.
- List { list: &'elem mut ListValueRef<'container> },
- /// Deserialize by setting a dictionary key.
- Dict { dict: &'elem mut DictValueRef<'container>, key: String },
- }
- /// serde deserializer for for `base::Value`.
- ///
- /// serde is the "standard" framework for serializing and deserializing
- /// data formats in Rust. https://serde.rs/
- ///
- /// This implements both the Visitor and Deserialize roles described
- /// here: https://serde.rs/impl-deserialize.html
- ///
- /// One note, though. Normally serde instantiates a new object. The design
- /// of `base::Value` is that each sub-value (e.g. a list like this)
- /// needs to be deserialized into the parent value, which is pre-existing.
- /// To achieve this we use a feature of serde called 'stateful deserialization'
- /// (see https://docs.serde.rs/serde/de/trait.DeserializeSeed.html)
- ///
- /// This struct stores that state.
- ///
- /// Handily, this also enables us to store the desired recursion limit.
- ///
- /// We use runtime dispatch (matching on an enum) to deserialize into a
- /// dictionary, list, etc. This may be slower than having three different
- /// `Visitor` implementations, where everything would be monomorphized
- /// and would probably disappear with inlining, but for now this is much
- /// less code.
- pub struct ValueVisitor<'elem, 'container> {
- container: DeserializationTarget<'elem, 'container>,
- recursion_depth_check: RecursionDepthCheck,
- }
- impl<'elem, 'container> ValueVisitor<'elem, 'container> {
- /// Constructor - pass in an existing slot that can store a new
- /// `base::Value`, then this visitor can be passed to serde deserialization
- /// libraries to populate it with a tree of contents.
- /// Any existing `base::Value` in the slot will be replaced.
- pub fn new(slot: ValueSlotRef<'container>, mut max_depth: usize) -> Self {
- max_depth += 1; // we will increment this counter when deserializing
- // the initial `base::Value`. To match C++ behavior, we should
- // only start counting for subsequent layers, hence decrement
- // now.
- Self {
- container: DeserializationTarget::NewValue { slot },
- recursion_depth_check: RecursionDepthCheck(max_depth),
- }
- }
- }
- impl<'de, 'elem, 'container> Visitor<'de> for ValueVisitor<'elem, 'container> {
- // Because we are deserializing into a pre-existing object.
- type Value = ();
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("any valid JSON")
- }
- fn visit_i32<E: serde::de::Error>(self, value: i32) -> Result<Self::Value, E> {
- match self.container {
- DeserializationTarget::NewValue { mut slot } => slot.construct_integer(value),
- DeserializationTarget::List { list } => list.append_integer(value),
- DeserializationTarget::Dict { dict, key } => dict.set_integer_key(&key, value),
- };
- Ok(())
- }
- fn visit_i8<E: serde::de::Error>(self, value: i8) -> Result<Self::Value, E> {
- self.visit_i32(value as i32)
- }
- fn visit_bool<E: serde::de::Error>(self, value: bool) -> Result<Self::Value, E> {
- match self.container {
- DeserializationTarget::NewValue { mut slot } => slot.construct_bool(value),
- DeserializationTarget::List { list } => list.append_bool(value),
- DeserializationTarget::Dict { dict, key } => dict.set_bool_key(&key, value),
- };
- Ok(())
- }
- fn visit_i64<E: serde::de::Error>(self, value: i64) -> Result<Self::Value, E> {
- // Here we match the behavior of the Chromium C++ JSON parser,
- // which will attempt to create an integer base::Value but will
- // overflow into a double if needs be.
- // (See JSONParser::ConsumeNumber in json_parser.cc for equivalent,
- // and json_reader_unittest.cc LargerIntIsLossy for a related test).
- match i32::try_from(value) {
- Ok(value) => self.visit_i32(value),
- Err(_) => self.visit_f64(value as f64),
- }
- }
- fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
- // See visit_i64 comment.
- match i32::try_from(value) {
- Ok(value) => self.visit_i32(value),
- Err(_) => self.visit_f64(value as f64),
- }
- }
- fn visit_f64<E: serde::de::Error>(self, value: f64) -> Result<Self::Value, E> {
- match self.container {
- DeserializationTarget::NewValue { mut slot } => slot.construct_double(value),
- DeserializationTarget::List { list } => list.append_double(value),
- DeserializationTarget::Dict { dict, key } => dict.set_double_key(&key, value),
- };
- Ok(())
- }
- fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
- match self.container {
- DeserializationTarget::NewValue { mut slot } => slot.construct_string(value),
- DeserializationTarget::List { list } => list.append_string(value),
- DeserializationTarget::Dict { dict, key } => dict.set_string_key(&key, value),
- };
- Ok(())
- }
- fn visit_borrowed_str<E: serde::de::Error>(self, value: &'de str) -> Result<Self::Value, E> {
- match self.container {
- DeserializationTarget::NewValue { mut slot } => slot.construct_string(value),
- DeserializationTarget::List { list } => list.append_string(value),
- DeserializationTarget::Dict { dict, key } => dict.set_string_key(&key, value),
- };
- Ok(())
- }
- fn visit_string<E: serde::de::Error>(self, value: String) -> Result<Self::Value, E> {
- self.visit_str(&value)
- }
- fn visit_none<E: serde::de::Error>(self) -> Result<Self::Value, E> {
- match self.container {
- DeserializationTarget::NewValue { mut slot } => slot.construct_none(),
- DeserializationTarget::List { list } => list.append_none(),
- DeserializationTarget::Dict { dict, key } => dict.set_none_key(&key),
- };
- Ok(())
- }
- fn visit_unit<E: serde::de::Error>(self) -> Result<Self::Value, E> {
- self.visit_none()
- }
- fn visit_map<M>(mut self, mut access: M) -> Result<Self::Value, M::Error>
- where
- M: MapAccess<'de>,
- {
- let mut value = match self.container {
- DeserializationTarget::NewValue { ref mut slot } => slot.construct_dict(),
- DeserializationTarget::List { list } => list.append_dict(),
- DeserializationTarget::Dict { dict, key } => dict.set_dict_key(&key),
- };
- // If it were exposed by values.h, we could use access.size_hint()
- // to give a clue to the C++ about the size of the desired map.
- while let Some(key) = access.next_key::<String>()? {
- access.next_value_seed(ValueVisitor {
- container: DeserializationTarget::Dict { dict: &mut value, key },
- recursion_depth_check: self.recursion_depth_check.recurse()?,
- })?;
- }
- Ok(())
- }
- fn visit_seq<S>(mut self, mut access: S) -> Result<Self::Value, S::Error>
- where
- S: SeqAccess<'de>,
- {
- let mut value = match self.container {
- DeserializationTarget::NewValue { ref mut slot } => slot.construct_list(),
- DeserializationTarget::List { list } => list.append_list(),
- DeserializationTarget::Dict { dict, key } => dict.set_list_key(&key),
- };
- if let Some(size_hint) = access.size_hint() {
- value.reserve_size(size_hint);
- }
- while let Some(_) = access.next_element_seed(ValueVisitor {
- container: DeserializationTarget::List { list: &mut value },
- recursion_depth_check: self.recursion_depth_check.recurse()?,
- })? {}
- Ok(())
- }
- }
- impl<'de, 'elem, 'container> DeserializeSeed<'de> for ValueVisitor<'elem, 'container> {
- // Because we are deserializing into a pre-existing object.
- type Value = ();
- fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: Deserializer<'de>,
- {
- deserializer.deserialize_any(self)
- }
- }
|