use std::marker::PhantomData;
use super::func::{FromFn, Once, Repeat};
use crate::{InitSans, Sans, Step};
pub struct Init<I, O, S: Sans<I, O>>(O, S, PhantomData<I>);
impl<I, O, S> InitSans<I, O> for Init<I, O, S>
where
S: Sans<I, O>,
{
type Next = S;
fn init(self) -> Step<(O, S), S::Return> {
Step::Yielded((self.0, self.1))
}
}
pub fn init<I, O, S: Sans<I, O>>(output: O, coro: S) -> Init<I, O, S> {
Init(output, coro, PhantomData)
}
pub fn init_once<I, O, F: FnOnce(I) -> O>(o: O, f: F) -> (O, Once<F>) {
(o, super::func::once(f))
}
pub fn init_repeat<I, O, F: FnMut(I) -> O>(o: O, f: F) -> (O, Repeat<F>) {
(o, super::func::repeat(f))
}
pub fn init_from_fn<I, O, D, F>(initial: O, f: F) -> (O, FromFn<F>)
where
F: FnMut(I) -> Step<O, D>,
{
(initial, super::func::from_fn(f))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{InitSans, Sans};
use std::mem::size_of_val;
#[test]
fn test_simple_addition() {
let mut prev = 1;
let fib = init_repeat(1, move |n: u128| {
let next = prev + n;
prev = next;
next
});
let (_, mut next) = fib.init().unwrap_yielded();
for i in 1..11 {
let cur = next.next(1).unwrap_yielded();
assert_eq!(i + 1, cur);
}
}
#[test]
fn test_simple_divider() {
let mut start = 101323012313805546028676730784521326u128;
let divider = init_repeat(start, |divisor: u128| {
start /= divisor;
start
});
assert_eq!(size_of_val(÷r), 32);
let (mut cur, mut next) = divider.init().unwrap_yielded();
for i in 2..20 {
let next_cur = next.next(i).unwrap_yielded();
assert_eq!(cur / i, next_cur);
cur = next_cur;
}
}
}