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}