1use std::{any::Any, marker::PhantomData, ptr, sync::Arc};
9
10use crate::{
11 runtime::{
12 FunctorHandle, invoke_callback_handle, invoke_callback_with_handle,
13 invoke_render_slot_handle, invoke_render_slot_with_handle, remember_callback_handle,
14 remember_callback_with_handle, remember_render_slot_handle,
15 remember_render_slot_with_handle, track_render_slot_read_dependency,
16 },
17 tessera,
18};
19
20pub struct Slot<F: ?Sized> {
25 inner: Arc<F>,
26}
27
28impl<F: ?Sized> Slot<F> {
29 pub fn from_shared(handler: Arc<F>) -> Self {
31 Self { inner: handler }
32 }
33
34 pub fn shared(&self) -> Arc<F> {
36 Arc::clone(&self.inner)
37 }
38}
39
40impl<F: ?Sized> Clone for Slot<F> {
41 fn clone(&self) -> Self {
42 Self {
43 inner: Arc::clone(&self.inner),
44 }
45 }
46}
47
48impl<F: ?Sized> PartialEq for Slot<F> {
49 fn eq(&self, other: &Self) -> bool {
50 Arc::ptr_eq(&self.inner, &other.inner)
51 }
52}
53
54impl<F: ?Sized> Eq for Slot<F> {}
55
56#[derive(Clone, Copy)]
64pub struct Callback {
65 repr: CallbackRepr,
66}
67
68#[derive(Clone, Copy, Eq, PartialEq)]
69enum CallbackRepr {
70 Noop,
71 Handle(FunctorHandle),
72}
73
74impl Callback {
75 #[track_caller]
79 pub fn new<F>(handler: F) -> Self
80 where
81 F: Fn() + Send + Sync + 'static,
82 {
83 Self {
84 repr: CallbackRepr::Handle(remember_callback_handle(handler)),
85 }
86 }
87
88 pub const fn noop() -> Self {
90 Self {
91 repr: CallbackRepr::Noop,
92 }
93 }
94
95 pub fn call(&self) {
97 match self.repr {
98 CallbackRepr::Noop => {}
99 CallbackRepr::Handle(handle) => invoke_callback_handle(handle),
100 }
101 }
102}
103
104impl<F> From<F> for Callback
105where
106 F: Fn() + Send + Sync + 'static,
107{
108 fn from(handler: F) -> Self {
109 Self::new(handler)
110 }
111}
112
113impl Default for Callback {
114 fn default() -> Self {
115 Self::noop()
116 }
117}
118
119impl PartialEq for Callback {
120 fn eq(&self, other: &Self) -> bool {
121 self.repr == other.repr
122 }
123}
124
125impl Eq for Callback {}
126
127pub struct CallbackWith<T, R = ()> {
134 repr: CallbackWithRepr<T, R>,
135}
136
137enum CallbackWithRepr<T, R> {
138 Handle(FunctorHandle),
139 Static(fn(T) -> R),
140}
141
142impl<T, R> Copy for CallbackWithRepr<T, R> {}
143
144impl<T, R> Clone for CallbackWithRepr<T, R> {
145 fn clone(&self) -> Self {
146 *self
147 }
148}
149
150impl<T, R> CallbackWith<T, R>
151where
152 T: 'static,
153 R: 'static,
154{
155 #[track_caller]
159 pub fn new<F>(handler: F) -> Self
160 where
161 F: Fn(T) -> R + Send + Sync + 'static,
162 {
163 Self {
164 repr: CallbackWithRepr::Handle(remember_callback_with_handle(handler)),
165 }
166 }
167
168 pub fn call(&self, value: T) -> R {
170 match self.repr {
171 CallbackWithRepr::Handle(handle) => invoke_callback_with_handle(handle, value),
172 CallbackWithRepr::Static(handler) => handler(value),
173 }
174 }
175
176 fn from_static(handler: fn(T) -> R) -> Self {
177 Self {
178 repr: CallbackWithRepr::Static(handler),
179 }
180 }
181}
182
183impl<T, R, F> From<F> for CallbackWith<T, R>
184where
185 T: 'static,
186 R: 'static,
187 F: Fn(T) -> R + Send + Sync + 'static,
188{
189 fn from(handler: F) -> Self {
190 Self::new(handler)
191 }
192}
193
194impl<T, R> Copy for CallbackWith<T, R> {}
195
196impl<T, R> Clone for CallbackWith<T, R> {
197 fn clone(&self) -> Self {
198 *self
199 }
200}
201
202impl<T, R> PartialEq for CallbackWith<T, R> {
203 fn eq(&self, other: &Self) -> bool {
204 match (self.repr, other.repr) {
205 (CallbackWithRepr::Handle(lhs), CallbackWithRepr::Handle(rhs)) => lhs == rhs,
206 (CallbackWithRepr::Static(lhs), CallbackWithRepr::Static(rhs)) => {
207 ptr::fn_addr_eq(lhs, rhs)
208 }
209 _ => false,
210 }
211 }
212}
213
214impl<T, R> Eq for CallbackWith<T, R> {}
215
216impl<T, R> CallbackWith<T, R>
217where
218 T: 'static,
219 R: Default + 'static,
220{
221 pub fn default_value() -> Self {
224 fn default_value_impl<T, R: Default>(_: T) -> R {
225 R::default()
226 }
227
228 Self::from_static(default_value_impl::<T, R>)
229 }
230}
231
232impl<T> CallbackWith<T, T>
233where
234 T: 'static,
235{
236 pub fn identity() -> Self {
238 fn identity_impl<T>(value: T) -> T {
239 value
240 }
241
242 Self::from_static(identity_impl::<T>)
243 }
244}
245
246#[derive(Clone, Copy)]
284pub struct RenderSlot {
285 repr: RenderSlotRepr,
286}
287
288#[derive(Clone, Copy, Eq, PartialEq)]
289enum RenderSlotRepr {
290 Empty,
291 Handle(FunctorHandle),
292}
293
294impl RenderSlot {
295 #[track_caller]
299 pub fn new<F, Output>(render: F) -> Self
300 where
301 F: Fn() -> Output + Send + Sync + 'static,
302 {
303 Self {
304 repr: RenderSlotRepr::Handle(remember_render_slot_handle(move || {
305 render();
306 })),
307 }
308 }
309
310 pub const fn empty() -> Self {
312 Self {
313 repr: RenderSlotRepr::Empty,
314 }
315 }
316
317 pub fn render(&self) {
321 match self.repr {
322 RenderSlotRepr::Empty => {}
323 RenderSlotRepr::Handle(handle) => {
324 render_slot_boundary(handle).props.execute_now();
325 }
326 }
327 }
328}
329
330#[tessera(crate)]
331fn render_slot_boundary(handle: FunctorHandle) {
332 track_render_slot_read_dependency(handle);
333 invoke_render_slot_handle(handle);
334}
335
336impl<F, Output> From<F> for RenderSlot
337where
338 F: Fn() -> Output + Send + Sync + 'static,
339{
340 fn from(render: F) -> Self {
341 Self::new(render)
342 }
343}
344
345impl From<Callback> for RenderSlot {
346 fn from(callback: Callback) -> Self {
347 Self::new(move || callback.call())
348 }
349}
350
351impl Default for RenderSlot {
352 fn default() -> Self {
353 Self::empty()
354 }
355}
356
357impl PartialEq for RenderSlot {
358 fn eq(&self, other: &Self) -> bool {
359 match (&self.repr, &other.repr) {
360 (RenderSlotRepr::Empty, RenderSlotRepr::Empty) => true,
361 (RenderSlotRepr::Handle(lhs), RenderSlotRepr::Handle(rhs)) => lhs == rhs,
362 _ => false,
363 }
364 }
365}
366
367impl Eq for RenderSlot {}
368
369pub struct RenderSlotWith<T> {
374 handle: FunctorHandle,
375 marker: PhantomData<fn(T)>,
376}
377
378impl<T> RenderSlotWith<T> {
379 #[track_caller]
383 pub fn new<F, Output>(render: F) -> Self
384 where
385 T: 'static,
386 F: Fn(T) -> Output + Send + Sync + 'static,
387 {
388 Self {
389 handle: remember_render_slot_with_handle(move |value| {
390 render(value);
391 }),
392 marker: PhantomData,
393 }
394 }
395
396 pub fn render(&self, value: T)
400 where
401 T: Clone + PartialEq + Send + Sync + 'static,
402 {
403 render_slot_with_boundary(self.handle, value)
404 .props
405 .execute_now();
406 }
407}
408
409#[tessera(crate)]
410fn render_slot_with_boundary<T>(handle: FunctorHandle, value: T)
411where
412 T: Clone + PartialEq + Send + Sync + 'static,
413{
414 track_render_slot_read_dependency(handle);
415 invoke_render_slot_with_handle(handle, value)
416}
417
418impl<T, F, Output> From<F> for RenderSlotWith<T>
419where
420 T: 'static,
421 F: Fn(T) -> Output + Send + Sync + 'static,
422{
423 fn from(render: F) -> Self {
424 Self::new(render)
425 }
426}
427
428impl<T> From<CallbackWith<T>> for RenderSlotWith<T>
429where
430 T: 'static,
431{
432 fn from(callback: CallbackWith<T>) -> Self {
433 Self::new(move |value| {
434 callback.call(value);
435 })
436 }
437}
438
439impl<T> Clone for RenderSlotWith<T> {
440 fn clone(&self) -> Self {
441 *self
442 }
443}
444
445impl<T> Copy for RenderSlotWith<T> {}
446
447impl<T> PartialEq for RenderSlotWith<T> {
448 fn eq(&self, other: &Self) -> bool {
449 self.handle == other.handle
450 }
451}
452
453impl<T> Eq for RenderSlotWith<T> {}
454
455pub trait Prop: Clone + Send + Sync + 'static {
457 fn prop_eq(&self, other: &Self) -> bool;
459 fn run_component(self: Arc<Self>);
461}
462
463pub(crate) trait ErasedComponent: Send + Sync {
464 fn as_any(&self) -> &dyn Any;
465 fn as_any_mut(&mut self) -> &mut dyn Any;
466 fn equals(&self, other: &dyn ErasedComponent) -> bool;
467 fn run(self: Arc<Self>);
468}
469
470impl<T> ErasedComponent for T
471where
472 T: Prop,
473{
474 fn as_any(&self) -> &dyn Any {
475 self
476 }
477
478 fn as_any_mut(&mut self) -> &mut dyn Any {
479 self
480 }
481
482 fn equals(&self, other: &dyn ErasedComponent) -> bool {
483 let Some(other) = other.as_any().downcast_ref::<T>() else {
484 return false;
485 };
486 self.prop_eq(other)
487 }
488 fn run(self: Arc<Self>) {
489 self.run_component();
490 }
491}