Skip to main content

topcoat_runtime/
signal.rs

1use std::{iter::empty, ops::Deref};
2
3use serde::{Deserialize, Serialize, de::DeserializeOwned};
4use topcoat_core::context::Cx;
5use topcoat_view::{NodeViewParts, PartsWriter};
6use uuid::Uuid;
7
8use crate::{Surrogate, Surrogated};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(transparent)]
12pub struct SignalId(Uuid);
13
14impl SignalId {
15    #[inline]
16    #[must_use]
17    pub fn new() -> Self {
18        Self(Uuid::new_v4())
19    }
20}
21
22impl Default for SignalId {
23    #[inline]
24    fn default() -> Self {
25        Self::new()
26    }
27}
28
29impl std::fmt::Display for SignalId {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        self.0.fmt(f)
32    }
33}
34
35#[derive(Debug)]
36pub struct Signal<T> {
37    id: SignalId,
38    value: T,
39}
40
41impl<T> Signal<T> {
42    #[inline]
43    pub fn new(value: T) -> Self {
44        Self {
45            id: SignalId::new(),
46            value,
47        }
48    }
49
50    pub(crate) fn id(&self) -> SignalId {
51        self.id
52    }
53
54    pub(crate) fn read(&self) -> &T {
55        &self.value
56    }
57}
58
59impl<T> Signal<T>
60where
61    T: Clone,
62{
63    pub(crate) fn get(&self) -> T {
64        self.value.clone()
65    }
66}
67
68pub struct SignalDeclaration<'a, T>(&'a Signal<T>);
69
70impl<'a, T> SignalDeclaration<'a, T> {
71    #[inline]
72    pub fn new(signal: &'a Signal<T>) -> Self {
73        Self(signal)
74    }
75}
76
77impl<T> NodeViewParts for SignalDeclaration<'_, T>
78where
79    for<'a> &'a T: Surrogated,
80    for<'a> <&'a T as Surrogated>::Surrogate: Serialize,
81{
82    fn into_view_parts(self, _cx: &Cx, parts: &mut PartsWriter<'_>) {
83        #[derive(Serialize)]
84        struct SignalDeclarationPayload<'a, V>
85        where
86            V: ?Sized,
87        {
88            t: &'static str,
89            id: std::string::String,
90            v: &'a V,
91        }
92
93        let value = (&self.0.value).into_surrogate();
94        let payload = SignalDeclarationPayload {
95            t: "signal",
96            id: self.0.id().to_string(),
97            v: &value,
98        };
99        let json = serde_json::to_string(&payload)
100            .expect("failed to serialize signal declaration payload");
101
102        parts.push_str_unescaped("<!-- ::topcoat::signal(");
103        parts.push_str_unescaped(json);
104        parts.push_str_unescaped(") -->");
105    }
106}
107
108#[derive(Debug, Clone)]
109pub struct ReadSignal<T> {
110    id: SignalId,
111    value: T,
112}
113
114impl<T> ReadSignal<T> {
115    pub fn new(signal: &Signal<T>) -> Self
116    where
117        T: Clone,
118    {
119        Self {
120            id: signal.id,
121            value: signal.value.clone(),
122        }
123    }
124
125    pub fn id(&self) -> SignalId {
126        self.id
127    }
128}
129
130impl<T> Deref for ReadSignal<T> {
131    type Target = T;
132
133    fn deref(&self) -> &Self::Target {
134        &self.value
135    }
136}
137
138impl<'de, T> Deserialize<'de> for ReadSignal<T>
139where
140    T: Surrogated,
141    T::Surrogate: Deserialize<'de>,
142{
143    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
144    where
145        D: serde::Deserializer<'de>,
146    {
147        #[derive(Deserialize)]
148        #[serde(deny_unknown_fields)]
149        struct EncodedReadSignal<S> {
150            id: SignalId,
151            value: S,
152        }
153
154        let encoded = EncodedReadSignal::<T::Surrogate>::deserialize(deserializer)?;
155        Ok(Self {
156            id: encoded.id,
157            value: encoded.value.into_real(),
158        })
159    }
160}
161
162pub trait Signals: Sized {
163    fn ids(&self) -> impl Iterator<Item = SignalId>;
164    fn decode(encoded_signals: EncodedSignals) -> Self;
165}
166
167impl Signals for () {
168    fn ids(&self) -> impl Iterator<Item = SignalId> {
169        empty()
170    }
171
172    fn decode(_encoded_signals: EncodedSignals) -> Self {}
173}
174
175macro_rules! impl_signals_for_tuple {
176    ($($n:tt $t:ident),+) => {
177        impl<$($t),+> Signals for ($(ReadSignal<$t>,)+)
178        where
179            $(
180                $t: Surrogated,
181                <$t as Surrogated>::Surrogate: DeserializeOwned,
182            )+
183        {
184            fn ids(&self) -> impl Iterator<Item = SignalId> {
185                [$(self.$n.id),+].into_iter()
186            }
187
188            fn decode(encoded_signals: EncodedSignals) -> Self {
189                serde_json::from_str(&encoded_signals.0).unwrap()
190            }
191        }
192    };
193}
194
195impl_signals_for_tuple!(0 T0);
196impl_signals_for_tuple!(0 T0, 1 T1);
197impl_signals_for_tuple!(0 T0, 1 T1, 2 T2);
198impl_signals_for_tuple!(0 T0, 1 T1, 2 T2, 3 T3);
199impl_signals_for_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4);
200impl_signals_for_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5);
201impl_signals_for_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6);
202impl_signals_for_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7);
203impl_signals_for_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8);
204impl_signals_for_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9);
205impl_signals_for_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10);
206impl_signals_for_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10, 11 T11);
207
208pub struct EncodedSignals(String);
209
210impl EncodedSignals {
211    pub fn new(inner: impl Into<String>) -> Self {
212        Self(inner.into())
213    }
214}