1use std::{
2 mem::swap,
3 rc::{
4 Rc,
5 Weak,
6 },
7 cell::{
8 RefCell,
9 Ref,
10 },
11 ops::Deref,
12};
13use crate::{
14 core::{
15 Id,
16 ValueTrait,
17 ProcessingContext,
18 Cleanup,
19 Link_,
20 Value,
21 IntoValue,
22 },
23 Link,
24};
25
26pub struct PrimMut_<T> {
27 value: T,
28 first_change: bool,
29 next: Vec<Weak<Link_>>,
30}
31
32impl<T: 'static> PrimMut_<T> {
33 pub fn get(&self) -> &T {
34 return &self.value;
35 }
36}
37
38pub(crate) struct Prim_<T> {
39 mut_: RefCell<PrimMut_<T>>,
40}
41
42impl<T> ValueTrait for Prim_<T> {
43 fn next_links(&self) -> Vec<crate::Link> {
44 let mut out = vec![];
45 let mut self2 = self.mut_.borrow_mut();
46 out.reserve(self2.next.len());
47 self2.next.retain_mut(|e| {
48 match e.upgrade() {
49 Some(e) => {
50 out.push(Link(e.clone()));
51 return true;
52 },
53 None => {
54 return false;
55 },
56 }
57 });
58 return out;
59 }
60}
61
62impl<T> Cleanup for Prim_<T> {
63 fn clean(&self) {
64 self.mut_.borrow_mut().first_change = true;
65 }
66}
67
68#[derive(Clone)]
70pub struct Prim<T>(pub(crate) Rc<Prim_<T>>);
71
72#[derive(Clone)]
73pub struct WeakPrim<T>(Weak<Prim_<T>>);
74
75impl<T: 'static> Prim<T> {
76 pub fn new(initial: T) -> Self {
77 return Prim(Rc::new(Prim_ { mut_: RefCell::new(PrimMut_ {
78 value: initial,
79 first_change: true,
80 next: vec![],
81 }) }));
82 }
83
84 pub fn add_next(&self, link: &Link) {
87 self.0.mut_.borrow_mut().next.push(Rc::downgrade(&link.0));
88 }
89
90 pub fn weak(&self) -> WeakPrim<T> {
92 return WeakPrim(Rc::downgrade(&self.0));
93 }
94
95 pub fn set(&self, pc: &mut ProcessingContext, value: T) {
97 let first_change;
98 {
99 let mut self2 = self.0.mut_.borrow_mut();
100 first_change = self2.first_change;
101 self2.first_change = false;
102 self2.value = value;
103 }
104 if first_change {
105 pc.1.cleanup.push(self.0.clone());
106 if !pc.1.processing {
107 for l in self.0.next_links() {
108 pc.1.step1_stacked_links.push((true, l));
109 }
110 }
111 }
112 }
113
114 pub fn borrow<'a>(&'a self) -> ValueRef<'a, T> {
116 return ValueRef(self.0.mut_.borrow());
117 }
118}
119
120impl<T: 'static> IntoValue for Prim<T> {
121 fn into_value(&self) -> Value {
122 return Value(self.0.clone());
123 }
124}
125
126impl<T: 'static> WeakPrim<T> {
127 pub fn upgrade(&self) -> Option<Prim<T>> {
128 return Some(Prim(self.0.upgrade()?));
129 }
130}
131
132pub struct ValueRef<'a, T: 'static>(Ref<'a, PrimMut_<T>>);
133
134impl<'a, T: 'static> Deref for ValueRef<'a, T> {
135 type Target = T;
136
137 fn deref(&self) -> &Self::Target {
138 return &self.0.value;
139 }
140}
141
142pub struct HistPrimMut_<T: PartialEq + Clone> {
143 value: T,
144 previous_value: Option<T>,
145 next: Vec<Weak<Link_>>,
146}
147
148impl<T: PartialEq + Clone + 'static> HistPrimMut_<T> {
149 pub fn get(&self) -> &T {
150 return &self.value;
151 }
152}
153
154pub(crate) struct HistPrim_<T: PartialEq + Clone> {
155 pub(crate) id: Id,
156 mut_: RefCell<HistPrimMut_<T>>,
157}
158
159impl<T: PartialEq + Clone> ValueTrait for HistPrim_<T> {
160 fn next_links(&self) -> Vec<crate::Link> {
161 let mut out = vec![];
162 let mut self2 = self.mut_.borrow_mut();
163 out.reserve(self2.next.len());
164 self2.next.retain_mut(|e| {
165 match e.upgrade() {
166 Some(e) => {
167 out.push(Link(e.clone()));
168 return true;
169 },
170 None => {
171 return false;
172 },
173 }
174 });
175 return out;
176 }
177}
178
179impl<T: PartialEq + Clone> Cleanup for HistPrim_<T> {
180 fn clean(&self) {
181 self.mut_.borrow_mut().previous_value = None;
182 }
183}
184
185#[derive(Clone)]
190pub struct HistPrim<T: PartialEq + Clone>(pub(crate) Rc<HistPrim_<T>>);
191
192#[derive(Clone)]
193pub struct WeakHistPrim<T: PartialEq + Clone>(Weak<HistPrim_<T>>);
194
195impl<T: PartialEq + Clone + 'static> HistPrim<T> {
196 pub fn new(pc: &mut ProcessingContext, initial: T) -> Self {
197 let id = pc.1.take_id();
198 return HistPrim(Rc::new(HistPrim_ {
199 id: id,
200 mut_: RefCell::new(HistPrimMut_ {
201 value: initial,
202 previous_value: None,
203 next: vec![],
204 }),
205 }));
206 }
207
208 pub fn add_next(&self, link: &Link) {
211 self.0.mut_.borrow_mut().next.push(Rc::downgrade(&link.0));
212 }
213
214 pub fn weak(&self) -> WeakHistPrim<T> {
216 return WeakHistPrim(Rc::downgrade(&self.0));
217 }
218
219 pub fn set(&self, pc: &mut ProcessingContext, mut value: T) {
221 let first_change;
222 {
223 let mut self2 = self.0.mut_.borrow_mut();
224 if self2.value == value {
225 return;
226 }
227 swap(&mut self2.value, &mut value);
228 first_change = self2.previous_value.is_none();
229 self2.previous_value = Some(value);
230 }
231 if first_change {
232 pc.1.cleanup.push(self.0.clone());
233 if !pc.1.processing {
234 for l in self.0.next_links() {
235 pc.1.step1_stacked_links.push((true, l));
236 }
237 }
238 }
239 }
240
241 pub fn borrow<'a>(&'a self) -> HistValueRef<'a, T> {
243 return HistValueRef(self.0.mut_.borrow());
244 }
245
246 pub fn get(&self) -> T {
248 return self.0.mut_.borrow().value.clone();
249 }
250
251 pub fn get_old(&self) -> T {
253 let m = self.0.mut_.borrow();
254 return m.previous_value.as_ref().unwrap_or_else(|| &m.value).clone();
255 }
256}
257
258impl<T: PartialEq + Clone + 'static> IntoValue for HistPrim<T> {
259 fn into_value(&self) -> Value {
260 return Value(self.0.clone());
261 }
262}
263
264impl<T: PartialEq + Clone + 'static> WeakHistPrim<T> {
265 pub fn upgrade(&self) -> Option<HistPrim<T>> {
266 return Some(HistPrim(self.0.upgrade()?));
267 }
268}
269
270pub struct HistValueRef<'a, T: PartialEq + Clone + 'static>(Ref<'a, HistPrimMut_<T>>);
271
272impl<'a, T: PartialEq + Clone + 'static> Deref for HistValueRef<'a, T> {
273 type Target = T;
274
275 fn deref(&self) -> &Self::Target {
276 return &self.0.value;
277 }
278}