| Crates.io | hv-alchemy |
| lib.rs | hv-alchemy |
| version | 0.1.0 |
| created_at | 2021-11-12 21:43:00.347694+00 |
| updated_at | 2021-11-12 21:43:00.347694+00 |
| description | Heavy Alchemy - the black arts of transmutation, wrapped for your safe usage and enjoyment |
| homepage | |
| repository | https://github.com/sdleffler/hv-dev |
| max_upload_size | |
| id | 481135 |
| size | 53,174 |
hv-alchemy is a set of traits and types which maintain a global runtime registry (static is not
possible at the moment, but the linkme crate might come into play at some point) of trait object
vtables and other type info such as sizes, alignments, destructors, and more. It requires Rust
nightly for the ptr_metadata, unsize, and arbitrary_self_types features.
A few of the things this crate allows you to do:
dyn AlchemicalAny to a concrete sized type Tdyn AlchemicalAny to an unsized trait object type dyn TraitCopy and Clone bounds (requiring runtime-registered
Copy and Clone implementations)Send, Sync, Copy, and Clone constraints which can be used during compile-time and
are conditionally accessed during run-time, for specializing behavior according to traits some
type implementsTypeTable (vtable registry) for any applicable type at any time with any trait it is
statically known to implementType<T> to Box<dyn AlchemicalAny> or any other trait you
implement for itDefault::default function pointer item as a fn() -> T for some type which
implements Default (checking at runtime and without a compile-time Default bound)*const dyn AlchemicalAny, try to clone it into a fresh allocation using the Layout
stored in the type table provided by dyn AlchemicalAnyPlease use irresponsibly. hv-alchemy is no_std compatible, but requires alloc.
We cannot currently at compile-time register all the different things that some type implements w/
the Alchemy registry. As such you basically have to supply some kind of hook in your APIs (if you're
relying on Alchemy) which encourages/provides a way to add relevant trait objects to the
TypeTables you're interested in. Something like linkme or the currently broken inventory crate
are capable of doing something somewhat like this but they cannot universally quantify over types,
as that would require monomorphizing a forall T. bound into a bunch of
Type::<T>::of().add::<...>() calls, and for very good reasons which may or may not be obvious to
you, Rust currently has no way to do this.
Alchemy keeps a global static HashMap of TypeIds to &'static TypeTables, which are created
through Box::leak (at some point this might be switched to a global Bump arena or similar.)
These TypeTables contain again, HashMaps of TypeId to &'static DynVtables; a DynVtable
represents the vtable of some trait object dyn SomeTrait for some type SomeType. Specifically,
if you want to see if some object implements fmt::Debug, Alchemy lookups go something like this:
TypeTable of the object. If we're trying to dyncast a trait object dyn AlchemicalAny,
it's as easy as calling the .type_table() method. Otherwise, we could use Type::<T>::of(), if
know T statically (and just don't want a static fmt::Debug bound.)
Type::<T>::of(), Alchemy takes the TypeId of T and uses it to look for its
TypeTable in the global registry. If it's not there, it creates an empty one.TypeId of dyn fmt::Debug, and use that to look for the corresponding DynVtable in
the vtables map of the TypeTable.DynVtable there, we know by invariants that its implementor type will be the type
of the thing we're trying to check, and that its trait object type will be dyn fmt::Debug. We
can then assume it is safe to use DynVtable::to_dyn_object_pointer on our original
reference/value to convert it to an &dyn fmt::Debug. Or if all we wanted to know was whether it
did implement Debug, we have our answer.Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.