// Copyright (C) 2022 Soni L. // SPDX-License-Identifier: MIT OR Apache-2.0 //! Type Tree support. //! //! Type Trees are a Datafu feature for extracting types from a `serde`-based //! `Deserialize` in such a way that it can be used with Datafu patterns. //! //! They work by matching the `Deserialize` against some data, with the help of //! `serde_transmute`. Datafu then collects the relevant `Deserialize` calls, //! and uses them to infer an appropriate type tree for dynamic //! deserialization. //! //! When introspecting the `Deserialize`, all matching parts are extracted, and //! non-matching parts are ignored. Even if an error occurs, Datafu will gladly //! infer a type tree for what it could match. //! //! For example, given a struct and the corresponding data: //! //! ``` //! struct Foo { //! bar: i32, //! } //! //! let data = Foo { bar: 0 }; //! ``` //! //! Building a type tree will first inspect the struct like so: //! //! 1. call `deserialize()` on `Foo`. //! 2. inspect the `deserialize_struct` from `Foo`, storing the name and //! fields. //! 3. give `Foo` the appropriate visitor (from `data`), through //! `serde_transmute`. //! 4. inspect the `deserialize_i32` etc, also storing those. //! //! The resulting type tree can then be used in any pattern to effectively //! match a `Foo`, but more efficiently than with a predicate. Another big //! difference between predicates and type trees is how predicates are eager, //! and can consume values that would otherwise be matched by the rest of a //! pattern, like `IgnoredAny`. //! //! Type trees are pretty flexible. Consider the following example: //! //! ``` //! struct Foo { //! bar: Vec, //! } //! //! let data = Foo { bar: vec![1, 2, 3] }; //! ``` //! //! This will actually produce a type tree which checks that the first 3 items //! are `u32`! Further, when using different types for the predicate and the //! data, you can get even more flexiblity. For example, with the following //! struct and data: //! //! ``` //! struct Foo { //! bar: Vec, //! } //! //! let data = (); //! ``` //! //! Datafu will actually inspect the `deserialize_struct`, and then the //! struct visitor will error. But despite the error, it'll still create a type //! tree for the `deserialize_struct`! // use serde::Deserializer; // /// A deserializer which attempts to fill in a type tree. // struct TypeTreeDeserializer<'tt, D> { // inner: D, // tt: &'tt mut TypeTreeNode, // } /// A Type Tree entry type. /// /// This represents a type to be deserialized with Serde, with everything that /// comes with that. It supports the 29 core Serde types, and 2 self-describing /// ones. #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub enum TypeTreeType { /// An open type, which can be anything. /// /// This represents [`Deserializer::deserialize_any`]. #[default] Any, /// A type for a value which will be ignored. /// /// This represents [`Deserializer::deserialize_ignored_any`]. IgnoredAny, Bool, } /// A node of a type tree. #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub struct TypeTreeNode { /// The type to be requested for this node. pub node_type: TypeTreeType, /// The types for when this node is an enum. pub enum_nodes: (), // TODO /// The types for when this node is a map. pub map_nodes: (), // TODO /// The types for when this node is a seq. pub seq_nodes: (), // TODO /// The type for when this node is a some. pub some_node: Option>, /// The type for when this node is a newtype struct. pub newtype_node: Option>, }