use super::Mul;
use crate::combinator::Combinator;
impl<Lhs, Rhs, Sep, Init, Fold> Combinator<Mul<Lhs, Rhs, Sep, Init, Fold>> {
#[inline]
pub fn fold<Value, Acc, NewInit: Fn() -> Acc, NewFold: Fn(Acc, Value) -> Acc>(
self,
init: NewInit,
fold: NewFold,
) -> Combinator<Mul<Lhs, Rhs, Sep, NewInit, NewFold>> {
Combinator::new(Mul {
lhs: self.action.lhs,
rhs: self.action.rhs,
sep: self.action.sep,
init,
fold,
})
}
}
#[cfg(test)]
mod tests {
use crate::{
action::{Action, Input},
combinator::{bytes, take, Bind, Combinator, Take},
digest::Digest,
instant::Instant,
};
use std::{ops::RangeFrom, slice::SliceIndex};
fn helper<Text: ?Sized + Digest>(
action: impl Action<Text = Text, State = (), Heap = (), Value = i32>,
input: &Text,
value: i32,
) where
RangeFrom<usize>: SliceIndex<Text, Output = Text>,
{
assert_eq!(
action
.exec(Input {
instant: &Instant::new(input),
state: &mut (),
heap: &mut ()
})
.unwrap()
.value,
value
)
}
fn accepter() -> Combinator<Bind<Take, i32>> {
take(1).bind(1)
}
fn rejecter() -> Combinator<impl Action<Text = str, State = (), Heap = (), Value = i32>> {
accepter().reject(|_| true)
}
fn accepter_b() -> Combinator<Bind<bytes::Take, i32>> {
bytes::take(1).bind(1)
}
fn rejecter_b() -> Combinator<impl Action<Text = [u8], State = (), Heap = (), Value = i32>> {
accepter_b().reject(|_| true)
}
fn init() -> i32 {
0
}
fn fold(acc: i32, v: i32) -> i32 {
acc + v
}
#[test]
fn combinator_mul_usize_fold() {
helper((accepter() * 3).fold(init, fold), "123", 3);
helper((accepter_b() * 3).fold(init, fold), b"123", 3);
helper((accepter() * 0).fold(init, fold), "123", 0);
helper((accepter_b() * 0).fold(init, fold), b"123", 0);
helper((accepter().reject(|_| true) * 0).fold(init, fold), "123", 0);
helper(
(accepter_b().reject(|_| true) * 0).fold(init, fold),
b"123",
0,
);
}
#[test]
fn combinator_mul_range_fold() {
helper((accepter() * (2..4)).fold(init, fold), "123", 3);
helper((accepter_b() * (2..4)).fold(init, fold), b"123", 3);
helper((accepter() * (0..1)).fold(init, fold), "123", 0);
helper((accepter_b() * (0..1)).fold(init, fold), b"123", 0);
helper((rejecter() * (0..1)).fold(init, fold), "123", 0);
helper((rejecter_b() * (0..1)).fold(init, fold), b"123", 0);
}
#[test]
fn combinator_mul_range_from_fold() {
helper((accepter() * (2..)).fold(init, fold), "123", 3);
helper((accepter_b() * (2..)).fold(init, fold), b"123", 3);
helper((rejecter() * (0..)).fold(init, fold), "123", 0);
helper((rejecter_b() * (0..)).fold(init, fold), b"123", 0);
}
#[test]
fn combinator_mul_range_full_fold() {
helper((accepter() * (..)).fold(init, fold), "123", 3);
helper((accepter_b() * (..)).fold(init, fold), b"123", 3);
helper((rejecter() * (..)).fold(init, fold), "123", 0);
helper((rejecter_b() * (..)).fold(init, fold), b"123", 0);
}
#[test]
fn combinator_mul_range_inclusive_fold() {
helper((accepter() * (2..=3)).fold(init, fold), "123", 3);
helper((accepter_b() * (2..=3)).fold(init, fold), b"123", 3);
helper((accepter() * (0..=0)).fold(init, fold), "123", 0);
helper((accepter_b() * (0..=0)).fold(init, fold), b"123", 0);
helper((rejecter() * (0..=0)).fold(init, fold), "123", 0);
helper((rejecter_b() * (0..=0)).fold(init, fold), b"123", 0);
}
#[test]
fn combinator_mul_range_to_fold() {
helper((accepter() * (..4)).fold(init, fold), "123", 3);
helper((accepter_b() * (..4)).fold(init, fold), b"123", 3);
helper((accepter() * (..1)).fold(init, fold), "123", 0);
helper((accepter_b() * (..1)).fold(init, fold), b"123", 0);
helper((rejecter() * (..1)).fold(init, fold), "123", 0);
helper((rejecter_b() * (..1)).fold(init, fold), b"123", 0);
}
#[test]
fn combinator_mul_range_to_inclusive_fold() {
helper((accepter() * (2..=3)).fold(init, fold), "123", 3);
helper((accepter_b() * (2..=3)).fold(init, fold), b"123", 3);
helper((accepter() * (0..=0)).fold(init, fold), "123", 0);
helper((accepter_b() * (0..=0)).fold(init, fold), b"123", 0);
helper((rejecter() * (0..=0)).fold(init, fold), "123", 0);
helper((rejecter_b() * (0..=0)).fold(init, fold), b"123", 0);
}
}