Skip to main content

winio_elm/
boxed.rs

1use std::{convert::Infallible, fmt::Debug, pin::Pin};
2
3use futures_util::FutureExt;
4
5use crate::{Component, ComponentMessage, ComponentSender, channel::Channel};
6
7type DynComponentSender<T> =
8    Channel<ComponentMessage<<T as DynComponent>::Message, <T as DynComponent>::Event>>;
9
10trait DynComponent {
11    type Message;
12    type Event;
13    type Error: Debug;
14
15    fn start<'a>(
16        &'a mut self,
17        sender: &'a DynComponentSender<Self>,
18    ) -> Pin<Box<dyn Future<Output = Infallible> + 'a>>;
19
20    fn update_children(&mut self) -> Pin<Box<dyn Future<Output = Result<bool, Self::Error>> + '_>>;
21
22    fn update<'a>(
23        &'a mut self,
24        message: Self::Message,
25        sender: &'a DynComponentSender<Self>,
26    ) -> Pin<Box<dyn Future<Output = Result<bool, Self::Error>> + 'a>>;
27
28    fn render(&mut self, sender: &DynComponentSender<Self>) -> Result<(), Self::Error>;
29
30    fn render_children(&mut self) -> Result<(), Self::Error>;
31}
32
33impl<T: Component + 'static> DynComponent for T {
34    type Error = <T as Component>::Error;
35    type Event = <T as Component>::Event;
36    type Message = <T as Component>::Message;
37
38    fn start<'a>(
39        &'a mut self,
40        sender: &'a DynComponentSender<Self>,
41    ) -> Pin<Box<dyn Future<Output = Infallible> + 'a>> {
42        let sender = ComponentSender::<T>::from_ref(sender);
43        Box::pin(Component::start(self, sender).map(|a| a))
44    }
45
46    fn update_children(&mut self) -> Pin<Box<dyn Future<Output = Result<bool, Self::Error>> + '_>> {
47        Box::pin(Component::update_children(self))
48    }
49
50    fn update<'a>(
51        &'a mut self,
52        message: Self::Message,
53        sender: &'a DynComponentSender<Self>,
54    ) -> Pin<Box<dyn Future<Output = Result<bool, Self::Error>> + 'a>> {
55        let sender = ComponentSender::<T>::from_ref(sender);
56        Box::pin(Component::update(self, message, sender))
57    }
58
59    fn render(&mut self, sender: &DynComponentSender<Self>) -> Result<(), Self::Error> {
60        let sender = ComponentSender::<T>::from_ref(sender);
61        Component::render(self, sender)
62    }
63
64    fn render_children(&mut self) -> Result<(), Self::Error> {
65        Component::render_children(self)
66    }
67}
68
69/// A boxed component. It is not initialized directly, but constructed by
70/// [`Child::into_boxed`] or [`Root::into_boxed`].
71///
72/// [`Child::into_boxed`]: crate::Child::into_boxed
73/// [`Root::into_boxed`]: crate::Root::into_boxed
74pub struct BoxComponent<M, Ev, Err>(Box<dyn DynComponent<Message = M, Event = Ev, Error = Err>>);
75
76impl<M, Ev, Err> BoxComponent<M, Ev, Err> {
77    pub(crate) fn new<T: Component<Message = M, Event = Ev, Error = Err> + 'static>(
78        component: T,
79    ) -> Self {
80        Self(Box::new(component))
81    }
82}
83
84impl<M, Ev, Err: Debug> Component for BoxComponent<M, Ev, Err> {
85    type Error = Err;
86    type Event = Ev;
87    type Init<'a> = Infallible;
88    type Message = M;
89
90    async fn init(
91        init: Self::Init<'_>,
92        _sender: &ComponentSender<Self>,
93    ) -> Result<Self, Self::Error> {
94        match init {}
95    }
96
97    async fn start(&mut self, sender: &ComponentSender<Self>) -> ! {
98        let sender = &sender.0;
99        match self.0.start(sender).await {}
100    }
101
102    async fn update_children(&mut self) -> Result<bool, Self::Error> {
103        self.0.update_children().await
104    }
105
106    async fn update(
107        &mut self,
108        message: Self::Message,
109        sender: &ComponentSender<Self>,
110    ) -> Result<bool, Self::Error> {
111        let sender = &sender.0;
112        self.0.update(message, sender).await
113    }
114
115    fn render(&mut self, sender: &ComponentSender<Self>) -> Result<(), Self::Error> {
116        let sender = &sender.0;
117        self.0.render(sender)
118    }
119
120    fn render_children(&mut self) -> Result<(), Self::Error> {
121        self.0.render_children()
122    }
123}
124
125impl<M, Ev, Err> Debug for BoxComponent<M, Ev, Err> {
126    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127        f.debug_struct("BoxComponent").finish_non_exhaustive()
128    }
129}