use fixed_typemap::decl_fixed_typemap;
trait Plugin {
fn run(&self);
}
#[derive(Default)]
struct GraphicsPlugin(u64);
#[derive(Default)]
struct SoundPlugin(u64);
#[derive(Default)]
struct NetworkingPlugin(u64);
#[derive(Default)]
struct UserProvidedPlugin(u64);
impl Plugin for GraphicsPlugin {
fn run(&self) {
println!("Running graphics: {}", self.0);
}
}
impl Plugin for SoundPlugin {
fn run(&self) {
println!("Running sound: {}", self.0);
}
}
impl Plugin for NetworkingPlugin {
fn run(&self) {
println!("Running networking: {}", self.0);
}
}
impl Plugin for UserProvidedPlugin {
fn run(&self) {
println!("Running user-supplied code: {}", self.0);
}
}
decl_fixed_typemap! {
#[fixed_typemap(dynamic, iterable_traits(Plugin = "iter_plugins"))]
struct PluginMap {
graphics: GraphicsPlugin,
_: SoundPlugin,
_: NetworkingPlugin = NetworkingPlugin(100),
}
}
fn run_plugins(map: &PluginMap) {
for p in map.iter_plugins() {
p.run();
}
}
fn main() {
let mut map = PluginMap::new();
println!("Before adding user-provided plugin");
run_plugins(&map);
map.insert(UserProvidedPlugin(0))
.expect("In this context, insert should always succeed");
println!("After user-provided plugin");
run_plugins(&map);
map.graphics = GraphicsPlugin(1);
*map.get_infallible_mut::<SoundPlugin>() = SoundPlugin(2);
map.insert(NetworkingPlugin(10))
.expect("Insert should always succeed in this context");
*map.get_mut::<UserProvidedPlugin>().unwrap() = UserProvidedPlugin(20);
println!("After modification");
run_plugins(&map);
}