Crates.io | traitreg-macros |
lib.rs | traitreg-macros |
version | 0.3.0 |
source | src |
created_at | 2024-09-05 13:47:21.884476 |
updated_at | 2024-09-06 13:42:06.669818 |
description | Create a registry of implementations of a trait |
homepage | https://github.com/m4c-ro/traitreg |
repository | https://github.com/m4c-ro/traitreg |
max_upload_size | |
id | 1364636 |
size | 13,606 |
Create a registry of implementations of a trait. Useful for all kinds of metaprogramming, but in particular can be used for:
Register a trait implementation
trait MyTrait {}
struct MyType;
#[traitreg::register]
impl MyTrait for MyType {}
Optionally: register with a constructor
trait MyTrait {}
#[derive(Default)]
struct MyType;
#[traitreg::register(default)]
impl MyTrait for MyType {}
struct MyOtherType;
impl MyOtherType {
fn new() -> Self { Self }
}
#[traitreg::register(new)]
impl MyTrait for MyOtherType {}
Build a static registry of all registered trait implementations.
#[traitreg::registry(MyTrait)]
static MYTRAIT_REGISTRY: () = ();
Access registry contents.
// Enumerate impls
for reg in MYTRAIT_REGISTRY.iter() {
println!("{reg:#?}");
// Instanciate
let instance: Option<Box<dyn MyTrait>> = reg.instanciate();
}
The registry is built during startup by methods called by the linker, before main()
is
called. This approach is very much platform dependent but avoids issues with other approaches
which run at compile-time but are unsound.
Notably multiple crates (i.e. compilation units) can register implementations independently,
the registry will pick up all of the impls automatically at runtime. This can be useful for a
plugin system where shared libraries (cdylib
crates) are loaded. Currently loading shared
libraries manually after main()
is called will not update the registry.
It is possible to build a registry like this purely at compile time using procedural macros but as far as I am aware this is unsound. Each proc macro invocation currently reuses the same proc-macro executable in-memory without reloading it, so state can be persisted in static memory, but storing state across several independent macro calls is not supported by rustc and this behaviour may break in the future.