Skip to main content

ferroui_base/data/core/
weak_value.rs

1use super::value_type::value_type_id;
2use super::ValueTypes;
3use crate::{AnyValue, BoxedValue, FerroObject, WeakRef};
4use std::any::TypeId;
5use std::rc::{Rc, Weak};
6
7/// A reference to a binding source that does not keep it alive.
8///
9/// Objects of the class hierarchy and registered reference (model) types are
10/// held weakly, as the managed implementation holds every source. Plain
11/// values (numbers, strings, value structs) own nothing that could form a
12/// cycle and exist only as the transient box that carries them, so they are
13/// held by value.
14#[derive(Clone)]
15pub enum WeakValue {
16    /// A shared model object.
17    Reference(Weak<dyn AnyValue>),
18    /// An object of the class hierarchy and the handle type it was seen as.
19    Object(WeakRef<FerroObject>, TypeId),
20    /// A plain value.
21    Value(BoxedValue),
22}
23
24/// Two references are equal when they refer to the same source: the same
25/// object for the weakly held ones, equal values for plain values.
26impl PartialEq for WeakValue {
27    fn eq(&self, other: &Self) -> bool {
28        match (self, other) {
29            (WeakValue::Reference(a), WeakValue::Reference(b)) => std::ptr::addr_eq(a.as_ptr(), b.as_ptr()),
30            (WeakValue::Object(a, a_id), WeakValue::Object(b, b_id)) => a.ptr_eq(b) && a_id == b_id,
31            (WeakValue::Value(a), WeakValue::Value(b)) => **a == **b,
32            _ => false,
33        }
34    }
35}
36
37impl WeakValue {
38    pub fn new(value: &BoxedValue) -> Self {
39        let id = value_type_id(&**value);
40        if let Some(object) = ValueTypes::as_object(&**value) {
41            WeakValue::Object(object.downgrade(), id)
42        } else if ValueTypes::is_reference(id) {
43            WeakValue::Reference(Rc::downgrade(value))
44        } else {
45            WeakValue::Value(value.clone())
46        }
47    }
48
49    /// The source, if it is still alive.
50    pub fn upgrade(&self) -> Option<BoxedValue> {
51        match self {
52            WeakValue::Reference(weak) => weak.upgrade(),
53            WeakValue::Object(weak, id) => weak.upgrade().and_then(|o| ValueTypes::from_object(*id, o)),
54            WeakValue::Value(value) => Some(value.clone()),
55        }
56    }
57}