use super::value_type::value_type_id;
use super::ValueTypes;
use crate::{AnyValue, BoxedValue, FerroObject, WeakRef};
use std::any::TypeId;
use std::rc::{Rc, Weak};
#[derive(Clone)]
pub enum WeakValue {
Reference(Weak<dyn AnyValue>),
Object(WeakRef<FerroObject>, TypeId),
Value(BoxedValue),
}
impl PartialEq for WeakValue {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(WeakValue::Reference(a), WeakValue::Reference(b)) => std::ptr::addr_eq(a.as_ptr(), b.as_ptr()),
(WeakValue::Object(a, a_id), WeakValue::Object(b, b_id)) => a.ptr_eq(b) && a_id == b_id,
(WeakValue::Value(a), WeakValue::Value(b)) => **a == **b,
_ => false,
}
}
}
impl WeakValue {
pub fn new(value: &BoxedValue) -> Self {
let id = value_type_id(&**value);
if let Some(object) = ValueTypes::as_object(&**value) {
WeakValue::Object(object.downgrade(), id)
} else if ValueTypes::is_reference(id) {
WeakValue::Reference(Rc::downgrade(value))
} else {
WeakValue::Value(value.clone())
}
}
pub fn upgrade(&self) -> Option<BoxedValue> {
match self {
WeakValue::Reference(weak) => weak.upgrade(),
WeakValue::Object(weak, id) => weak.upgrade().and_then(|o| ValueTypes::from_object(*id, o)),
WeakValue::Value(value) => Some(value.clone()),
}
}
}