Skip to content

Commit dfed5bf

Browse files
committed
Add CowSignal, but it is unused
1 parent b4b5f22 commit dfed5bf

File tree

7 files changed

+210
-39
lines changed

7 files changed

+210
-39
lines changed

rsact-reactive/src/cow.rs

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use crate::{
2+
maybe::{IntoMaybeReactive, MaybeReactive},
3+
read::ReadSignal,
4+
signal::{create_signal, Signal},
5+
write::{SignalSetter, WriteSignal},
6+
ReactiveValue,
7+
};
8+
9+
/// Clone On Write signal mooooo
10+
/// Works similar to alloc::borrow::Cow, but Borrowed variant is a Memo (or readonly Signal) and Owned value is a signal.
11+
#[derive(Clone, Debug, PartialEq)]
12+
pub enum CowSignal<T: PartialEq + Clone + 'static> {
13+
Borrowed(MaybeReactive<T>),
14+
Owned(Signal<T>),
15+
}
16+
17+
impl<T: PartialEq + Clone + 'static> CowSignal<T> {
18+
pub fn new_owned(signal: Signal<T>) -> Self {
19+
Self::Owned(signal)
20+
}
21+
22+
pub fn new_borrowed(memo: impl IntoMaybeReactive<T>) -> Self {
23+
Self::Borrowed(memo.maybe_reactive())
24+
}
25+
}
26+
27+
impl<T: PartialEq + Clone + 'static> CowSignal<T> {
28+
pub fn to_mut(&mut self) -> Signal<T> {
29+
match self {
30+
CowSignal::Borrowed(memo) => {
31+
let signal = create_signal(memo.get_cloned());
32+
*self = CowSignal::Owned(signal);
33+
signal
34+
},
35+
CowSignal::Owned(signal) => *signal,
36+
}
37+
}
38+
}
39+
40+
impl<T: PartialEq + Clone + 'static> ReadSignal<T> for CowSignal<T> {
41+
fn track(&self) {
42+
match self {
43+
CowSignal::Borrowed(memo) => memo.track(),
44+
CowSignal::Owned(signal) => signal.track(),
45+
}
46+
}
47+
48+
fn with_untracked<U>(&self, f: impl FnOnce(&T) -> U) -> U {
49+
match self {
50+
CowSignal::Borrowed(memo) => memo.with_untracked(f),
51+
CowSignal::Owned(signal) => signal.with_untracked(f),
52+
}
53+
}
54+
}
55+
56+
impl<T: PartialEq + Clone + 'static> WriteSignal<T> for CowSignal<T> {
57+
/// Notify subscribers about changes. No op for CowSignal storing Borrowed data!
58+
fn notify(&self) {
59+
match self {
60+
CowSignal::Borrowed(_) => {},
61+
CowSignal::Owned(signal) => signal.notify(),
62+
}
63+
}
64+
65+
fn update_untracked<U>(&mut self, f: impl FnOnce(&mut T) -> U) -> U {
66+
self.to_mut().update_untracked(f)
67+
}
68+
}
69+
70+
// impl<T: PartialEq + Clone + 'static> SignalMap<T> for CowSignal<T> {
71+
// type Output<U: PartialEq + 'static> = Memo<U>;
72+
73+
// fn map<U: PartialEq + 'static>(
74+
// &self,
75+
// map: impl FnMut(&T) -> U + 'static,
76+
// ) -> Self::Output<U> {
77+
// match self {
78+
// CowSignal::Borrowed(mr) => mr.map(map),
79+
// CowSignal::Owned(signal) => signal.map(map),
80+
// }
81+
// }
82+
// }
83+
84+
impl<T: PartialEq + Clone + 'static, S: ReactiveValue> SignalSetter<T, S>
85+
for CowSignal<T>
86+
where
87+
Signal<T>: SignalSetter<T, S>,
88+
{
89+
fn setter(
90+
&mut self,
91+
source: S,
92+
set_map: impl FnMut(&mut T, &<S as ReactiveValue>::Value) + 'static,
93+
) {
94+
self.to_mut().setter(source, set_map);
95+
}
96+
}

rsact-reactive/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ extern crate alloc;
77

88
mod callback;
99
pub mod computed;
10+
pub mod cow;
1011
pub mod eco;
1112
pub mod effect;
1213
pub mod maybe;
@@ -23,6 +24,7 @@ pub mod write;
2324

2425
pub mod prelude {
2526
pub use super::{
27+
cow::CowSignal,
2628
effect::{create_effect, Effect},
2729
maybe::{
2830
Inert, IntoInert, IntoMaybeSignal, MaybeReactive, MaybeSignal,

rsact-reactive/src/maybe.rs

+60-31
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,11 @@ impl<T> IntoInert<T> for T {
122122
/// For RW version of [`MaybeReactive`] see [`MaybeSignal`]
123123
pub enum MaybeReactive<T: PartialEq + 'static> {
124124
Inert(Inert<T>),
125+
// TODO: Remove Signal, Memo can now store signals
125126
Signal(Signal<T>),
126127
Memo(Memo<T>),
127128
MemoChain(MemoChain<T>),
128-
Derived(Rc<RefCell<dyn FnMut() -> T>>),
129+
// Derived(Rc<RefCell<dyn FnMut() -> T>>),
129130
}
130131

131132
impl_read_signal_traits!(MaybeReactive<T>: PartialEq);
@@ -135,9 +136,9 @@ impl<T: PartialEq + 'static> MaybeReactive<T> {
135136
Self::Inert(value.inert())
136137
}
137138

138-
pub fn new_derived(f: impl FnMut() -> T + 'static) -> Self {
139-
Self::Derived(Rc::new(RefCell::new(f)))
140-
}
139+
// pub fn new_derived(f: impl FnMut() -> T + 'static) -> Self {
140+
// Self::Derived(Rc::new(RefCell::new(f)))
141+
// }
141142
}
142143

143144
impl<T: PartialEq + 'static> ReactiveValue for MaybeReactive<T> {
@@ -150,7 +151,7 @@ impl<T: PartialEq + 'static> ReactiveValue for MaybeReactive<T> {
150151
MaybeReactive::Signal(signal) => signal.is_alive(),
151152
MaybeReactive::Memo(memo) => memo.is_alive(),
152153
MaybeReactive::MemoChain(memo_chain) => memo_chain.is_alive(),
153-
MaybeReactive::Derived(_) => true,
154+
// MaybeReactive::Derived(_) => true,
154155
}
155156
}
156157

@@ -161,7 +162,7 @@ impl<T: PartialEq + 'static> ReactiveValue for MaybeReactive<T> {
161162
MaybeReactive::Signal(signal) => signal.dispose(),
162163
MaybeReactive::Memo(memo) => memo.dispose(),
163164
MaybeReactive::MemoChain(memo_chain) => memo_chain.dispose(),
164-
MaybeReactive::Derived(derived) => core::mem::drop(derived),
165+
// MaybeReactive::Derived(derived) => core::mem::drop(derived),
165166
}
166167
}
167168
}
@@ -174,7 +175,7 @@ impl<T: PartialEq + 'static> ReadSignal<T> for MaybeReactive<T> {
174175
MaybeReactive::Signal(signal) => signal.track(),
175176
MaybeReactive::Memo(memo) => memo.track(),
176177
MaybeReactive::MemoChain(memo_chain) => memo_chain.track(),
177-
MaybeReactive::Derived(_) => {},
178+
// MaybeReactive::Derived(_) => {},
178179
}
179180
}
180181

@@ -187,7 +188,7 @@ impl<T: PartialEq + 'static> ReadSignal<T> for MaybeReactive<T> {
187188
MaybeReactive::MemoChain(memo_chain) => {
188189
memo_chain.with_untracked(f)
189190
},
190-
MaybeReactive::Derived(derived) => f(&derived.borrow_mut()()),
191+
// MaybeReactive::Derived(derived) => f(&derived.borrow_mut()()),
191192
}
192193
}
193194
}
@@ -217,10 +218,10 @@ impl<T: PartialEq + 'static> SignalMap<T> for MaybeReactive<T> {
217218
MaybeReactive::MemoChain(memo_chain) => {
218219
MaybeReactive::Memo(memo_chain.map(map))
219220
},
220-
MaybeReactive::Derived(derived) => {
221-
let derived = Rc::clone(derived);
222-
MaybeReactive::new_derived(move || map(&derived.borrow_mut()()))
223-
},
221+
// MaybeReactive::Derived(derived) => {
222+
// let derived = Rc::clone(derived);
223+
// MaybeReactive::new_derived(move || map(&derived.borrow_mut()()))
224+
// },
224225
}
225226
}
226227
}
@@ -253,13 +254,13 @@ impl<T: PartialEq + 'static> IntoMaybeReactive<T> for MemoChain<T> {
253254
}
254255
}
255256

256-
impl<T: PartialEq + 'static, F: FnMut() -> T + 'static> IntoMaybeReactive<T>
257-
for F
258-
{
259-
fn maybe_reactive(self) -> MaybeReactive<T> {
260-
MaybeReactive::new_derived(self)
261-
}
262-
}
257+
// impl<T: PartialEq + 'static, F: FnMut() -> T + 'static> IntoMaybeReactive<T>
258+
// for F
259+
// {
260+
// fn maybe_reactive(self) -> MaybeReactive<T> {
261+
// MaybeReactive::new_derived(self)
262+
// }
263+
// }
263264

264265
impl<T: PartialEq + 'static> IntoMaybeReactive<T> for Inert<T> {
265266
fn maybe_reactive(self) -> MaybeReactive<T> {
@@ -274,11 +275,13 @@ impl<T: PartialEq + Clone + 'static> Clone for MaybeReactive<T> {
274275
Self::Signal(arg0) => Self::Signal(arg0.clone()),
275276
Self::Memo(arg0) => Self::Memo(arg0.clone()),
276277
Self::MemoChain(arg0) => Self::MemoChain(arg0.clone()),
277-
Self::Derived(arg0) => Self::Derived(arg0.clone()),
278+
// Self::Derived(arg0) => Self::Derived(arg0.clone()),
278279
}
279280
}
280281
}
281282

283+
impl<T: PartialEq + Copy + 'static> Copy for MaybeReactive<T> {}
284+
282285
macro_rules! impl_inert_into_maybe_reactive {
283286
($($ty: ty),* $(,)?) => {
284287
$(
@@ -368,10 +371,10 @@ impl<T: PartialEq + Clone> IntoMemo<T> for MaybeReactive<T> {
368371
MaybeReactive::Signal(signal) => signal.memo(),
369372
MaybeReactive::Memo(memo) => memo,
370373
MaybeReactive::MemoChain(memo_chain) => memo_chain.memo(),
371-
MaybeReactive::Derived(derived) => {
372-
let derived = Rc::clone(&derived);
373-
create_memo(move |_| derived.borrow_mut()())
374-
},
374+
// MaybeReactive::Derived(derived) => {
375+
// let derived = Rc::clone(&derived);
376+
// create_memo(move |_| derived.borrow_mut()())
377+
// },
375378
}
376379
}
377380
}
@@ -380,7 +383,9 @@ impl<T: PartialEq + Clone> IntoMemo<T> for MaybeReactive<T> {
380383
pub enum MaybeSignal<T: 'static> {
381384
/// Option needed to deal with conversion from [`Inert`] into [`Signal`]
382385
/// Optimize: Can be replaced with MaybeUninit for performance
386+
#[non_exhaustive]
383387
Inert(Option<T>),
388+
#[non_exhaustive]
384389
Signal(Signal<T>),
385390
}
386391

@@ -413,10 +418,34 @@ impl<T: 'static> IntoSignal<T> for MaybeSignal<T> {
413418
}
414419

415420
impl<T: 'static> MaybeSignal<T> {
421+
/// Creates new inert MaybeSignal
416422
pub fn new_inert(value: T) -> Self {
417423
Self::Inert(Some(value))
418424
}
419425

426+
pub fn as_inert(&self) -> Option<&T> {
427+
match self {
428+
// Note: Option here is for lazy initialization, so unwrap is right
429+
MaybeSignal::Inert(inert) => Some(inert.as_ref().unwrap()),
430+
MaybeSignal::Signal(_) => None,
431+
}
432+
}
433+
434+
pub fn as_inert_mut(&mut self) -> Option<&mut T> {
435+
match self {
436+
// Note: Option here is for lazy initialization, so unwrap is right
437+
MaybeSignal::Inert(inert) => Some(inert.as_mut().unwrap()),
438+
MaybeSignal::Signal(_) => None,
439+
}
440+
}
441+
442+
pub fn as_signal(&self) -> Option<Signal<T>> {
443+
match self {
444+
MaybeSignal::Signal(signal) => Some(*signal),
445+
_ => None,
446+
}
447+
}
448+
420449
#[track_caller]
421450
fn now_reactive(&mut self) -> Signal<T> {
422451
match self {
@@ -509,11 +538,11 @@ impl<T: 'static, U: PartialEq + 'static> SignalSetter<T, MaybeReactive<U>>
509538
MaybeReactive::MemoChain(memo_chain) => {
510539
self.now_reactive().setter(memo_chain, set_map)
511540
},
512-
MaybeReactive::Derived(derived) => {
513-
// TODO: use_effect or not to use effect? See [`Signal: SignalSetter<T, MaybeReactive<U>>`] case for Derived
514-
let derived = Rc::clone(&derived);
515-
self.update(|this| set_map(this, &derived.borrow_mut()()))
516-
},
541+
// MaybeReactive::Derived(derived) => {
542+
// // TODO: use_effect or not to use effect? See [`Signal: SignalSetter<T, MaybeReactive<U>>`] case for Derived
543+
// let derived = Rc::clone(&derived);
544+
// self.update(|this| set_map(this, &derived.borrow_mut()()))
545+
// },
517546
}
518547
}
519548
}
@@ -670,8 +699,8 @@ mod tests {
670699
// Inert<()>
671700
// Inert values need explicit conversion into Inert wrapper
672701
accept_maybe_reactive(().inert());
673-
// Derived signal
674-
accept_maybe_reactive(|| {});
702+
// // Derived signal
703+
// accept_maybe_reactive(|| {});
675704
// Memo<()>
676705
accept_maybe_reactive(create_memo(move |_| {}));
677706
// Signal<()>

rsact-reactive/src/memo.rs

+20
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ impl<T: PartialEq + 'static> Memo<T> {
7979
}
8080
}
8181

82+
pub fn id(&self) -> ValueId {
83+
match self {
84+
Memo::Memo { id, ty } => *id,
85+
Memo::Signal(signal) => signal.id(),
86+
}
87+
}
88+
8289
// TODO: As a simplification and replacement of MemoChain
8390
// pub fn after_map(&mut self, f: impl FnMut(&T) -> T + 'static) -> Self {
8491
// // Replace old callback with new one. Now, passed callback is called first. [`replace_callback`] removes all subs and sources
@@ -335,6 +342,19 @@ mod tests {
335342
assert_eq!(runs.get(), 3);
336343
}
337344

345+
#[test]
346+
fn signal_into_memo() {
347+
let mut signal = create_signal(1);
348+
349+
let memo = signal.memo();
350+
351+
assert_eq!(memo.get(), 1);
352+
353+
signal.set(2);
354+
355+
assert_eq!(memo.get(), 2);
356+
}
357+
338358
// No longer works
339359
// #[test]
340360
// fn shortcut_typing() {

rsact-reactive/src/runtime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ impl Runtime {
503503
}
504504

505505
#[cfg(debug_assertions)]
506-
pub(crate) fn debug_info(&self, id: ValueId) -> ValueDebugInfo {
506+
pub fn debug_info(&self, id: ValueId) -> ValueDebugInfo {
507507
let debug_info = self.storage.debug_info(id).unwrap();
508508

509509
if let Some(ValueDebugInfo { created_at: Some(observer), .. }) = self

rsact-reactive/src/signal.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ impl<T: 'static, M: marker::Any> Signal<T, M> {
8282
}
8383
}
8484

85+
pub fn id(&self) -> ValueId {
86+
self.id
87+
}
88+
8589
#[track_caller]
8690
pub fn is_alive(self) -> bool {
8791
with_current_runtime(|rt| rt.is_alive(self.id))
@@ -219,11 +223,11 @@ impl<T: 'static, U: PartialEq + 'static> SignalSetter<T, MaybeReactive<U>>
219223
MaybeReactive::MemoChain(memo_chain) => {
220224
self.setter(memo_chain, set_map)
221225
},
222-
MaybeReactive::Derived(derived) => {
223-
// TODO: use_effect or not to use effect? How do we know if derived function is using reactive values or not
224-
let derived = Rc::clone(&derived);
225-
self.update(|this| set_map(this, &derived.borrow_mut()()));
226-
},
226+
// MaybeReactive::Derived(derived) => {
227+
// // TODO: use_effect or not to use effect? How do we know if derived function is using reactive values or not
228+
// let derived = Rc::clone(&derived);
229+
// self.update(|this| set_map(this, &derived.borrow_mut()()));
230+
// },
227231
}
228232
}
229233
}

0 commit comments

Comments
 (0)