use core::cell::{RefCell};
use core::ops::{Range};
use crate::Rand;
#[derive(Default)]
pub struct State {
next_u64_invocations: u64,
}
impl State {
fn next_u64_invocations(&self) -> u64 {
self.next_u64_invocations
}
}
pub struct TestMock<D: FnMut(&State) -> u64> {
state: State,
delegate: D,
}
impl<D: FnMut(&State) -> u64> TestMock<D> {
pub fn new(delegate: D) -> Self {
Self {
state: State::default(),
delegate
}
}
pub fn state(&self) -> &State {
&self.state
}
}
impl<D: FnMut(&State) -> u64> Rand for TestMock<D> {
fn next_u64(&mut self) -> u64 {
let delegate = &mut self.delegate;
let r = delegate(&self.state);
self.state.next_u64_invocations += 1;
r
}
}
pub fn counter<T, S>(range: Range<T>) -> impl FnMut(&S) -> T
where
T: Copy + Next + Eq
{
let mut current = range.start;
move |_| {
let c = current;
let next = current.next();
current = if next == range.end { range.start } else { next };
c
}
}
pub trait Next {
#[must_use]
fn next(self) -> Self;
}
impl Next for u64 {
fn next(self) -> Self {
self + 1
}
}
impl Next for u128 {
fn next(self) -> Self {
self + 1
}
}
pub fn fixed<T: Copy, S>(val: T) -> impl FnMut(&S) -> T {
move |_| val
}
pub fn echo<T: Copy, S>(cell: &RefCell<T>) -> impl FnMut(&S) -> T + '_ {
|_| *cell.borrow()
}
#[cfg(test)]
mod tests;