mini_rx/
rx_ref.rs

1use std::fmt::Debug;
2use std::marker::PhantomData;
3use derivative::Derivative;
4use crate::dag::{RxDAG, RxSubDAG, RxContext, MutRxContext};
5use crate::dag_uid::RxDAGUid;
6use crate::clone_set_fn::CloneSetFn;
7use crate::rx_impl::{CurrentOrNext, Rx};
8
9/// Index into the DAG which will give you a node, which may be a variable or computed value.
10///
11/// To actually get or set the value you need a shared reference to the [RxDAG].
12///
13/// The DAG and refs have an ID so that you can't use one ref on another DAG, however this is checked at runtime.
14/// The lifetimes are checked at compile-time though.
15#[derive(Debug, Derivative)]
16#[derivative(Clone(bound = ""), Copy(bound = ""))]
17pub(crate) struct RxRef<'c, T> {
18    index: usize,
19    graph_id: RxDAGUid<'c>,
20    phantom: PhantomData<T>
21}
22
23/// Index into the [RxDAG] which will give you a variable.
24///
25/// To actually get or set the value you need a shared reference to the [RxDAG].
26#[derive(Debug, Derivative)]
27#[derivative(Clone(bound = ""), Copy(bound = ""))]
28pub struct Var<'c, T>(RxRef<'c, T>);
29
30/// Index into the [RxDAG] which will give you a computed value.
31///
32/// To actually get the value you need a shared reference to the [RxDAG].
33/// You cannot set the value, instead it's computed from other values.
34#[derive(Debug, Derivative)]
35#[derivative(Clone(bound = ""), Copy(bound = ""))]
36pub struct CRx<'c, T>(RxRef<'c, T>);
37
38/// View and mutate a part of a [Var].
39#[derive(Debug)]
40pub struct DVar<'c, S, T, GetFn: Fn(&S) -> &T, SetFn: Fn(&S, T) -> S> {
41    source: RxRef<'c, S>,
42    get: GetFn,
43    set: SetFn
44}
45
46/// View a part of a [CRx].
47#[derive(Debug)]
48pub struct DCRx<'c, S, T, GetFn: Fn(&S) -> &T> {
49    source: RxRef<'c, S>,
50    get: GetFn
51}
52
53impl<'c, T> RxRef<'c, T> {
54    pub(crate) fn new(graph: &RxDAG<'c>, index: usize) -> Self {
55        RxRef {
56            index,
57            graph_id: graph.id(),
58            phantom: PhantomData
59        }
60    }
61
62    /// Read the node
63    fn get<'a>(self, graph: RxSubDAG<'a, 'c>) -> &'a T where 'c: 'a {
64        unsafe { self.get_rx(graph).get_dyn() }
65    }
66
67    /// Take `next` if set, otherwise returns a reference to `current`.
68    /// The value should then be re-passed to `next` via `set`
69    fn take_latest<'a>(self, graph: RxSubDAG<'a, 'c>) -> CurrentOrNext<'a, T> where 'c: 'a {
70        unsafe { self.get_rx(graph).take_latest_dyn() }
71    }
72
73    /// Write a new value to the node. The changes will be applied on recompute.
74    fn set(self, graph: RxSubDAG<'_, 'c>, value: T) {
75        unsafe { self.get_rx(graph).set_dyn(value); }
76    }
77
78    /// Apply a transformation to the latest value. If `set` this will apply to the recently-set value.
79    /// This must be used instead of chaining [RxRef::set] and [RxRef::get], since setting a value doesn't make it
80    /// returned by [RxRef::get] until the graph is recomputed.
81    ///
82    /// Like `set` the changes only actually reflect in [RxRef::get] on recompute.
83    fn modify<F: FnOnce(&T) -> T>(self, graph: RxSubDAG<'_, 'c>, modify: F) {
84        let latest = self.take_latest(graph);
85        let next = modify(latest.as_ref());
86        self.set(graph, next);
87    }
88
89    /// Get the underlying [Rx] where the data is stored.
90    fn get_rx<'a>(self, graph: RxSubDAG<'a, 'c>) -> &'a Rx<'c> where 'c: 'a {
91        debug_assert!(self.graph_id == graph.id, "RxRef::get_rx: different graph");
92        debug_assert!(self.index < graph.before.len(), "RxRef refers to a future node (not a DAG?)");
93        // Since we already checked the index, we can use get_unchecked
94        let elem = unsafe { graph.before.get_unchecked(self.index) };
95        elem.as_node().expect("RxRef is corrupt: it points to an edge")
96    }
97}
98
99impl<'c, T> Var<'c, T> {
100    pub(crate) fn new(internal: RxRef<'c, T>) -> Self {
101        Var(internal)
102    }
103
104    /// Read the variable
105    pub fn get<'a>(self, c: impl RxContext<'a, 'c>) -> &'a T where 'c: 'a {
106        let graph = c.sub_dag();
107        self.0.get(graph)
108    }
109
110    /// Write a new value to the variable. The changes will be applied on recompute.
111    pub fn set<'a>(self, c: impl MutRxContext<'a, 'c>, value: T) where 'c: 'a {
112        let graph = c.sub_dag();
113        self.0.set(graph, value);
114    }
115
116    /// Apply a transformation to the latest value. If [Var::set] this will apply to the recently-set value.
117    /// This must be used instead of chaining [Var::set] and [Var::get], since setting a value doesn't make it
118    /// returned by [Var::get] until the graph is recomputed.
119    ///
120    /// Like `set` the changes only actually reflect in [Var::get] on recompute.
121    pub fn modify<'a, F: FnOnce(&T) -> T>(self, c: impl MutRxContext<'a, 'c>, modify: F) where 'c: 'a {
122        let graph = c.sub_dag();
123        self.0.modify(graph, modify)
124    }
125
126    /// Create a view of part of the variable.
127    ///
128    /// Do know that `SetFn` will take the most recently-set value even if the graph hasn't been recomputed.
129    /// This means you can create multiple `derive`s and set them all before recompute, and you don't have to worry
130    /// about the later derived values setting their part on the stale whole.
131    pub fn derive<U, GetFn: Fn(&T) -> &U, SetFn: Fn(&T, U) -> T>(self, get: GetFn, set: SetFn) -> DVar<'c, T, U, GetFn, SetFn> {
132        DVar {
133            source: self.0,
134            get,
135            set
136        }
137    }
138
139    /// Create a view of part of the variable, which clones the value on set.
140    ///
141    /// Do know that `SetFn` will take the most recently-set value even if the graph hasn't been recomputed.
142    /// This means you can create multiple `derive`s and set them all before recompute, and you don't have to worry
143    /// about the later derived values setting their part on the stale whole.
144    pub fn derive_using_clone<U, GetFn: Fn(&T) -> &U, SetFn: Fn(&mut T, U)>(self, get: GetFn, set: SetFn) -> DVar<'c, T, U, GetFn, CloneSetFn<T, U, SetFn>> where T: Clone {
145        self.derive(get, CloneSetFn::new(set))
146    }
147}
148
149impl<'c, T> CRx<'c, T> {
150    pub(crate) fn new(internal: RxRef<'c, T>) -> Self {
151        CRx(internal)
152    }
153
154    /// Read the computed value
155    pub fn get<'a>(self, c: impl RxContext<'a, 'c>) -> &'a T where 'c: 'a {
156        let graph = c.sub_dag();
157        self.0.get(graph)
158    }
159
160    /// Create a view of part of the computed value.
161    pub fn derive<U, GetFn: Fn(&T) -> &U>(self, get: GetFn) -> DCRx<'c, T, U, GetFn> {
162        DCRx {
163            source: self.0,
164            get
165        }
166    }
167}
168
169impl<'c, S, T, GetFn: Fn(&S) -> &T, SetFn: Fn(&S, T) -> S> DVar<'c, S, T, GetFn, SetFn> {
170    /// Read the part of the variable this view gets.
171    pub fn get<'a>(&self, c: impl RxContext<'a, 'c>) -> &'a T where 'c: 'a, S: 'a {
172        let graph = c.sub_dag();
173        (self.get)(self.source.get(graph))
174    }
175
176    /// Write a new value to the part of the variable this view gets.
177    ///
178    /// Do know that this uses the most recently-set value even if the graph hasn't been recomputed.
179    /// This means you can create multiple `derive`s and set them all before recompute, and you don't have to worry
180    /// about the later derived values setting their part on the stale whole.
181    pub fn set<'a>(&self, c: impl MutRxContext<'a, 'c>, value: T) where 'c: 'a, S: 'a {
182        let graph = c.sub_dag();
183        let old_value = self.source.take_latest(graph);
184        let new_value = (self.set)(old_value.as_ref(), value);
185        self.source.set(graph, new_value)
186    }
187}
188
189impl<'c, S, T, GetFn: Fn(&S) -> &T> DCRx<'c, S, T, GetFn> {
190    /// Read the part of the computed value this view gets.
191    pub fn get<'a>(&self, c: impl RxContext<'a, 'c>) -> &'a T where 'c: 'a, S: 'a {
192        let graph = c.sub_dag();
193        (self.get)(self.source.get(graph))
194    }
195}
196