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_fieldto 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 appropriatePortion. (We must store the value as aserde_value::Valuesince we don’t know what type it should be, and can’t know until we are ready to enter T and U’sDeserializeimpls.) - 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
TandU, 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
TandU’s deserialisation, discard the partially-deserialisedTandUand restart them each time (with cloned copies of theValues). This is O(n^2) and involves much boxing.
§References
-
Tickets against
serde-ignored: https://github.com/dtolnay/serde-ignored/issues/17 https://github.com/dtolnay/serde-ignored/issues/10 -
Workaround with
HashMapthat doesn’t quite work right: https://github.com/dtolnay/serde-ignored/issues/10#issuecomment-1044058310 https://github.com/serde-rs/serde/issues/2176 -
Discussion in Tor Project gitlab re Arti configuration: https://gitlab.torproject.org/tpo/core/arti/-/merge_requests/1599#note_2944510
Re-exports§
pub use derive_deftly_template_Flattenable;
Macros§
- call_
any 🔒 - Implement
deserialize_$whatas a call todeserialize_any. - call_
any_ 🔒for_ rest - Implement most
deserialize_*as calls todeserialize_any. - derive_
deftly_ 🔒driver_ Flatten
Structs§
- Field
Extractor 🔒 - Stunt “data format” which we use for extracting fields for derived
Flattenableimpls - Field
Extractor 🔒Success - Error resulting from successful operation of a
FieldExtractor - Flatten
- Helper for flattening deserialisation, compatible with
serde_ignored - Flatten
Visitor 🔒 de::VisitorforFlatten- Key 🔒
- Wrapper for a field name, impls
de::Deserializer - Portion 🔒
- The keys and values we are to direct to a particular child
Traits§
- Flattenable
- Types that can be used with
Flatten
Functions§
- flattenable_
extract_ fields - Extract fields of a struct, as viewed by
serde
Type Aliases§
- Field
List 🔒 - List of fields, appears in several APIs here
- Flatten
Error 🔒 - Type alias for reified error