ferroui_base/data/
binding_base.rs1use crate::data::BindingExpressionBase;
2use crate::{FerroObject, FerroProperty, Ref};
3use std::rc::Rc;
4
5pub trait BindingBase {
8 fn create_instance(
16 &self,
17 target: &FerroObject,
18 target_property: Option<&'static FerroProperty>,
19 anchor: Option<&Ref<FerroObject>>,
20 ) -> Rc<dyn BindingExpressionBase>;
21
22 fn as_any(&self) -> Option<&dyn std::any::Any> {
26 None
27 }
28
29 #[doc(hidden)]
31 fn reference_id(&self) -> *const () {
32 self as *const Self as *const ()
33 }
34}
35
36impl PartialEq for dyn BindingBase {
39 #[inline]
40 fn eq(&self, other: &Self) -> bool {
41 self.reference_id() == other.reference_id()
42 }
43}
44
45impl<T: BindingBase + ?Sized> BindingBase for Rc<T> {
49 fn create_instance(
50 &self,
51 target: &FerroObject,
52 target_property: Option<&'static FerroProperty>,
53 anchor: Option<&Ref<FerroObject>>,
54 ) -> Rc<dyn BindingExpressionBase> {
55 (**self).create_instance(target, target_property, anchor)
56 }
57
58 fn as_any(&self) -> Option<&dyn std::any::Any> {
59 (**self).as_any()
60 }
61
62 fn reference_id(&self) -> *const () {
63 (**self).reference_id()
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70 use crate::data::{CompiledBinding, CompiledBindingPath, ReflectionBinding};
71
72 #[test]
73 fn a_binding_is_cast_to_its_concrete_class_through_any_handle() {
74 let reflection = ReflectionBinding::new("Name");
75 let contract: Rc<dyn BindingBase> = reflection.clone();
76 assert!(contract.as_any().is_some_and(|any| any.is::<ReflectionBinding>()));
77 let handle: &dyn BindingBase = &reflection;
79 let concrete = handle.as_any().and_then(|any| any.downcast_ref::<ReflectionBinding>());
80 assert!(concrete.is_some_and(|binding| std::ptr::eq(binding, &*reflection)));
81 let handle: &dyn BindingBase = &contract;
83 assert!(handle.as_any().is_some_and(|any| any.is::<ReflectionBinding>()));
84
85 let compiled: Rc<dyn BindingBase> = CompiledBinding::new(CompiledBindingPath::new());
86 assert!(compiled.as_any().is_some_and(|any| any.is::<CompiledBinding>()));
87 assert!(!compiled.as_any().is_some_and(|any| any.is::<ReflectionBinding>()));
88 }
89}