dioxus_shareables/
lib.rs

1//! Crate [`dioxus-shareables`](crate)
2//!
3//! This crate provides abstractions for global resource sharing in
4//! [`dioxus`](https://docs.rs/dioxus) similar to `fermi`, but with a slightly different data
5//! model, and some extensions for shared structures.
6//!
7//! The primary interfaces for the crate are [`Shared`], [`shareable_struct`] and [`List`]
8//!
9//! `dioxus` is still under development; if you're using the latest nightly version of `dioxus`
10//! then your `Cargo.toml` should look something like this:
11//! ```Cargo.toml
12//! ...
13//! [dependencies]
14//! ...
15//! dioxus-shareables = { version = "0.3.0", features = ["dixous-git"] }
16//! ...
17//! [replace]
18//! "dioxus-core:0.3.0" = { git = 'https://github.com/dioxuslabs/dioxus' }
19//! "dioxus-hooks:0.3.0" = { git = 'https://github.com/dioxuslabs/dioxus' }
20//!
21//! ```
22
23pub mod shared;
24pub use shared::Shared;
25
26pub mod list;
27pub use list::{List, ListEntry};
28
29#[doc(hidden)]
30pub mod r#struct;
31
32#[doc(hidden)]
33pub mod reexported {
34    pub use dioxus_core::Scope;
35    pub use parking_lot::Mutex;
36    pub use paste::paste;
37}
38
39#[doc(hidden)]
40mod sealed {
41    pub trait Flag {
42        const READ: bool;
43    }
44
45    pub trait InductiveMarkerTuple {
46        type __Base;
47        type __Step;
48        type __Decons;
49        fn __base(&self) -> Self::__Base;
50        fn __step(&self) -> Self::__Step;
51    }
52    macro_rules! impl_InductiveMarkerTuple_for {
53        () => {};
54        ($T:ident$($(,$U:ident$({$ct:tt})?)+)?) => {
55            impl<$T: Copy$($(,$U: Copy)+)?> InductiveMarkerTuple for ($($($U,)+)?$T,) {
56                type __Base = ($($($U,)+)?);
57                type __Step = $T;
58                type __Decons = super::Decons<Self::__Base, Self::__Step>;
59                fn __base(&self) -> Self::__Base {
60                    paste::paste! {
61                        let ($($([<__ $U:lower>],)+)?_,) = *self;
62                        $(($([<__ $U:lower>],)+))?
63                    }
64                }
65                fn __step(&self) -> Self::__Step {
66                    let ($($(_ $($ct)?,)+)?r,) = *self;
67                    r
68                }
69            }
70            impl_InductiveMarkerTuple_for! ($($($U),+)?);
71        }
72    }
73    impl_InductiveMarkerTuple_for!(
74        AA, AB, AC, AD, AE, AF, AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU, AV, AW,
75        AX, AY, AZ, BA, BB, BC, BD, BE, BF, BG, BH, BI, BJ, BK, BL, BM, BN, BO, BP, BQ, BR, BS, BT,
76        BU, BV, BW, BX, BY, BZ
77    );
78
79    pub trait InitType: Sized + Copy {
80        fn __init_field<P, T, S: crate::shared::Static<Type = T>>(
81            cx: &dioxus_core::Scope<P>,
82            _: &mut Option<crate::shared::Shared<T, Self>>,
83            _: S,
84        );
85        fn __share_field<T, S: crate::shared::Static<Type = T>>(
86            _: &mut Option<crate::Shared<T, Self>>,
87            _: S,
88        );
89    }
90    impl InitType for () {
91        fn __init_field<P, T, S: crate::shared::Static<Type = T>>(
92            _: &dioxus_core::Scope<P>,
93            _: &mut Option<crate::Shared<T, Self>>,
94            _: S,
95        ) {
96        }
97        fn __share_field<T, S: crate::shared::Static<Type = T>>(
98            _: &mut Option<crate::Shared<T, Self>>,
99            _: S,
100        ) {
101        }
102    }
103}
104/// A type flag for shared pointers.
105///
106/// This trait is implemented for [`W`] and [`RW`], the marker types which indicate the behavior of
107/// a [`Shared`] hook.
108pub trait Flag: sealed::Flag {}
109impl<T: sealed::Flag> Flag for T {}
110
111/// A type flag for fields in shared structures.
112///
113/// This trait is implemented for [`W`], [`RW`], and [`()`], so it is either a Flag or the unit
114/// type (which is used to indicate a field is not initialized.)
115pub trait InitType: sealed::InitType {
116    #[doc(hidden)]
117    fn init_field<P, T, S: shared::Static<Type = T>>(
118        cx: &dioxus_core::Scope<P>,
119        f: &mut Option<Shared<T, Self>>,
120        s: S,
121    ) {
122        Self::__init_field(cx, f, s)
123    }
124    #[doc(hidden)]
125    fn share_field<T, S: crate::shared::Static<Type = T>>(
126        f: &mut Option<crate::Shared<T, Self>>,
127        s: S,
128    ) {
129        Self::__share_field(f, s)
130    }
131}
132impl<T: sealed::InitType> InitType for T {}
133
134/// Marker for an access to shared data which is used for writing but not reading.
135///
136/// The primary promise for such an access is that it does not effect component display.
137#[derive(Clone, Copy)]
138pub struct W;
139impl sealed::Flag for W {
140    const READ: bool = false;
141}
142impl sealed::InitType for W {
143    fn __init_field<P, T, S: shared::Static<Type = T>>(
144        _: &dioxus_core::Scope<P>,
145        f: &mut Option<Shared<T, Self>>,
146        s: S,
147    ) {
148        if f.is_none() {
149            *f = Some(s._share());
150        }
151    }
152    fn __share_field<T, S: crate::shared::Static<Type = T>>(
153        f: &mut Option<crate::Shared<T, Self>>,
154        s: S,
155    ) {
156        if f.is_none() {
157            *f = Some(s._share());
158        }
159    }
160}
161
162/// Marker for an access to shared data which is used for reading.
163///
164/// Components which hold a `RW` handle are marked as needing update whenever that handle is
165/// written to.
166#[derive(Clone, Copy)]
167pub struct RW;
168impl sealed::Flag for RW {
169    const READ: bool = true;
170}
171impl sealed::InitType for RW {
172    fn __init_field<P, T, S: shared::Static<Type = T>>(
173        cx: &dioxus_core::Scope<P>,
174        f: &mut Option<Shared<T, Self>>,
175        s: S,
176    ) {
177        if f.is_none() {
178            let id = cx.scope_id().0;
179            let mut r = s._share();
180            r.id = Some(id);
181            r.link.add_listener(id, || cx.schedule_update());
182            // SAFETY:
183            //   * Shared<T, W> and Shared<T, RW> are layed out identically in memory.
184            *f = Some(unsafe { std::mem::transmute(r) });
185        }
186    }
187    fn __share_field<T, S: crate::shared::Static<Type = T>>(
188        _: &mut Option<crate::Shared<T, Self>>,
189        _: S,
190    ) {
191        unreachable!()
192    }
193}
194
195#[doc(hidden)]
196pub trait InductiveMarkerTuple: sealed::InductiveMarkerTuple {
197    type Base;
198    type Step;
199    type Decons;
200    fn base(&self) -> Self::Base;
201    fn step(&self) -> Self::Step;
202}
203impl<T: sealed::InductiveMarkerTuple> InductiveMarkerTuple for T {
204    type Base = T::__Base;
205    type Step = T::__Step;
206    type Decons = T::__Decons;
207    fn base(&self) -> Self::Base {
208        self.__base()
209    }
210    fn step(&self) -> Self::Step {
211        self.__step()
212    }
213}
214#[doc(hidden)]
215pub struct Decons<T, U>(T, U);