use super::{BoxedGenerator, BoxedPrintableGenerator, Generator, PrintableGenerator};
use crate::pretty::PrettyPrinter;
use crate::test_case::TestCase;
use std::sync::{Arc, OnceLock};
struct DeferredGenerator<B> {
inner: Arc<OnceLock<B>>,
}
impl<B> DeferredGenerator<B> {
fn get(&self) -> &B {
self.inner
.get()
.unwrap_or_else(|| panic!("DeferredGenerator has not been set"))
}
}
impl<T, B: Generator<T> + Send + Sync> Generator<T> for DeferredGenerator<B> {
fn do_draw(&self, tc: &TestCase) -> T {
self.get().do_draw(tc)
}
}
impl<T, B: PrintableGenerator<T> + Send + Sync> PrintableGenerator<T> for DeferredGenerator<B> {
fn do_draw_and_print(&self, tc: &TestCase, printer: &mut PrettyPrinter) -> T {
self.get().do_draw_and_print(tc, printer)
}
}
pub struct DeferredGeneratorDefinition<T, B = BoxedPrintableGenerator<'static, T>> {
inner: Arc<OnceLock<B>>,
_phantom: std::marker::PhantomData<fn(T)>,
}
impl<T: Send + Sync + 'static> DeferredGeneratorDefinition<T, BoxedPrintableGenerator<'static, T>> {
pub fn generator(&self) -> BoxedPrintableGenerator<'static, T> {
DeferredGenerator {
inner: Arc::clone(&self.inner),
}
.boxed_printable()
}
pub fn set(self, generator: impl PrintableGenerator<T> + Send + Sync + 'static) {
let _ = self.inner.set(generator.boxed_printable());
}
}
impl<T: Send + Sync + 'static> DeferredGeneratorDefinition<T, BoxedGenerator<'static, T>> {
pub fn generator(&self) -> BoxedGenerator<'static, T> {
DeferredGenerator {
inner: Arc::clone(&self.inner),
}
.boxed()
}
pub fn set(self, generator: impl Generator<T> + Send + Sync + 'static) {
let _ = self.inner.set(generator.boxed());
}
}
pub fn deferred<T>() -> DeferredGeneratorDefinition<T> {
DeferredGeneratorDefinition {
inner: Arc::new(OnceLock::new()),
_phantom: std::marker::PhantomData,
}
}
pub fn deferred_silent<T>() -> DeferredGeneratorDefinition<T, BoxedGenerator<'static, T>> {
DeferredGeneratorDefinition {
inner: Arc::new(OnceLock::new()),
_phantom: std::marker::PhantomData,
}
}