TypeSift
A Rust derive macro that walks structs, enums, collections and maps to collect every value of a given type.
Usage
use TypeSift;
;
let group = Group ;
// Get references to all values of type `UserId` inside of `group`
let user_ids = group.;
assert_eq!;
Motivation
Big API responses tend to be graphs of DTOs that point at other resources by id. Before responding you want those resources loaded. Collecting the ids normally means a function that walks every field by hand, and that function may quietly go stale when a new field is added.
Typesift reduces the amount of code that needs to be written and eliminates this concern.
Integration with third-party crates
If you don't own a type, the orphan rule stops it from implementing the trait.
Feature flags
Support for types from some popular crates can be enabled with the corresponding crate feature: bytes, chrono, enum-map, http, indexmap, rust_decimal, serde_json, smallvec, time, url, uuid.
Example:
= { = "0.1", = ["uuid"] }
Typesift attributes
If the crate you're interested in is not supported, typesift offers you the following macro attributes to overcome the issue:
#[typesift(leaf)]finds the field but doesn't look inside it. This is what you want for ids, timestamps and other opaque values.#[typesift(skip)]leaves it out of the search entirely. Also the escape hatch forRefCell,Mutexand friends, which can't lend out their contents for as long as the search needs them.#[typesift(with = path)]hands the field to a function of yours, which decides what the search sees and in what order.
Limitations
Everything involved has to be 'static, so the derive rejects types with lifetime parameters, though &'static T fields are fine.
Interior mutability isn't supported; skip those fields.
Benchmarks
Run benchmarks with just bench.
| variant | time | vs baseline |
|---|---|---|
manual_collector (baseline) |
3.82 µs | - |
typesift |
5.48 µs | 1.43x slower |
manual_iterator |
31.78 µs | 8.3x slower |
manual_collectorwalks the fields by hand and pushes into aVec, which is about as fast as this gets.TypeSiftcosts roughly 1.4x of thatmanual_iteratoris the same walk written as a chain ofimpl Iterators, which is what most people reach for.
License
MIT © Serhii Potapov