flourish_unsend/lib.rs
1#![warn(clippy::pedantic)]
2#![warn(missing_docs)]
3#![warn(unreachable_pub)]
4// #![warn(clippy::single_call_fn)]
5//! <details><summary>README / Quick Start (click to expand)</summary>
6//!
7#![cfg_attr(feature = "_doc", doc = include_str!("../README.md"))]
8//!
9//! </details>
10//!
11//! # Safety Notes
12//!
13//! [`impl FnMut`](`FnMut`) closures that appear in parameters with "`fn_pin`" in their name are guaranteed to be [pinned](`core::pin`) when called.
14
15pub mod conversions;
16mod opaque;
17
18mod signal;
19pub use signal::{Signal, SignalDyn, SignalDynCell};
20
21pub mod unmanaged;
22
23//TODO: Inter-runtime signals (i.e. takes two signals runtimes as parameters, acts as source for one and dynamic subscriber for the other).
24
25mod signal_arc;
26pub use signal_arc::{
27 SignalArc, SignalArcDyn, SignalArcDynCell, SignalWeak, SignalWeakDyn, SignalWeakDynCell,
28};
29
30mod subscription;
31pub use subscription::{Subscription, SubscriptionDyn, SubscriptionDynCell};
32
33mod effect;
34pub use effect::Effect;
35
36mod traits;
37pub use traits::Guard;
38
39pub use isoprenoid_unsend::runtime::{LocalSignalsRuntime, Propagation, SignalsRuntimeRef};
40
41pub mod prelude {
42 //! Unmanaged signal accessors and [`SignalsRuntimeRef`].
43 //! Not necessary to use managed signals.
44
45 pub use crate::{
46 unmanaged::{UnmanagedSignal, UnmanagedSignalCell},
47 SignalsRuntimeRef,
48 };
49}
50
51#[doc(hidden)]
52pub mod __ {
53 pub use super::unmanaged::{
54 raw_effect::new_raw_unsubscribed_effect,
55 raw_subscription::{
56 new_raw_unsubscribed_subscription, pin_into_pin_impl_source, pull_new_subscription,
57 },
58 };
59}
60
61/// Shadows each identifier in place with its [`Clone::clone`].
62///
63/// This is useful to duplicate smart pointers:
64///
65/// ```
66/// # {
67/// # #![cfg(feature = "local_signals_runtime")] // flourish feature
68/// use flourish_unsend::{shadow_clone, LocalSignalsRuntime};
69///
70/// type Signal<T, S> = flourish_unsend::Signal<T, S, LocalSignalsRuntime>;
71///
72/// let a = Signal::cell(1);
73/// let b = Signal::cell(2);
74/// let c = Signal::computed({
75/// shadow_clone!(a, b);
76/// move || a.get() + b.get()
77/// });
78///
79/// drop((a, b, c));
80/// # }
81/// ```
82#[macro_export]
83macro_rules! shadow_clone {
84 ($ident:ident$(,)?) => {
85 // This would warn because of extra parentheses… and it's fewer tokens.
86 let $ident = ::std::clone::Clone::clone(&$ident);
87 };
88 ($($ident:ident),*$(,)?) => {
89 let ($($ident),*) = ($(::std::clone::Clone::clone(&$ident)),*);
90 };
91}
92
93/// Shadows each reference in place with its [`ToOwned::Owned`].
94///
95/// This is useful to upgrade and persist borrows:
96///
97/// ```
98/// use std::ops::Add;
99/// use flourish_unsend::{prelude::*, shadow_ref_to_owned, Signal, SignalArc, SignalDyn};
100///
101/// fn live_sum<'a, SR: 'a + SignalsRuntimeRef>(
102/// a: &SignalDyn<'a, u64, SR>,
103/// b: &SignalDyn<'a, u64, SR>,
104/// ) -> SignalArc<u64, impl 'a + UnmanagedSignal<u64, SR>, SR> {
105/// Signal::computed_with_runtime({
106/// shadow_ref_to_owned!(a, b);
107/// move || a.get() + b.get()
108/// }, a.clone_runtime_ref())
109/// }
110/// ```
111#[macro_export]
112macro_rules! shadow_ref_to_owned {
113 ($ident:ident$(,)?) => {
114 // This would warn because of extra parentheses… and it's fewer tokens.
115 let $ident = ::std::borrow::ToOwned::to_owned($ident);
116 };
117 ($($ident:ident),*$(,)?) => {
118 let ($($ident),*) = ($(::std::borrow::ToOwned::to_owned($ident)),*);
119 };
120}