diff options
Diffstat (limited to 'src/type_tree.rs')
-rw-r--r-- | src/type_tree.rs | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/type_tree.rs b/src/type_tree.rs new file mode 100644 index 0000000..8e8098b --- /dev/null +++ b/src/type_tree.rs @@ -0,0 +1,70 @@ +// Copyright (C) 2021-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. +//! +//! Type trees are pretty flexible. Consider the following example: +//! +//! ``` +//! struct Foo { +//! bar: Vec<u32>, +//! } +//! +//! 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<u32>, +//! } +//! +//! 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`! + +// TODO |