1use std::{any::Any, marker::PhantomData, ptr, sync::Arc};
9
10use crate::runtime::{
11 FunctorHandle, invoke_callback_handle, invoke_callback_with_handle, invoke_render_slot_handle,
12 invoke_render_slot_with_handle, remember_callback_handle, remember_callback_with_handle,
13 remember_render_slot_handle, remember_render_slot_with_handle,
14 track_render_slot_read_dependency,
15};
16
17pub struct Slot<F: ?Sized> {
22 inner: Arc<F>,
23}
24
25impl<F: ?Sized> Slot<F> {
26 pub fn from_shared(handler: Arc<F>) -> Self {
28 Self { inner: handler }
29 }
30
31 pub fn shared(&self) -> Arc<F> {
33 Arc::clone(&self.inner)
34 }
35}
36
37impl<F: ?Sized> Clone for Slot<F> {
38 fn clone(&self) -> Self {
39 Self {
40 inner: Arc::clone(&self.inner),
41 }
42 }
43}
44
45impl<F: ?Sized> PartialEq for Slot<F> {
46 fn eq(&self, other: &Self) -> bool {
47 Arc::ptr_eq(&self.inner, &other.inner)
48 }
49}
50
51impl<F: ?Sized> Eq for Slot<F> {}
52
53#[derive(Clone, Copy)]
65pub struct Callback {
66 repr: CallbackRepr,
67}
68
69#[derive(Clone, Copy, Eq, PartialEq)]
70enum CallbackRepr {
71 Noop,
72 Handle(FunctorHandle),
73}
74
75impl Callback {
76 #[track_caller]
80 pub fn new<F>(handler: F) -> Self
81 where
82 F: Fn() + Send + Sync + 'static,
83 {
84 Self {
85 repr: CallbackRepr::Handle(remember_callback_handle(handler)),
86 }
87 }
88
89 pub const fn noop() -> Self {
91 Self {
92 repr: CallbackRepr::Noop,
93 }
94 }
95
96 pub fn call(&self) {
98 match self.repr {
99 CallbackRepr::Noop => {}
100 CallbackRepr::Handle(handle) => invoke_callback_handle(handle),
101 }
102 }
103}
104
105impl<F> From<F> for Callback
106where
107 F: Fn() + Send + Sync + 'static,
108{
109 fn from(handler: F) -> Self {
110 Self::new(handler)
111 }
112}
113
114impl Default for Callback {
115 fn default() -> Self {
116 Self::noop()
117 }
118}
119
120impl PartialEq for Callback {
121 fn eq(&self, other: &Self) -> bool {
122 self.repr == other.repr
123 }
124}
125
126impl Eq for Callback {}
127
128pub struct CallbackWith<T, R = ()> {
135 repr: CallbackWithRepr<T, R>,
136}
137
138enum CallbackWithRepr<T, R> {
139 Handle(FunctorHandle),
140 Static(fn(T) -> R),
141}
142
143impl<T, R> Copy for CallbackWithRepr<T, R> {}
144
145impl<T, R> Clone for CallbackWithRepr<T, R> {
146 fn clone(&self) -> Self {
147 *self
148 }
149}
150
151impl<T, R> CallbackWith<T, R>
152where
153 T: 'static,
154 R: 'static,
155{
156 #[track_caller]
160 pub fn new<F>(handler: F) -> Self
161 where
162 F: Fn(T) -> R + Send + Sync + 'static,
163 {
164 Self {
165 repr: CallbackWithRepr::Handle(remember_callback_with_handle(handler)),
166 }
167 }
168
169 pub fn call(&self, value: T) -> R {
171 match self.repr {
172 CallbackWithRepr::Handle(handle) => invoke_callback_with_handle(handle, value),
173 CallbackWithRepr::Static(handler) => handler(value),
174 }
175 }
176
177 fn from_static(handler: fn(T) -> R) -> Self {
178 Self {
179 repr: CallbackWithRepr::Static(handler),
180 }
181 }
182}
183
184impl<T, R, F> From<F> for CallbackWith<T, R>
185where
186 T: 'static,
187 R: 'static,
188 F: Fn(T) -> R + Send + Sync + 'static,
189{
190 fn from(handler: F) -> Self {
191 Self::new(handler)
192 }
193}
194
195impl<T, R> Copy for CallbackWith<T, R> {}
196
197impl<T, R> Clone for CallbackWith<T, R> {
198 fn clone(&self) -> Self {
199 *self
200 }
201}
202
203impl<T, R> PartialEq for CallbackWith<T, R> {
204 fn eq(&self, other: &Self) -> bool {
205 match (self.repr, other.repr) {
206 (CallbackWithRepr::Handle(lhs), CallbackWithRepr::Handle(rhs)) => lhs == rhs,
207 (CallbackWithRepr::Static(lhs), CallbackWithRepr::Static(rhs)) => {
208 ptr::fn_addr_eq(lhs, rhs)
209 }
210 _ => false,
211 }
212 }
213}
214
215impl<T, R> Eq for CallbackWith<T, R> {}
216
217impl<T, R> CallbackWith<T, R>
218where
219 T: 'static,
220 R: Default + 'static,
221{
222 pub fn default_value() -> Self {
225 fn default_value_impl<T, R: Default>(_: T) -> R {
226 R::default()
227 }
228
229 Self::from_static(default_value_impl::<T, R>)
230 }
231}
232
233impl<T> CallbackWith<T, T>
234where
235 T: 'static,
236{
237 pub fn identity() -> Self {
239 fn identity_impl<T>(value: T) -> T {
240 value
241 }
242
243 Self::from_static(identity_impl::<T>)
244 }
245}
246
247#[derive(Clone, Copy)]
258pub struct RenderSlot {
259 repr: RenderSlotRepr,
260}
261
262#[derive(Clone, Copy, Eq, PartialEq)]
263enum RenderSlotRepr {
264 Empty,
265 Handle(FunctorHandle),
266}
267
268impl RenderSlot {
269 #[track_caller]
273 pub fn new<F>(render: F) -> Self
274 where
275 F: Fn() + Send + Sync + 'static,
276 {
277 Self {
278 repr: RenderSlotRepr::Handle(remember_render_slot_handle(render)),
279 }
280 }
281
282 pub const fn empty() -> Self {
284 Self {
285 repr: RenderSlotRepr::Empty,
286 }
287 }
288
289 fn invoke(&self) {
290 match &self.repr {
291 RenderSlotRepr::Empty => {}
292 RenderSlotRepr::Handle(handle) => invoke_render_slot_handle(*handle),
293 }
294 }
295
296 pub fn render(&self) {
298 if let RenderSlotRepr::Handle(handle) = self.repr {
299 track_render_slot_read_dependency(handle);
300 }
301 self.invoke();
302 }
303}
304
305impl<F> From<F> for RenderSlot
306where
307 F: Fn() + Send + Sync + 'static,
308{
309 fn from(render: F) -> Self {
310 Self::new(render)
311 }
312}
313
314impl From<Callback> for RenderSlot {
315 fn from(callback: Callback) -> Self {
316 Self::new(move || callback.call())
317 }
318}
319
320impl Default for RenderSlot {
321 fn default() -> Self {
322 Self::empty()
323 }
324}
325
326impl PartialEq for RenderSlot {
327 fn eq(&self, other: &Self) -> bool {
328 match (&self.repr, &other.repr) {
329 (RenderSlotRepr::Empty, RenderSlotRepr::Empty) => true,
330 (RenderSlotRepr::Handle(lhs), RenderSlotRepr::Handle(rhs)) => lhs == rhs,
331 _ => false,
332 }
333 }
334}
335
336impl Eq for RenderSlot {}
337
338pub struct RenderSlotWith<T> {
343 handle: FunctorHandle,
344 marker: PhantomData<fn(T)>,
345}
346
347impl<T> RenderSlotWith<T> {
348 #[track_caller]
352 pub fn new<F>(render: F) -> Self
353 where
354 T: 'static,
355 F: Fn(T) + Send + Sync + 'static,
356 {
357 Self {
358 handle: remember_render_slot_with_handle(render),
359 marker: PhantomData,
360 }
361 }
362
363 pub fn render(&self, value: T)
365 where
366 T: 'static,
367 {
368 track_render_slot_read_dependency(self.handle);
369 invoke_render_slot_with_handle(self.handle, value)
370 }
371}
372
373impl<T, F> From<F> for RenderSlotWith<T>
374where
375 T: 'static,
376 F: Fn(T) + Send + Sync + 'static,
377{
378 fn from(render: F) -> Self {
379 Self::new(render)
380 }
381}
382
383impl<T> From<CallbackWith<T>> for RenderSlotWith<T>
384where
385 T: 'static,
386{
387 fn from(callback: CallbackWith<T>) -> Self {
388 Self::new(move |value| {
389 callback.call(value);
390 })
391 }
392}
393
394impl<T> Clone for RenderSlotWith<T> {
395 fn clone(&self) -> Self {
396 *self
397 }
398}
399
400impl<T> Copy for RenderSlotWith<T> {}
401
402impl<T> PartialEq for RenderSlotWith<T> {
403 fn eq(&self, other: &Self) -> bool {
404 self.handle == other.handle
405 }
406}
407
408impl<T> Eq for RenderSlotWith<T> {}
409
410pub trait Prop: Clone + Send + Sync + 'static {
412 fn prop_eq(&self, other: &Self) -> bool;
414}
415
416impl Prop for () {
417 fn prop_eq(&self, _other: &Self) -> bool {
418 true
419 }
420}
421
422pub trait ErasedProp: Send + Sync {
424 fn as_any(&self) -> &dyn Any;
426 fn clone_box(&self) -> Box<dyn ErasedProp>;
428 fn equals(&self, other: &dyn ErasedProp) -> bool;
430}
431
432impl<T> ErasedProp for T
433where
434 T: Prop,
435{
436 fn as_any(&self) -> &dyn Any {
437 self
438 }
439
440 fn clone_box(&self) -> Box<dyn ErasedProp> {
441 Box::new(self.clone())
442 }
443
444 fn equals(&self, other: &dyn ErasedProp) -> bool {
445 let Some(other) = other.as_any().downcast_ref::<T>() else {
446 return false;
447 };
448 self.prop_eq(other)
449 }
450}
451
452pub trait ErasedComponentRunner: Send + Sync {
454 fn run(&self, props: &dyn ErasedProp);
456}
457
458struct ComponentRunner<P: Prop> {
459 run_fn: fn(&P),
460}
461
462impl<P> ErasedComponentRunner for ComponentRunner<P>
463where
464 P: Prop,
465{
466 fn run(&self, props: &dyn ErasedProp) {
467 let Some(props) = props.as_any().downcast_ref::<P>() else {
468 panic!(
469 "component runner props type mismatch: expected {}",
470 std::any::type_name::<P>()
471 );
472 };
473 (self.run_fn)(props);
474 }
475}
476
477pub fn make_component_runner<P>(run_fn: fn(&P)) -> Arc<dyn ErasedComponentRunner>
479where
480 P: Prop,
481{
482 Arc::new(ComponentRunner { run_fn })
483}
484
485#[derive(Clone)]
487pub struct ComponentReplayData {
488 pub runner: Arc<dyn ErasedComponentRunner>,
490 pub props: Arc<dyn ErasedProp>,
492}
493
494impl ComponentReplayData {
495 pub fn new<P>(runner: Arc<dyn ErasedComponentRunner>, props: &P) -> Self
497 where
498 P: Prop,
499 {
500 Self {
501 runner,
502 props: Arc::new(props.clone()),
503 }
504 }
505}