async_callback_manager/task/dyn_task/
handlers.rs

1use crate::{AsyncTask, FrontendEffect, TaskHandler};
2
3/// Allow closures to be accepted as TaskHandlers if equality and debug features
4/// are not required.
5#[cfg(all(not(feature = "task-equality"), not(feature = "task-debug")))]
6impl<T, F, Input, Frntend, Bkend, Md> TaskHandler<Input, Frntend, Bkend, Md> for F
7where
8    F: FnOnce(&mut Frntend, Input) -> T,
9    T: Into<AsyncTask<Frntend, Bkend, Md>>,
10    Input: 'static,
11{
12    fn handle(self, input: Input) -> impl FrontendEffect<Frntend, Bkend, Md> {
13        |this: &mut Frntend| self(this, input)
14    }
15}
16
17/// Allow closures to be accepted as TaskHandlers if equality and debug features
18/// are not required.
19impl<F, T, Frntend, Bkend, Md> FrontendEffect<Frntend, Bkend, Md> for F
20where
21    F: FnOnce(&mut Frntend) -> T,
22    T: Into<AsyncTask<Frntend, Bkend, Md>>,
23{
24    fn apply(self, target: &mut Frntend) -> impl Into<AsyncTask<Frntend, Bkend, Md>> {
25        self(target).into()
26    }
27}
28
29/// Helper handler for a task that returns a Result<T,E>
30#[derive(PartialEq, Clone, Debug)]
31pub(crate) struct TryHandler<OkH, ErrH> {
32    pub(crate) ok_handler: OkH,
33    pub(crate) err_handler: ErrH,
34}
35
36impl<OkH, ErrH, T, E, Frntend, Bkend, Md> TaskHandler<Result<T, E>, Frntend, Bkend, Md>
37    for TryHandler<OkH, ErrH>
38where
39    OkH: TaskHandler<T, Frntend, Bkend, Md>,
40    ErrH: TaskHandler<E, Frntend, Bkend, Md>,
41{
42    fn handle(self, output: Result<T, E>) -> impl FrontendEffect<Frntend, Bkend, Md> {
43        let Self {
44            ok_handler,
45            err_handler,
46        } = self;
47        match output {
48            Ok(x) => Either::Left(ok_handler.handle(x)),
49            Err(e) => Either::Right(err_handler.handle(e)),
50        }
51    }
52}
53
54/// Helper to utilise static dispatch when returning different types of impl
55/// Trait.
56#[derive(PartialEq, Clone, Debug)]
57pub(crate) enum Either<L, R> {
58    Left(L),
59    Right(R),
60}
61
62impl<L, R, Frntend, Bkend, Md> FrontendEffect<Frntend, Bkend, Md> for Either<L, R>
63where
64    L: FrontendEffect<Frntend, Bkend, Md>,
65    R: FrontendEffect<Frntend, Bkend, Md>,
66{
67    fn apply(self, target: &mut Frntend) -> impl std::convert::Into<AsyncTask<Frntend, Bkend, Md>> {
68        match self {
69            Either::Left(x) => x.apply(target).into(),
70            Either::Right(x) => x.apply(target).into(),
71        }
72    }
73}
74
75/// Helper handler for a task that returns Option<T>
76#[derive(PartialEq, Clone, Debug)]
77pub(crate) struct OptionHandler<SomeH>(pub(crate) SomeH);
78
79impl<SomeH, T, Frntend, Bkend, Md> TaskHandler<Option<T>, Frntend, Bkend, Md>
80    for OptionHandler<SomeH>
81where
82    SomeH: TaskHandler<T, Frntend, Bkend, Md>,
83{
84    fn handle(self, output: Option<T>) -> impl FrontendEffect<Frntend, Bkend, Md> {
85        output.map(|output| self.0.handle(output))
86    }
87}
88impl<M, Frntend, Bkend, Md> FrontendEffect<Frntend, Bkend, Md> for Option<M>
89where
90    M: FrontendEffect<Frntend, Bkend, Md>,
91{
92    fn apply(self, target: &mut Frntend) -> impl std::convert::Into<AsyncTask<Frntend, Bkend, Md>> {
93        let Some(mutation) = self else {
94            return AsyncTask::new_no_op();
95        };
96        mutation.apply(target).into()
97    }
98}
99
100#[derive(PartialEq, Clone, Copy, Debug)]
101pub struct NoOpHandler;
102impl<Input, Frntend, Bkend, Md> TaskHandler<Input, Frntend, Bkend, Md> for NoOpHandler {
103    fn handle(self, _: Input) -> impl FrontendEffect<Frntend, Bkend, Md> {
104        |_: &mut Frntend| AsyncTask::new_no_op()
105    }
106}