use crate::{Sans, Step};
pub fn many<const N: usize, I, O, S>(rest: [S; N]) -> Many<N, S>
where
S: Sans<I, O, Return = I>,
{
Many {
states: rest.map(|r| Some(r)),
index: 0,
}
}
pub struct Many<const N: usize, S> {
states: [Option<S>; N],
index: usize,
}
impl<const N: usize, I, O, S> Sans<I, O> for Many<N, S>
where
S: Sans<I, O, Return = I>,
{
type Return = S::Return;
fn next(&mut self, mut input: I) -> Step<O, Self::Return> {
loop {
match self.states.get_mut(self.index) {
Some(Some(s)) => match s.next(input) {
Step::Yielded(o) => return Step::Yielded(o),
Step::Complete(a) => {
self.index += 1;
input = a;
}
},
Some(None) => {
self.index += 1;
}
None => return Step::Complete(input),
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::build::once;
#[test]
fn test_many_empty_array() {
#[allow(clippy::type_complexity)]
let mut coro: Many<0, crate::build::Once<fn(i32) -> i32>> = many([]);
assert_eq!(coro.next(42).unwrap_complete(), 42);
}
#[test]
fn test_many_single_coroutine() {
fn add_ten(x: i32) -> i32 {
x + 10
}
let mut coro = many([once(add_ten)]);
assert_eq!(coro.next(5).unwrap_yielded(), 15);
assert_eq!(coro.next(20).unwrap_complete(), 20);
}
#[test]
fn test_many_two_coroutines() {
fn add_ten(x: i32) -> i32 {
x + 10
}
fn mul_two(x: i32) -> i32 {
x * 2
}
let mut coro = many([
once(add_ten as fn(i32) -> i32),
once(mul_two as fn(i32) -> i32),
]);
assert_eq!(coro.next(5).unwrap_yielded(), 15);
assert_eq!(coro.next(7).unwrap_yielded(), 14);
assert_eq!(coro.next(20).unwrap_complete(), 20);
}
#[test]
fn test_many_three_coroutines() {
fn add_ten(x: i32) -> i32 {
x + 10
}
fn mul_two(x: i32) -> i32 {
x * 2
}
fn add_hundred(x: i32) -> i32 {
x + 100
}
let mut coro = many([
once(add_ten as fn(i32) -> i32),
once(mul_two as fn(i32) -> i32),
once(add_hundred as fn(i32) -> i32),
]);
assert_eq!(coro.next(5).unwrap_yielded(), 15);
assert_eq!(coro.next(6).unwrap_yielded(), 12);
assert_eq!(coro.next(7).unwrap_yielded(), 107);
assert_eq!(coro.next(8).unwrap_complete(), 8);
}
#[test]
fn test_many_passes_return_to_next_coro() {
fn add_one(x: i32) -> i32 {
x + 1
}
fn mul_ten(x: i32) -> i32 {
x * 10
}
let mut coro = many([
once(add_one as fn(i32) -> i32),
once(mul_ten as fn(i32) -> i32),
]);
assert_eq!(coro.next(5).unwrap_yielded(), 6);
assert_eq!(coro.next(100).unwrap_yielded(), 1000);
assert_eq!(coro.next(50).unwrap_complete(), 50);
}
#[test]
fn test_many_large_array() {
fn add_one(x: i32) -> i32 {
x + 1
}
let f = add_one as fn(i32) -> i32;
let mut coro = many([once(f), once(f), once(f), once(f), once(f)]);
assert_eq!(coro.next(0).unwrap_yielded(), 1); assert_eq!(coro.next(10).unwrap_yielded(), 11); assert_eq!(coro.next(20).unwrap_yielded(), 21); assert_eq!(coro.next(30).unwrap_yielded(), 31); assert_eq!(coro.next(40).unwrap_yielded(), 41); assert_eq!(coro.next(50).unwrap_complete(), 50); }
}