flense
Purpose-oriented lensing for Rust.
State
This is not production ready and should not be relied on. The tests pass under miri, but no thorough deep validation of the pointers and logic has been performed that would give a high degree of confidence. Stacked borrows are hard.
High-level
Rather than focusing on accessing specific fields of specific structures, flense allows a sort of duck-typing for lenses, where you annotate purpose-oriented fields like Position or Color (or whatever you please!), then define how to adapt the data inside your structure into flense.
Other lensing libraries can only lense the original structure and its original fields. You can still achieve that with flense by creating a specialized Field for each specific structure field.
Invalid mutable lenses which alias data should be prevented at compile time, though cargo check may fail to find them when cargo build does.
Properties
Creating a lens is simple: some_data.lens(). Type inference drives the creation of the correct lens. A future goal is the creation of a derive macro which can help remove the need to manually specify adapter implementations, though they will always be possible to implement on any type.
This crate should largely compile out and be zero overhead. Functions taking reified lenses have a small performance overhead since the size of a lens is dependent on the number of fields in it.
Examples
use *;
// Some common fields you might wish to use. Maybe you're creating lenses for
// different data structures that might store position in other locations inside
// themselves, or your library wants to access something that is semantically a
// position but to use user-provided data types in processing without requiring
// allocations and transformations back and forth.
// A plain old data type, defined anywhere - if it was defined outside your lib,
// you could wrap it in a #[repr(transparent)] wrapper and pierce through it.
// Fundamentally, the safety constraint on `Adapter` is: you must provide the
// offset, in bytes, from the beginning of the structure to the adapted field,
// which must be the exact type that is defined in the `Field`.
// In the future, a derive macro might allow annotating structure fields with
// `Field` to derive the correct offset automatically.
unsafe
unsafe
unsafe
// You can also implement reflexive Adapters; a blanket implementation cannot be
// provided as it would prevent other implementations, since a Field implemented
// remotely could change its type.
// In the future, a derive macro might provide this functionality.
unsafe
// Somewhere else, possibly even provided in a library which is unaware of the
// concrete Vertex definition entirely.
// Or, you can avoid performing code generation of the body multiple times by
// separating the lens construction from its usage, though this may prevent
// optimizations like vectorization.
use *;
unsafe
unsafe
unsafe
unsafe
// hacky drag for the velocities via linear decay
// positions is guaranteed to be rectangular, so you don't have to worry about
// one slice being longer or shorter than the other
// or you can take multiple lenses for more flexibility
Prior art, other lenses
flense was heavily inspired by some work I've done in creating a sound wrapper for meshoptimizer (which will eventually be published). In doing so, I explored concepts used in terrors and frunk.
grist_lensis another lens library which I saw the announcement of a few days before separating this one from mymeshoptimizerwrapper, though I haven't used it. I did, however, read the author's blog post going over the various lens options she has seen and used.lens-rspl-lens