tawasuyu

tawasuyu/llimphi

Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.

Rust 229TOML 101Markdown 82Shell 24052 Definitions

⎇ main llimphi-despacho/src/lib.rs Rust · 88 lines · 3.7 KB History Who touched what raw

chore: refresco desde el monorepo — 128 miembros, los 76 widgets y los 11 módulos b3f12e136 · Sergio ·

1//! **«Mandale este mensaje al bucle»** — sin decir cuál bucle.
2//!
3//! Un `llimphi_ui::Handle<Msg>` es dos cosas pegadas: la capacidad de despachar
4//! un mensaje, y el bucle de escritorio que lo hospeda. Todo lo que quiere la
5//! primera se lleva la segunda de arriba, y con ella winit, wgpu y el backend
6//! `vello` — que es **excluyente** con el de una app enjaulada.
7//!
8//! Eso ya mordió, y de la forma más tonta: `llimphi-motion` existe para
9//! interpolar números y depende de `llimphi-ui` por **una línea**
10//! (`handle.dispatch`), así que los 39 crates que animan un color quedaban
11//! atados al escritorio.
12//!
13//! Acá está esa línea sola. Es el mismo movimiento que ya se hizo dos veces en
14//! esta familia —`llimphi-entrada` para el input, `llimphi-reproductor` para el
15//! dibujo—: una capacidad no tiene por qué saber quién la hospeda.
16//!
17//! ## Qué NO es
18//!
19//! No es un ejecutor ni una cola. `despachar` puede encolar, mandar por un canal
20//! o escribir en un socket; quien lo implementa decide. Lo único que promete es
21//! que el mensaje llega al `update` de alguien, alguna vez.
22
23#![no_std]
24#![forbid(unsafe_code)]
25
26extern crate alloc;
27
28/// Algo que sabe hacerle llegar un `Msg` a un bucle Elm.
29///
30/// Deliberadamente sin supertraits: `Send`/`Sync`/`Clone` se piden **donde hacen
31/// falta** (animar necesita clonar hacia un hilo; despachar desde el `update` no
32/// necesita nada). Ponerlos acá obligaría a todo implementador a cumplirlos
33/// aunque su caso no los use.
34pub trait Despachador<Msg> {
35    /// Hacele llegar `msg` al bucle. No bloquea ni garantiza cuándo.
36    fn despachar(&self, msg: Msg);
37
38    /// Corré `trabajo` **fuera del bucle** y despachá lo que devuelva.
39    ///
40    /// Es la otra mitad de lo que una app le pide a su anfitrión: guardar un
41    /// archivo, esperar una respuesta del LSP. La firma es la de
42    /// `llimphi_ui::Handle::spawn` a propósito — quien la tenía no cambia.
43    ///
44    /// **El default corre el trabajo AHÍ MISMO**, y eso es correcto aunque
45    /// bloquee: un anfitrión sin hilos —o un test— tiene que ejecutar el efecto
46    /// igual. Lo que no sería correcto es tirarlo en silencio y que el archivo
47    /// no se guarde sin que nadie se entere.
48    fn lanzar(&self, trabajo: alloc::boxed::Box<dyn FnOnce() -> Msg + Send + 'static>) {
49        self.despachar(trabajo())
50    }
51}
52
53/// Un despachador detrás de un puntero sigue siendo un despachador.
54///
55/// Existe para que `Arc<dyn Despachador<Msg>>` —la forma que necesita quien
56/// quiera guardarlo y clonarlo hacia un hilo— se pueda usar donde se pide un
57/// `D: Despachador<Msg>`. Sin este impl, cada consumidor escribiría su propio
58/// reenvío.
59impl<Msg, D: Despachador<Msg> + ?Sized> Despachador<Msg> for &D {
60    fn despachar(&self, msg: Msg) {
61        (**self).despachar(msg)
62    }
63    fn lanzar(&self, trabajo: alloc::boxed::Box<dyn FnOnce() -> Msg + Send + 'static>) {
64        (**self).lanzar(trabajo)
65    }
66}
67
68impl<Msg, D: Despachador<Msg> + ?Sized> Despachador<Msg> for alloc::sync::Arc<D> {
69    fn despachar(&self, msg: Msg) {
70        (**self).despachar(msg)
71    }
72    fn lanzar(&self, trabajo: alloc::boxed::Box<dyn FnOnce() -> Msg + Send + 'static>) {
73        (**self).lanzar(trabajo)
74    }
75}
76
77/// El que tira todo lo que le mandan.
78///
79/// Para tests y para el arranque, donde el bucle todavía no existe. Está acá y
80/// no en cada crate porque un «despachador de mentira» escrito a las apuradas
81/// suele ser el que se cuela en producción: si va a haber uno, que sea éste, con
82/// el nombre diciendo lo que hace.
83#[derive(Debug, Clone, Copy, Default)]
84pub struct AlVacio;
85
86impl<Msg> Despachador<Msg> for AlVacio {
87    fn despachar(&self, _msg: Msg) {}
88}