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#[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#[derive(Debug, Derivative)]
27#[derivative(Clone(bound = ""), Copy(bound = ""))]
28pub struct Var<'c, T>(RxRef<'c, T>);
29
30#[derive(Debug, Derivative)]
35#[derivative(Clone(bound = ""), Copy(bound = ""))]
36pub struct CRx<'c, T>(RxRef<'c, T>);
37
38#[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#[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 fn get<'a>(self, graph: RxSubDAG<'a, 'c>) -> &'a T where 'c: 'a {
64 unsafe { self.get_rx(graph).get_dyn() }
65 }
66
67 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 fn set(self, graph: RxSubDAG<'_, 'c>, value: T) {
75 unsafe { self.get_rx(graph).set_dyn(value); }
76 }
77
78 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 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 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 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 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 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 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 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 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 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 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 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 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