1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//! Generator

use super::*;
use crate::prelude::*;

impl<const D: Dep, P: Copy, R: Copy> I<ValidH<P, R>, D> {
    /// Generator.
    ///
    /// TODO: Documentation
    pub fn generator<EP: Copy, S: Copy>(
        self,
        init: S,
        f_write_state: impl Fn(P, R, S) -> S,
        f_read_state: impl Fn(S) -> HOption<EP>,
    ) -> I<ValidH<EP, R>, { Dep::Helpful }> {
        unsafe {
            self.fsm::<_, { Dep::Helpful }, ValidH<EP, R>>(init, |ip, er, s| {
                let ep = f_read_state(s);

                let s_next = match ip {
                    Some(ip) => f_write_state(ip, er, s),
                    _ => s,
                };

                (ep, er, s_next)
            })
        }
    }
}

impl<const D: Dep, P: Copy, R: Copy> I<VrH<P, R>, D> {
    /// Generator.
    ///
    /// # Input
    /// - `init`: Initial state.
    /// - `f_write_state`: Write state function. This will set the state when ingress ingress_transfer happens.
    /// - `f_read_state`: Read state function. This will read the state and trigger egress transfer
    /// when egess ready is `true` and the function returns `Some`. Also, the boolean value
    /// returned by this function will work as the ready signal for the ingress transfer(i.e.,
    /// backpressure).
    pub fn generator<EP: Copy, S: Copy>(
        self,
        init: S,
        f_write_state: impl Fn(P, R, S) -> S,
        f_read_state: impl Fn(S) -> (HOption<EP>, bool),
    ) -> I<VrH<EP, R>, { Dep::Helpful }> {
        unsafe {
            self.fsm::<_, { Dep::Helpful }, VrH<EP, R>>(init, |ip, er, s| {
                let (ep, ready) = f_read_state(s);

                let s_next = match ip {
                    Some(ip) if ready => f_write_state(ip, er.inner, s),
                    _ => s,
                };

                let ir = Ready::new(ready, er.inner);

                (ep, ir, s_next)
            })
        }
    }
}