dyn-inventory-0.1.0 has been yanked.
dyn-inventory
proc macro for building runtime plugin registries using dyn-compatible traits and the inventory crate.
this crate generates code to:
- register plugins that implement a trait object (
dyn trait) - carry typed metadata alongside each plugin
- collect and instantiate all registered plugins at runtime
use dyn_inventory;
dyn_inventory!
Why dyn-compatible traits
the plugins produced by this crate are stored and used as Box<dyn Trait>. when used with inventory, this allows for new plugin registries to be developed for decentralized libraries and frameworks.
Quick Start
- add dependencies:
[]
= "0.3"
= "0.1"
- define a trait that is dyn-compatible:
- declare your inventory using the
dyn_inventory!proc macro:
dyn_inventory!;
[!TIP] what this generates:
- a struct
GreeterPlugin<T>with the fields you declared- an implementation
impl<T> GreeterPlugin<T> { pub const fn new(...) -> Self }- an inventory registration type
inventory::collect!(GreeterPlugin<fn() -> Box<dyn Greeter>>)- a macro
register_greeter!(snake_case of the struct name by default) to register plugins- a collector
GreeterPluginCollectorthat haspluginof typeVec<GreeterPlugin<Box<dyn Greeter>>>
- register a plugin somewhere in your code (could be another crate that depends on your trait crate):
use crate::;
// this expands to a unit struct named `MyGreeter` and registers it into the inventory
register_greeter!
// you implement the trait for the generated unit struct
- collect your plugins at runtime:
let collected = new;
for plugin in collected.plugins
Macro Syntax
use dyn_inventory;
dyn_inventory!;
Extra Parameters
two extra params are currently accepted:
macro_name = ident- sets the name of the generated registration macro. by default it is the snake_case of
StructName(for example,GreeterPlugin->greeter_plugin).
- sets the name of the generated registration macro. by default it is the snake_case of
handle_name = Ident- sets the name of the generated handle which implements your plugin. (for example,
handle_name = TheImplrequiresimpl GreeterPlugin for TheImpl)
- sets the name of the generated handle which implements your plugin. (for example,
advanced: customizing collection
the collector type is named by appending Collector to your struct name. it exposes:
new()-> builds the collection without modificationnew_with(|item: &mut StructName<fn() -> Box<dyn TraitName>>| {...})-> allows you to mutate the raw entries before they are instantiated intoBox<dyn TraitName>
limitations
- your trait must be object-safe (dyn-compatible)
- the
inventorycrate must be linked into the final binary; ensure your plugin crates depend oninventoryand your main binary pulls in the crates that perform registrations