use async_trait::async_trait;
use std::marker::PhantomData;
#[async_trait]
pub trait Generator: Send + Sync {
type Item;
async fn generate(&self, input: &str) -> Vec<Self::Item>;
}
pub struct ClosureGenerator<Item, F>(F, PhantomData<Item>)
where
F: Fn(&str) -> Vec<Item>;
impl<Item, F> ClosureGenerator<Item, F>
where
F: Fn(&str) -> Vec<Item>,
{
pub fn new(f: F) -> Self {
Self(f, PhantomData)
}
}
#[async_trait]
impl<Item, F> Generator for ClosureGenerator<Item, F>
where
F: Fn(&str) -> Vec<Item> + Sync + Send,
Item: Sync + Send,
{
type Item = Item;
async fn generate(&self, input: &str) -> Vec<Self::Item> {
(self.0)(input)
}
}
pub struct GenWrapper<Item, GenT, F, Cushion>
where
F: Fn(Item) -> Cushion + Sync + Send,
GenT: Generator<Item = Item> + Sync,
Cushion: Sync + Send,
{
f: F,
generator: GenT,
_marker: PhantomData<Cushion>,
}
#[async_trait]
impl<Item, GenT, F, Cushion> Generator for GenWrapper<Item, GenT, F, Cushion>
where
F: Fn(Item) -> Cushion + Sync + Send,
GenT: Generator<Item = Item> + Sync,
Cushion: Sync + Send,
{
type Item = Cushion;
async fn generate(&self, input: &str) -> Vec<Self::Item> {
self.generator
.generate(input)
.await
.into_iter()
.map(|item| (self.f)(item)) .collect()
}
}
impl<Item, GenT, F, Cushion> GenWrapper<Item, GenT, F, Cushion>
where
F: Fn(Item) -> Cushion + Sync + Send,
GenT: Generator<Item = Item> + Sync,
Cushion: Sync + Send,
{
pub fn new(generator: GenT, transformer: F) -> Self {
Self {
f: transformer,
generator,
_marker: PhantomData,
}
}
}