1use std::{
2 marker::PhantomData,
3 ops,
4 sync::{Arc, Weak},
5};
6
7use super::{util::VarData, *};
8
9#[macro_export]
39macro_rules! merge_var {
40 ($($tt:tt)+) => {
41 $crate::types::__merge_var! {
42 $crate,
43 $($tt)+
44 }
45 };
46}
47
48use parking_lot::Mutex;
49#[doc(hidden)]
50pub use zng_var_proc_macros::merge_var as __merge_var;
51
52#[doc(hidden)]
54pub struct ArcMergeVarInput<T: VarValue, V: Var<T>>(PhantomData<(V, T)>);
55impl<T: VarValue, V: Var<T>> ArcMergeVarInput<T, V> {
56 pub fn new(_: &V) -> Self {
57 ArcMergeVarInput(PhantomData)
58 }
59
60 #[expect(clippy::borrowed_box)]
61 pub fn get<'v>(&self, value: &'v Box<dyn AnyVarValue>) -> &'v T {
62 (**value).as_any().downcast_ref::<T>().unwrap()
63 }
64}
65
66struct MergeData<T> {
67 _input_vars: Box<[BoxedAnyVar]>,
68 inputs: Box<[Box<dyn AnyVarValue>]>,
69 input_handles: Box<[VarHandle]>,
70 merge: Box<dyn FnMut(&[Box<dyn AnyVarValue>]) -> T + Send + Sync>,
71}
72
73struct Data<T: VarValue> {
74 m: Mutex<MergeData<T>>,
75 value: VarData,
76}
77
78pub struct ArcMergeVar<T: VarValue>(Arc<Data<T>>);
80
81pub struct WeakMergeVar<T: VarValue>(Weak<Data<T>>);
83
84impl<T: VarValue> ArcMergeVar<T> {
85 #[doc(hidden)]
86 #[expect(clippy::new_ret_no_self)]
87 pub fn new(inputs: Box<[BoxedAnyVar]>, merge: impl FnMut(&[Box<dyn AnyVarValue>]) -> T + Send + 'static) -> BoxedVar<T> {
88 if inputs.iter().any(|v| v.is_contextual()) {
89 let merge = Arc::new(Mutex::new(merge));
90 types::ContextualizedVar::new(move || {
91 let merge = merge.clone();
92 ArcMergeVar::new_impl(Cow::Borrowed(&inputs), Box::new(move |values| merge.lock()(values)))
93 })
94 .boxed()
95 } else {
96 let merge = Mutex::new(merge);
97 ArcMergeVar::new_impl(Cow::Owned(inputs), Box::new(move |values| merge.lock()(values))).boxed()
98 }
99 }
100
101 fn new_impl(input_vars: Cow<Box<[BoxedAnyVar]>>, mut merge: Box<dyn FnMut(&[Box<dyn AnyVarValue>]) -> T + Send + Sync>) -> Self {
102 let inputs: Box<[_]> = input_vars.iter().map(|v| v.get_any()).collect();
103 let rc_merge = Arc::new(Data {
104 value: VarData::new(merge(&inputs)),
105 m: Mutex::new(MergeData {
106 _input_vars: Box::new([]),
107 inputs,
108 input_handles: Box::new([]),
109 merge,
110 }),
111 });
112 let wk_merge = Arc::downgrade(&rc_merge);
113
114 let input_handles: Box<[_]> = input_vars
115 .iter()
116 .enumerate()
117 .filter_map(|(i, var)| {
118 if var.capabilities().contains(VarCapability::NEW) {
119 let wk_merge = wk_merge.clone();
120 let handle = var.hook_any(Box::new(move |args| {
121 if let Some(rc_merge) = wk_merge.upgrade() {
122 let mut data = rc_merge.m.lock();
123 let data_mut = &mut *data;
124 if args.value_type() == data_mut.inputs[i].as_any().type_id() {
125 data_mut.inputs[i] = args.value().clone_boxed();
126
127 drop(data);
128 VARS.schedule_update(ArcMergeVar::update_merge(rc_merge), std::any::type_name::<T>());
129 }
130 true
131 } else {
132 false
133 }
134 }));
135
136 debug_assert!(!handle.is_dummy());
137
138 Some(handle)
139 } else {
140 None
141 }
142 })
143 .collect();
144
145 {
146 let mut l = rc_merge.m.lock();
147 l.input_handles = input_handles;
148 if let Cow::Owned(v) = input_vars {
149 l._input_vars = v;
150 } }
152
153 Self(rc_merge)
154 }
155
156 fn update_merge(rc_merge: Arc<Data<T>>) -> VarUpdateFn {
157 Box::new(move || {
158 let mut m = rc_merge.m.lock();
159 let m = &mut *m;
160 let new_value = (m.merge)(&m.inputs);
161 {
162 let modify = |v: &mut VarModify<T>| v.set(new_value);
163 #[cfg(feature = "dyn_closure")]
164 let modify = Box::new(modify);
165 rc_merge.value.apply_modify(modify)
166 };
167 })
168 }
169}
170
171impl<T: VarValue> Clone for ArcMergeVar<T> {
172 fn clone(&self) -> Self {
173 Self(self.0.clone())
174 }
175}
176
177impl<T: VarValue> Clone for WeakMergeVar<T> {
178 fn clone(&self) -> Self {
179 Self(self.0.clone())
180 }
181}
182
183impl<T: VarValue> crate::private::Sealed for ArcMergeVar<T> {}
184impl<T: VarValue> crate::private::Sealed for WeakMergeVar<T> {}
185
186impl<T: VarValue> AnyVar for ArcMergeVar<T> {
187 fn clone_any(&self) -> BoxedAnyVar {
188 Box::new(self.clone())
189 }
190
191 fn as_any(&self) -> &dyn Any {
192 self
193 }
194
195 fn as_unboxed_any(&self) -> &dyn Any {
196 self
197 }
198
199 fn double_boxed_any(self: Box<Self>) -> Box<dyn Any> {
200 let me: BoxedVar<T> = self;
201 Box::new(me)
202 }
203
204 fn var_type_id(&self) -> TypeId {
205 TypeId::of::<T>()
206 }
207
208 fn get_any(&self) -> Box<dyn AnyVarValue> {
209 Box::new(self.get())
210 }
211
212 fn with_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) {
213 self.with(|v| read(v))
214 }
215
216 fn with_new_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) -> bool {
217 self.with_new(|v| read(v)).is_some()
218 }
219
220 fn set_any(&self, _: Box<dyn AnyVarValue>) -> Result<(), VarIsReadOnlyError> {
221 Err(VarIsReadOnlyError {
222 capabilities: self.capabilities(),
223 })
224 }
225
226 fn last_update(&self) -> VarUpdateId {
227 self.0.value.last_update()
228 }
229
230 fn is_contextual(&self) -> bool {
231 false }
233
234 fn capabilities(&self) -> VarCapability {
235 if self.0.m.lock().inputs.is_empty() {
236 VarCapability::empty()
237 } else {
238 VarCapability::NEW
239 }
240 }
241
242 fn hook_any(&self, pos_modify_action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> VarHandle {
243 self.0.value.push_hook(pos_modify_action)
244 }
245
246 fn hook_animation_stop(&self, handler: Box<dyn FnOnce() + Send>) -> Result<(), Box<dyn FnOnce() + Send>> {
247 self.0.value.push_animation_hook(handler)
248 }
249
250 fn strong_count(&self) -> usize {
251 Arc::strong_count(&self.0)
252 }
253
254 fn weak_count(&self) -> usize {
255 Arc::weak_count(&self.0)
256 }
257
258 fn actual_var_any(&self) -> BoxedAnyVar {
259 Box::new(self.clone())
260 }
261
262 fn downgrade_any(&self) -> BoxedAnyWeakVar {
263 Box::new(WeakMergeVar(Arc::downgrade(&self.0)))
264 }
265
266 fn is_animating(&self) -> bool {
267 self.0.value.is_animating()
268 }
269
270 fn modify_importance(&self) -> usize {
271 self.0.value.modify_importance()
272 }
273
274 fn var_ptr(&self) -> VarPtr {
275 VarPtr::new_arc(&self.0)
276 }
277
278 fn get_debug(&self) -> Txt {
279 self.with(var_debug)
280 }
281
282 fn update(&self) -> Result<(), VarIsReadOnlyError> {
283 Var::modify(self, var_update)
284 }
285
286 fn map_debug(&self) -> BoxedVar<Txt> {
287 Var::map(self, var_debug).boxed()
288 }
289}
290
291impl<T: VarValue> AnyWeakVar for WeakMergeVar<T> {
292 fn clone_any(&self) -> BoxedAnyWeakVar {
293 Box::new(self.clone())
294 }
295
296 fn strong_count(&self) -> usize {
297 self.0.strong_count()
298 }
299
300 fn weak_count(&self) -> usize {
301 self.0.weak_count()
302 }
303
304 fn upgrade_any(&self) -> Option<BoxedAnyVar> {
305 self.0.upgrade().map(|rc| Box::new(ArcMergeVar(rc)) as _)
306 }
307
308 fn as_any(&self) -> &dyn Any {
309 self
310 }
311}
312
313impl<T: VarValue> IntoVar<T> for ArcMergeVar<T> {
314 type Var = Self;
315
316 fn into_var(self) -> Self::Var {
317 self
318 }
319}
320
321impl<T: VarValue> Var<T> for ArcMergeVar<T> {
322 type ReadOnly = types::ReadOnlyVar<T, Self>;
323
324 type ActualVar = Self;
325
326 type Downgrade = WeakMergeVar<T>;
327
328 type Map<O: VarValue> = ReadOnlyArcVar<O>;
329 type MapBidi<O: VarValue> = ArcVar<O>;
330
331 type FlatMap<O: VarValue, V: Var<O>> = types::ArcFlatMapVar<O, V>;
332
333 type FilterMap<O: VarValue> = ReadOnlyArcVar<O>;
334 type FilterMapBidi<O: VarValue> = ArcVar<O>;
335
336 type MapRef<O: VarValue> = types::MapRef<T, O, Self>;
337 type MapRefBidi<O: VarValue> = types::MapRefBidi<T, O, Self>;
338
339 type Easing = ReadOnlyArcVar<T>;
340
341 fn with<R, F>(&self, read: F) -> R
342 where
343 F: FnOnce(&T) -> R,
344 {
345 self.0.value.with(read)
346 }
347
348 fn modify<F>(&self, _: F) -> Result<(), VarIsReadOnlyError>
349 where
350 F: FnOnce(&mut VarModify<T>) + 'static,
351 {
352 Err(VarIsReadOnlyError {
353 capabilities: self.capabilities(),
354 })
355 }
356
357 fn actual_var(self) -> Self {
358 self
359 }
360
361 fn downgrade(&self) -> WeakMergeVar<T> {
362 WeakMergeVar(Arc::downgrade(&self.0))
363 }
364
365 fn into_value(self) -> T {
366 match Arc::try_unwrap(self.0) {
367 Ok(data) => data.value.into_value(),
368 Err(rc) => Self(rc).get(),
369 }
370 }
371
372 fn read_only(&self) -> Self::ReadOnly {
373 types::ReadOnlyVar::new(self.clone())
374 }
375
376 fn map<O, M>(&self, map: M) -> Self::Map<O>
377 where
378 O: VarValue,
379 M: FnMut(&T) -> O + Send + 'static,
380 {
381 var_map(self, map)
382 }
383
384 fn map_bidi<O, M, B>(&self, map: M, map_back: B) -> Self::MapBidi<O>
385 where
386 O: VarValue,
387 M: FnMut(&T) -> O + Send + 'static,
388 B: FnMut(&O) -> T + Send + 'static,
389 {
390 var_map_bidi(self, map, map_back)
391 }
392
393 fn flat_map<O, V, M>(&self, map: M) -> Self::FlatMap<O, V>
394 where
395 O: VarValue,
396 V: Var<O>,
397 M: FnMut(&T) -> V + Send + 'static,
398 {
399 var_flat_map(self, map)
400 }
401
402 fn filter_map<O, M, I>(&self, map: M, fallback: I) -> Self::FilterMap<O>
403 where
404 O: VarValue,
405 M: FnMut(&T) -> Option<O> + Send + 'static,
406 I: Fn() -> O + Send + Sync + 'static,
407 {
408 var_filter_map(self, map, fallback)
409 }
410
411 fn filter_map_bidi<O, M, B, I>(&self, map: M, map_back: B, fallback: I) -> Self::FilterMapBidi<O>
412 where
413 O: VarValue,
414 M: FnMut(&T) -> Option<O> + Send + 'static,
415 B: FnMut(&O) -> Option<T> + Send + 'static,
416 I: Fn() -> O + Send + Sync + 'static,
417 {
418 var_filter_map_bidi(self, map, map_back, fallback)
419 }
420
421 fn map_ref<O, M>(&self, map: M) -> Self::MapRef<O>
422 where
423 O: VarValue,
424 M: Fn(&T) -> &O + Send + Sync + 'static,
425 {
426 var_map_ref(self, map)
427 }
428
429 fn map_ref_bidi<O, M, B>(&self, map: M, map_mut: B) -> Self::MapRefBidi<O>
430 where
431 O: VarValue,
432 M: Fn(&T) -> &O + Send + Sync + 'static,
433 B: Fn(&mut T) -> &mut O + Send + Sync + 'static,
434 {
435 var_map_ref_bidi(self, map, map_mut)
436 }
437
438 fn easing<F>(&self, duration: Duration, easing: F) -> Self::Easing
439 where
440 T: Transitionable,
441 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
442 {
443 var_easing(self, duration, easing)
444 }
445
446 fn easing_with<F, S>(&self, duration: Duration, easing: F, sampler: S) -> Self::Easing
447 where
448 T: Transitionable,
449 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
450 S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static,
451 {
452 var_easing_with(self, duration, easing, sampler)
453 }
454}
455
456impl<T: VarValue> WeakVar<T> for WeakMergeVar<T> {
457 type Upgrade = ArcMergeVar<T>;
458
459 fn upgrade(&self) -> Option<ArcMergeVar<T>> {
460 self.0.upgrade().map(|rc| ArcMergeVar(rc))
461 }
462}
463
464pub struct MergeVarBuilder<I: VarValue> {
466 inputs: Vec<Box<dyn AnyVar>>,
467 _type: PhantomData<fn() -> I>,
468}
469impl<I: VarValue> MergeVarBuilder<I> {
470 pub fn new() -> Self {
472 Self {
473 inputs: vec![],
474 _type: PhantomData,
475 }
476 }
477
478 pub fn with_capacity(capacity: usize) -> Self {
480 Self {
481 inputs: Vec::with_capacity(capacity),
482 _type: PhantomData,
483 }
484 }
485
486 pub fn push(&mut self, input: impl Var<I>) {
488 self.inputs.push(input.boxed_any())
489 }
490
491 pub fn build<O: VarValue>(self, mut merge: impl FnMut(MergeVarInputs<I>) -> O + Send + 'static) -> BoxedVar<O> {
493 ArcMergeVar::new(self.inputs.into_boxed_slice(), move |inputs| {
494 merge(MergeVarInputs {
495 inputs,
496 _type: PhantomData,
497 })
498 })
499 }
500}
501impl<I: VarValue> Default for MergeVarBuilder<I> {
502 fn default() -> Self {
503 Self::new()
504 }
505}
506
507pub struct MergeVarInputs<'a, I: VarValue> {
509 inputs: &'a [Box<dyn AnyVarValue>],
510 _type: PhantomData<&'a I>,
511}
512impl<I: VarValue> MergeVarInputs<'_, I> {
513 #[expect(clippy::len_without_is_empty)]
515 pub fn len(&self) -> usize {
516 self.inputs.len()
517 }
518
519 pub fn iter(&self) -> impl ExactSizeIterator<Item = &I> + '_ {
521 (0..self.len()).map(move |i| &self[i])
522 }
523}
524impl<I: VarValue> ops::Index<usize> for MergeVarInputs<'_, I> {
525 type Output = I;
526
527 fn index(&self, index: usize) -> &Self::Output {
528 self.inputs[index].as_any().downcast_ref().unwrap()
529 }
530}