ferroui_reactive/linq/
dematerialize.rs1use crate::internal::{impl_sink_dispose, unary, OperatorSink, Sink};
4use crate::notification::Notification;
5use ferroui_system::{IObservable, IObserver, ObservableError};
6use std::rc::Rc;
7
8pub trait NotificationValue: 'static {
12 type Value: 'static;
14
15 fn into_notification(self) -> Notification<Self::Value>;
17}
18
19impl<T: 'static> NotificationValue for Notification<T> {
20 type Value = T;
21
22 fn into_notification(self) -> Notification<T> {
23 self
24 }
25}
26
27struct DematerializeSink<N: NotificationValue> {
30 sink: Sink<N::Value>,
31}
32
33impl<N: NotificationValue> OperatorSink<N, N::Value> for DematerializeSink<N> {
34 fn sink(&self) -> &Sink<N::Value> {
35 &self.sink
36 }
37}
38
39impl_sink_dispose!(DematerializeSink<N> where N: NotificationValue);
40
41impl<N: NotificationValue> IObserver<N> for DematerializeSink<N> {
42 fn on_next(&self, value: N) {
43 match value.into_notification() {
44 Notification::OnNext(value) => self.sink.forward_on_next(value),
45 Notification::OnError(error) => self.sink.forward_on_error(error),
46 Notification::OnCompleted => self.sink.forward_on_completed(),
47 }
48 }
49
50 fn on_error(&self, error: ObservableError) {
51 self.sink.forward_on_error(error);
52 }
53
54 fn on_completed(&self) {
55 self.sink.forward_on_completed();
56 }
57}
58
59pub(crate) fn dematerialize<N: NotificationValue>(source: Rc<dyn IObservable<N>>) -> Rc<dyn IObservable<N::Value>> {
60 unary(source, |observer| Rc::new(DematerializeSink::<N> { sink: Sink::new(observer) }))
65}
66
67macro_rules! dematerialize_methods {
69 () => {
70 fn dematerialize(
74 &self,
75 ) -> std::rc::Rc<dyn ferroui_system::IObservable<<T as crate::linq::dematerialize::NotificationValue>::Value>>
76 where
77 T: crate::linq::dematerialize::NotificationValue,
78 {
79 crate::linq::dematerialize::dematerialize(self.observable())
80 }
81 };
82}
83pub(crate) use dematerialize_methods;