use crate::resource::Resources;
pub trait Plugin: Send + Sync {
fn name(&self) -> &'static str;
fn dependencies(&self) -> &[&'static str] {
&[]
}
fn build(&self, resources: &mut Resources);
#[allow(unused_variables)]
fn finish(&self, resources: &mut Resources) {}
#[allow(unused_variables)]
fn cleanup(&self, resources: &mut Resources) {}
}
pub trait PluginGroup {
fn plugins(&self) -> Vec<Box<dyn Plugin>>;
fn name(&self) -> &'static str {
std::any::type_name::<Self>()
}
}
pub(crate) struct PluginGroupAdapter {
name: &'static str,
plugins: Vec<Box<dyn Plugin>>,
}
impl PluginGroupAdapter {
pub fn new(group: impl PluginGroup) -> Self {
Self {
name: group.name(),
plugins: group.plugins(),
}
}
pub fn into_plugins(self) -> Vec<Box<dyn Plugin>> {
self.plugins
}
}
pub struct FnPlugin<F>
where
F: Fn(&mut Resources) + Send + Sync + 'static,
{
name: &'static str,
build_fn: F,
}
impl<F> FnPlugin<F>
where
F: Fn(&mut Resources) + Send + Sync + 'static,
{
pub fn new(name: &'static str, build_fn: F) -> Self {
Self { name, build_fn }
}
}
impl<F> Plugin for FnPlugin<F>
where
F: Fn(&mut Resources) + Send + Sync + 'static,
{
fn name(&self) -> &'static str {
self.name
}
fn build(&self, resources: &mut Resources) {
(self.build_fn)(resources);
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestPlugin {
value: i32,
}
impl Plugin for TestPlugin {
fn name(&self) -> &'static str {
"TestPlugin"
}
fn build(&self, resources: &mut Resources) {
resources.insert(self.value);
}
}
#[test]
fn test_plugin_build() {
let plugin = TestPlugin { value: 42 };
let mut resources = Resources::new();
plugin.build(&mut resources);
assert_eq!(*resources.get::<i32>().unwrap(), 42);
}
#[test]
fn test_fn_plugin() {
let plugin = FnPlugin::new("test", |resources| {
resources.insert("hello".to_string());
});
let mut resources = Resources::new();
plugin.build(&mut resources);
assert_eq!(resources.get::<String>().unwrap(), "hello");
}
struct DependentPlugin;
impl Plugin for DependentPlugin {
fn name(&self) -> &'static str {
"DependentPlugin"
}
fn dependencies(&self) -> &[&'static str] {
&["TestPlugin"]
}
fn build(&self, resources: &mut Resources) {
if let Some(val) = resources.get_mut::<i32>() {
*val *= 2;
}
}
}
#[test]
fn test_plugin_dependencies() {
let deps = DependentPlugin.dependencies();
assert_eq!(deps, &["TestPlugin"]);
}
}