use crate::{AsyncCheck, Check};
type QueryFn<Ctx> = Box<dyn Fn(&Ctx) -> bool>;
type GeneratorFn<Ctx, Item, Items> =
Box<dyn Fn(&Ctx) -> Vec<Box<dyn Check<Item = Item, Items = Items>>>>;
type AsyncGeneratorFn<Ctx, Item, Items> =
Box<dyn Fn(&Ctx) -> Vec<Box<dyn AsyncCheck<Item = Item, Items = Items>>>>;
pub struct DiscoveryRegistry<Ctx, Item, Items>
where
Item: crate::Item,
Items: IntoIterator<Item = Item>,
{
plugins: Vec<(QueryFn<Ctx>, GeneratorFn<Ctx, Item, Items>)>,
async_plugins: Vec<(QueryFn<Ctx>, AsyncGeneratorFn<Ctx, Item, Items>)>,
}
impl<Ctx, Item, Items> Default for DiscoveryRegistry<Ctx, Item, Items>
where
Item: crate::Item,
Items: IntoIterator<Item = Item>,
{
fn default() -> Self {
Self::new()
}
}
impl<Ctx, Item, Items> DiscoveryRegistry<Ctx, Item, Items>
where
Item: crate::Item,
Items: IntoIterator<Item = Item>,
{
pub fn new() -> Self {
Self {
plugins: Vec::new(),
async_plugins: Vec::new(),
}
}
pub fn register<
Query: Fn(&Ctx) -> bool + 'static,
Generator: Fn(&Ctx) -> Vec<Box<dyn Check<Item = Item, Items = Items>>> + 'static,
>(
&mut self,
query: Query,
generator: Generator,
) {
self.plugins.push((Box::new(query), Box::new(generator)));
}
pub fn register_async<
Query: Fn(&Ctx) -> bool + 'static,
Generator: Fn(&Ctx) -> Vec<Box<dyn AsyncCheck<Item = Item, Items = Items>>> + 'static,
>(
&mut self,
query: Query,
generator: Generator,
) {
self.async_plugins
.push((Box::new(query), Box::new(generator)));
}
pub fn gather(&self, context: &Ctx) -> Option<Vec<Box<dyn Check<Item = Item, Items = Items>>>> {
for (query, generator) in &self.plugins {
if query(context) {
return Some(generator(context));
}
}
None
}
pub fn gather_async(
&self,
context: &Ctx,
) -> Option<Vec<Box<dyn AsyncCheck<Item = Item, Items = Items>>>> {
for (query, generator) in &self.async_plugins {
if query(context) {
return Some(generator(context));
}
}
None
}
}