1use std::future::Future;
2
3use crux_core::{capability::Operation, command::RequestBuilder, Command, Request};
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
8pub enum DelayOperation {
9 GetRandom(usize, usize),
10 Delay(usize),
11}
12#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
16pub enum DelayOutput {
17 Random(usize),
18 TimeUp,
19}
20impl Operation for DelayOperation {
24 type Output = DelayOutput;
25}
26#[must_use]
31pub fn milliseconds<Effect, Event>(
32 millis: usize,
33) -> RequestBuilder<Effect, Event, impl Future<Output = DelayOutput>>
34where
35 Effect: Send + From<Request<DelayOperation>> + 'static,
36 Event: Send + 'static,
37{
38 Command::request_from_shell(DelayOperation::Delay(millis))
39}
40
41#[must_use]
48pub fn random<Effect, Event>(
49 min: usize,
50 max: usize,
51) -> RequestBuilder<Effect, Event, impl Future<Output = DelayOutput>>
52where
53 Effect: Send + From<Request<DelayOperation>> + 'static,
54 Event: Send + 'static,
55{
56 assert!(min <= max, "min must be less than or equal to max");
57
58 Command::request_from_shell(DelayOperation::GetRandom(min, max)).then_request(|response| {
59 let DelayOutput::Random(millis) = response else {
60 panic!("Expected a random number")
61 };
62
63 Command::request_from_shell(DelayOperation::Delay(millis))
64 })
65}
66#[cfg(test)]
70mod tests {
71 use crux_core::macros::effect;
72
73 use super::*;
74
75 #[effect]
76 pub enum Effect {
77 Delay(DelayOperation),
78 }
79
80 enum Event {
81 Delay(DelayOutput),
82 }
83
84 #[test]
85 fn test_delay() {
86 let delay = 100;
87
88 let mut cmd = milliseconds(delay).then_send(Event::Delay);
89
90 let effect = cmd.expect_one_effect();
91 let Effect::Delay(mut request) = effect;
92
93 assert_eq!(request.operation, DelayOperation::Delay(delay));
94
95 request.resolve(DelayOutput::TimeUp).unwrap();
96
97 let event = cmd.events().next().unwrap();
98 let Event::Delay(output) = event;
99 assert_eq!(output, DelayOutput::TimeUp);
100
101 assert!(cmd.is_done());
102 }
103
104 #[test]
105 fn test_random() {
106 let min = 100;
107 let max = 200;
108
109 let mut cmd = random(min, max).then_send(Event::Delay);
110
111 let effect = cmd.expect_one_effect();
112 let Effect::Delay(mut request) = effect;
113
114 assert_eq!(request.operation, DelayOperation::GetRandom(min, max));
115 request.resolve(DelayOutput::Random(150)).unwrap();
116
117 let effect = cmd.expect_one_effect();
118 let Effect::Delay(mut request) = effect;
119
120 assert_eq!(request.operation, DelayOperation::Delay(150));
121
122 request.resolve(DelayOutput::TimeUp).unwrap();
123
124 let event = cmd.events().next().unwrap();
125 let Event::Delay(output) = event;
126 assert_eq!(output, DelayOutput::TimeUp);
127
128 assert!(cmd.is_done());
129 }
130}
131