use super::{Metric, Reporter};
mod support;
pub use support::black_box;
use support::HListIterator;
mod single;
pub use single::build_single as single;
mod suite;
pub use suite::build_suite as suite;
pub struct BenchmarkRunner<L: RunnableBenchmarkList = ()> {
iterations: usize,
list: L,
}
impl Default for BenchmarkRunner<()> {
fn default() -> Self {
Self {
iterations: 1,
list: (),
}
}
}
impl BenchmarkRunner {
pub const fn new() -> BenchmarkRunner<()> {
BenchmarkRunner {
iterations: 1,
list: (),
}
}
}
impl<L: RunnableBenchmarkList> BenchmarkRunner<L> {
pub const fn set_iterations(mut self, it: usize) -> Self {
self.iterations = it;
self
}
#[allow(clippy::should_implement_trait)]
pub fn add<X>(self, top_level_benchmark: X) -> BenchmarkRunner<(X, L)>
where
(X, L): RunnableBenchmarkList,
{
BenchmarkRunner {
iterations: self.iterations,
list: (top_level_benchmark, self.list),
}
}
pub fn run<M: Metric, R: Reporter<M>>(self, metric: &mut M, reporter: &mut R)
where
for<'a> HListIterator<'a, dyn RunnableBenchmarkList + 'a>: Clone,
{
reporter.top_level_benchmarks(HListIterator(&self.list as _));
reporter.num_iterations(self.iterations);
self.list.run(metric, reporter, self.iterations);
reporter.ended();
}
}
#[allow(clippy::len_without_is_empty)]
pub trait RunnableBenchmarkList {
fn run<M: Metric, R: Reporter<M>>(self, m: &mut M, r: &mut R, iterations: usize)
where
Self: Sized;
fn name_and_next<'a>(&'a self) -> Option<(&'static str, &'a (dyn RunnableBenchmarkList + 'a))>;
fn len(&self) -> usize;
}
impl<'a> Iterator for HListIterator<'a, (dyn RunnableBenchmarkList + 'a)> {
type Item = &'static str;
fn next(&mut self) -> Option<Self::Item> {
let (name, next) = self.0.name_and_next()?;
self.0 = next;
Some(name)
}
}
impl RunnableBenchmarkList for () {
fn run<M: Metric, R: Reporter<M>>(self, _m: &mut M, _r: &mut R, _iterations: usize) {}
fn name_and_next(&self) -> Option<(&'static str, &dyn RunnableBenchmarkList)> {
None
}
fn len(&self) -> usize {
0
}
}