Expand description
§steckrs
A lightweight, trait-based plugin system for Rust applications and libraries.
§What is steckrs?
“steckrs” is a wordplay combining the German word “Stecker” (meaning “plug” or “connector”) and the Rust file extension (.rs). The library provides a flexible, type-safe plugin architecture for Rust applications, allowing developers to:
- Define extension points in their applications
- Create plugins that integrate with these extension points
- Dynamically manage plugins (loading, enabling, disabling, unloading)
- Register and invoke hooks with proper type safety
§Core Concepts
§Extension Points
Extension points define interfaces where plugins can add functionality. Each extension point:
- Is defined as a trait that plugins implement
- Specifies the contract that plugins must fulfill
- Provides type-safe interaction between the core application and plugins
§Plugins
Plugins are self-contained modules that implement functionality for extension points. Each plugin:
- Has a unique identifier
- Can be enabled or disabled at runtime
- Can register multiple hooks to different extension points
- Has lifecycle methods (
on_load
,on_unload
)
§Hooks
Hooks are implementations of extension points that plugins register. They:
- Implement the trait defined by an extension point
- Are invoked when the application calls that extension point
- Can be uniquely identified by their plugin ID, extension point, and optional discriminator
§Logs
This library logs certain events with the tracing
library.
§Usage Example
Here’s a simple example of how to use steckrs to create a plugin-enabled application:
use steckrs::{extension_point, simple_plugin, PluginManager};
// Define an extension point
extension_point!(
GreeterExtension: GreeterTrait;
fn greet(&self, name: &str) -> String;
);
// Create a plugin
simple_plugin!(
HelloPlugin,
"hello_plugin",
"A simple greeting plugin",
hooks: [(GreeterExtension, EnglishGreeter)]
);
// Implement a hook
struct EnglishGreeter;
impl GreeterTrait for EnglishGreeter {
fn greet(&self, name: &str) -> String {
format!("Hello, {}!", name)
}
}
// Create plugin manager
let mut plugin_manager = PluginManager::new();
// Load and enable the plugin
plugin_manager.load_plugin(Box::new(HelloPlugin::new())).unwrap();
plugin_manager.enable_plugin(HelloPlugin::ID).unwrap();
// Get all enabled hooks (plugins could be disabled)
let hooks = plugin_manager.get_enabled_hooks_by_ep::<GreeterExtension>();
// execute all hooks relevant for this extension point
for (_id, hook) in hooks {
println!("{}", hook.inner().greet("World"));
}
§Macros
steckrs provides several convenience macros to reduce boilerplate:
extension_point!
- Defines an extension point and its associated traitsimple_plugin!
- Creates a simple plugin with minimal boilerplateregister_hook!
- Registers a hook with the hook registry
Note that register_hook!
is not needed if you generate your plugin with simple_plugin!
.
§Advanced Usage
For more complex scenarios, you can implement the Plugin
trait directly,
allowing for more customized plugin behavior and state management.
Modules§
Macros§
- extension_
point - Defines a new
ExtensionPoint
and its associated trait. - register_
hook - Registers a
Hook
with aHookRegistry
. - simple_
plugin - Creates a simple Plugin with a specified set of hooks.
Structs§
- PluginID
Owned - An owned version of
PluginID
that can be owned and has optional serialization support withserde
. - Plugin
Manager - Manages plugin loading, execution, and lifecycle.
Traits§
- Plugin
- Plugin trait that must be implemented by all plugins.
Type Aliases§
- PluginID
- Plugin identifier type.