Module tor_config::flatten

source ·
Expand description

Similar to #[serde(flatten)] but works with serde_ignored

Our approach to deserialize a Flatten is as follows:

  • We tell the input data format (underlying deserializer) that we want a map.
  • In our visitor, we visit each key in the map in order
  • For each key, we consult Flattenable::has_field to find out which child it’s in (fields in T shadow fields in U, as with serde), and store the key and the value in the appropriate Portion. (We must store the value as a serde_value::Value since we don’t know what type it should be, and can’t know until we are ready to enter T and U’s Deserialize impls.)
  • If it’s in neither T nor U, we explicitly ignore the value
  • When we’ve processed all the fields, we call the actual deserialisers for T and U: we take on the role of the data format, giving each of T and U a map.

From the point of view of T and U, we each offer them a subset of the fields, having already rendered the keys to strings and the values to Value.

From the point of view of the data format (which might be a serde_ignored proxy) we consume the union of the fields, and ignore the rest.

§Rationale and alternatives

The key difficulty is this: we want to call Deserializer::deserialize_ignored_any on our input data format for precisely the fields which neither T nor U want. We must achieve this somehow using information from T or U. If we tried to use only the Deserialize impls, the only way to detect this is to call their deserialize methods and watch to see if they in turn call deserialize_ignored_any. But we need to be asking each of T and U this question for each field: the shape of MapAccess puts the data structure in charge of sequencing. So we would need to somehow suspend T’s deserialisation, and call U’s, and then suspend Us, and go back to T.

Other possibilities that seemed worse:

  • Use threads. We could spawn a thread for each of T and U, allowing us to run them in parallel and control their execution flow.

  • Use coroutines eg. corosensei (by Amanieu, author of hashbrown etc.)

  • Instead of suspending and restarting T and U’s deserialisation, discard the partially-deserialised T and U and restart them each time (with cloned copies of the Values). This is O(n^2) and involves much boxing.

§References

Macros§

Structs§

Traits§

Functions§

Type Aliases§

  • FieldList 🔒
    List of fields, appears in several APIs here
  • Type alias for reified error