1use super::{RawInput, Runtime};
2
3#[derive(Clone)]
4pub struct Input<P> {
5 pub level: u32,
6 pub id: u32,
7 pub payload: P,
8}
9
10pub trait FromInput<P, S>
11where
12 Self: Sized,
13{
14 fn from_input<R: Runtime>(runtime: &mut R, input: &Input<P>, state: &S) -> Result<Self, ()>;
15}
16
17type TransitionFct<R, P, S> = dyn FnMut(&mut R, &Input<P>, &S) -> Result<(), ()>;
19
20type GuardFct<R, P> = dyn FnMut(&mut R, &Input<P>) -> bool;
21
22pub trait IntoTransition<R, P, S, T>
23where
24 R: Runtime,
25{
26 fn into_transition(self) -> Box<TransitionFct<R, P, S>>;
27}
28
29macro_rules! tuple_from_req {
31 ($struct_name:ident; $($generic_param:ident),*) => {
32 #[allow(non_snake_case)]
33 pub struct $struct_name<$($generic_param),*> {
34 $( $generic_param: $generic_param ),*
35 }
36
37 impl<P, S, $($generic_param),*> FromInput<P, S> for $struct_name<$($generic_param),*>
38 where
39 $($generic_param: FromInput<P, S>),*,
40 P: Clone,
41 {
42 fn from_input<R: Runtime>(runtime: &mut R, input: &Input<P>, state: &S) -> Result<Self, ()> {
43 $(
44 #[allow(non_snake_case)]
45 let $generic_param = match <$generic_param>::from_input(runtime, input, state) {
46 Ok(t) => t,
47 Err(_) => return Err(()),
48 };
49 )*
50
51 Ok($struct_name { $($generic_param),* })
52 }
53 }
54
55 impl<R, P, Fct, S, $($generic_param),*> IntoTransition<R, P, S, $struct_name<$($generic_param),*>> for Fct
56 where
57 R: Runtime,
58 Fct: Fn(&mut R, $($generic_param),*) + 'static,
59 $($generic_param: FromInput<P, S>),*,
60 P: Clone,
61 {
62 fn into_transition(self) -> Box<dyn FnMut(&mut R, &Input<P>, &S) -> Result<(), ()>> {
63 Box::new(move |runtime: &mut R, input: &Input<P>, state: &S| {
64 let tuple = match $struct_name::from_input(runtime, input, state) {
65 Ok(t) => t,
66 Err(_) => return Err(()),
67 };
68 (self)(runtime, $(tuple.$generic_param),*);
69 Ok(())
70 })
71 }
72 }
73 };
74}
75
76impl<R, P, F, S> IntoTransition<R, P, S, ()> for F
77where
78 R: Runtime,
79 F: Fn(&mut R) + 'static,
80{
81 fn into_transition(self) -> Box<dyn FnMut(&mut R, &Input<P>, &S) -> Result<(), ()>> {
82 println!("Into transition");
83 Box::new(move |runtime: &mut R, _: &Input<P>, _: &S| {
84 (self)(runtime);
85 Ok(())
86 })
87 }
88}
89
90tuple_from_req!(Tuple1; A);
91tuple_from_req!(Tuple2; A, B);
92tuple_from_req!(Tuple3; A, B, C);
93tuple_from_req!(Tuple4; A, B, C, D);
94tuple_from_req!(Tuple5; A, B, C, D, E);
95tuple_from_req!(Tuple6; A, B, C, D, E, F);
96tuple_from_req!(Tuple7; A, B, C, D, E, F, G);
97tuple_from_req!(Tuple8; A, B, C, D, E, F, G, H);
98tuple_from_req!(Tuple9; A, B, C, D, E, F, G, H, I);
99
100pub trait FromRawInput
102where
103 Self: Sized,
104{
105 fn from_raw_input<R: Runtime>(runtime: &mut R, input: &RawInput) -> Result<Self, ()>;
106}
107
108impl<S> FromInput<Vec<u8>, S> for () {
109 fn from_input<R: Runtime>(_: &mut R, _: &Input<Vec<u8>>, _: &S) -> Result<Self, ()> {
110 Ok(())
111 }
112}
113
114impl<P, S> FromInput<P, S> for Input<P>
115where
116 P: Clone,
117{
118 fn from_input<R: Runtime>(_: &mut R, input: &Input<P>, _: &S) -> Result<Self, ()> {
119 Ok(input.clone())
120 }
121}
122
123impl<P, S> FromInput<P, S> for P
124where
125 P: Clone,
126{
127 fn from_input<R: Runtime>(_: &mut R, input: &Input<P>, _: &S) -> Result<Self, ()> {
128 Ok(input.payload.clone())
129 }
130}
131
132impl FromRawInput for Vec<u8> {
133 fn from_raw_input<R: Runtime>(_: &mut R, input: &RawInput) -> Result<Self, ()> {
134 Ok(input.payload.clone())
135 }
136}
137
138impl FromRawInput for () {
139 fn from_raw_input<R: Runtime>(_: &mut R, _: &RawInput) -> Result<Self, ()> {
140 Ok(())
141 }
142}
143
144pub struct Service<R, P, S>
147where
148 P: FromRawInput,
149{
150 guards: Vec<Box<GuardFct<R, P>>>,
151 transitions: Vec<Box<TransitionFct<R, P, S>>>,
152 state: S,
153}
154
155impl<R, P, S> Service<R, P, S>
156where
157 P: FromRawInput,
158{
159 pub fn new(state: S) -> Self {
160 Self {
161 guards: Default::default(),
162 transitions: Default::default(),
163 state,
164 }
165 }
166}
167
168pub trait Runnable<R>
169where
170 R: Runtime,
171{
172 fn run(&mut self, runtime: &mut R, input: RawInput);
173}
174
175impl<R, P, S> Runnable<R> for Service<R, P, S>
176where
177 R: Runtime,
178 P: FromRawInput,
179{
180 fn run(&mut self, runtime: &mut R, input: RawInput) {
181 println!("run");
182
183 let payload = match P::from_raw_input(runtime, &input) {
184 Ok(payload) => payload,
185 Err(_) => todo!("handle this error"),
186 };
187 println!("payload is present");
188
189 let input = Input {
191 level: input.level,
192 id: input.id,
193 payload,
194 };
195
196 let state = &self.state;
198
199 let accepted = self.guards.iter_mut().all(|guard| guard(runtime, &input));
201
202 match accepted {
203 false => {
204 println!("hmmmm");
205 }
207 true => {
208 println!("it's accepted");
209 println!("transitions: {}", self.transitions.len());
211
212 for transition in self.transitions.iter_mut() {
213 println!("transition");
214 let _ = transition(runtime, &input, state);
215 }
216 }
217 }
218 }
219}
220
221impl<R, P, S> Service<R, P, S>
222where
223 R: Runtime + 'static,
224 P: FromRawInput + 'static,
225{
226 pub fn add_guard(&mut self, guard: fn(&mut R, &Input<P>) -> bool) -> &mut Self {
231 let boxed = Box::new(guard);
232 self.guards.push(boxed);
233 self
234 }
235
236 pub fn register<F, Marker>(&mut self, transition: F) -> &mut Self
241 where
242 F: IntoTransition<R, P, S, Marker> + 'static,
243 {
244 let fct = transition.into_transition();
245 println!("register");
246 println!("registered: {}", self.transitions.len());
247 self.transitions.push(fct);
248 self
249 }
250}
251
252pub trait IntoService<R, P, S>
253where
254 R: Runtime,
255 P: FromRawInput,
256{
257 fn into_service(self) -> Service<R, P, S>;
258}
259
260impl<R, P, S> IntoService<R, P, S> for Service<R, P, S>
261where
262 R: Runtime,
263 P: FromRawInput,
264{
265 fn into_service(self) -> Service<R, P, S> {
266 self
267 }
268}
269
270#[cfg(test)]
271mod tests {
272 use crate::core::{runtime::MockRuntime, Application, Runtime};
273
274 use super::{FromInput, IntoService, Service};
275
276 struct Test {
277 inner: String,
278 }
279
280 impl FromInput<Vec<u8>, String> for Test {
281 fn from_input<R: Runtime>(
282 _: &mut R,
283 _: &super::Input<Vec<u8>>,
284 state: &String,
285 ) -> Result<Self, ()> {
286 Ok(Self {
287 inner: state.clone(),
288 })
289 }
290 }
291
292 fn transition_0<R: Runtime>(rt: &mut R) {
293 rt.write_debug("Hello world 0");
294 }
295
296 fn transition_1<R: Runtime>(rt: &mut R, t: Test) {
297 rt.write_debug(&t.inner);
298 }
299
300 fn transition_2<R: Runtime>(rt: &mut R, _: (), _: ()) {
301 rt.write_debug("Hello world 2");
302 }
303
304 fn transition_3<R: Runtime>(rt: &mut R, _: (), _: (), _: ()) {
305 rt.write_debug("Hello world 3");
306 }
307
308 fn transition_4<R: Runtime>(rt: &mut R, _: (), _: (), _: (), _: ()) {
309 rt.write_debug("Hello world 4");
310 }
311
312 fn transition_5<R: Runtime>(rt: &mut R, _: (), _: (), _: (), _: (), _: ()) {
313 rt.write_debug("Hello world 5");
314 }
315
316 fn transition_6<R: Runtime>(rt: &mut R, _: (), _: (), _: (), _: (), _: (), _: ()) {
317 rt.write_debug("Hello world 6");
318 }
319
320 fn transition_7<R: Runtime>(rt: &mut R, _: (), _: (), _: (), _: (), _: (), _: (), _: ()) {
321 rt.write_debug("Hello world 7");
322 }
323
324 fn transition_8<R: Runtime>(
325 rt: &mut R,
326 _: (),
327 _: (),
328 _: (),
329 _: (),
330 _: (),
331 _: (),
332 _: (),
333 _: (),
334 ) {
335 rt.write_debug("Hello world 8");
336 }
337
338 fn transition_9<R: Runtime>(
339 rt: &mut R,
340 _: (),
341 _: (),
342 _: (),
343 _: (),
344 _: (),
345 _: (),
346 _: (),
347 _: (),
348 _: (),
349 ) {
350 rt.write_debug("Hello world 9");
351 }
352
353 #[test]
354 fn test() {
355 let mut runtime = MockRuntime::default();
356 runtime.add_input(Vec::default());
357 let mut service = Service::<_, Vec<u8>, String>::new("Hello world 1".to_string());
358
359 service
360 .add_guard(|_runtime, _input| true)
361 .register(transition_0)
362 .register(transition_1)
363 .register(transition_2)
364 .register(transition_3)
365 .register(transition_4)
366 .register(transition_5)
367 .register(transition_6)
368 .register(transition_7)
369 .register(transition_8)
370 .register(transition_9);
371
372 let () = Application::new(&mut runtime).service(service).run();
373
374 assert_eq!(
375 runtime.stdout(),
376 vec![
377 "Hello world 0",
378 "Hello world 1",
379 "Hello world 2",
380 "Hello world 3",
381 "Hello world 4",
382 "Hello world 5",
383 "Hello world 6",
384 "Hello world 7",
385 "Hello world 8",
386 "Hello world 9",
387 ]
388 )
389 }
390
391 struct CustomService {
392 _data: String,
393 }
394
395 fn custom_transition<R: Runtime>(_: &mut R) {}
396
397 impl<R> IntoService<R, Vec<u8>, CustomService> for CustomService
398 where
399 R: Runtime,
400 {
401 fn into_service(self) -> Service<R, Vec<u8>, Self> {
402 let mut service = Service::<R, Vec<u8>, Self>::new(self);
403 service.register(custom_transition);
404 service
405 }
406 }
407
408 #[test]
409 fn test_2() {
410 let mut runtime = MockRuntime::default();
411 let mut application = Application::new(&mut runtime);
412
413 let service = CustomService {
414 _data: "some data".to_string(),
415 };
416
417 application.service(service).run();
418 }
419}