use crate::data::core::TypedClrPropertyInfo;
use crate::data::model::INotifyPropertyChanged;
use crate::data::{BindingError, CompiledBindingPathBuilder};
use crate::PropertyValue;
use std::marker::PhantomData;
use std::rc::Rc;
pub type TypedPathElement = fn(&CompiledBindingPathBuilder, bool) -> Option<CompiledBindingPathBuilder>;
pub type TypedPathGetter<This, V> = Rc<dyn Fn(&This) -> Result<V, BindingError>>;
pub type TypedPathSetter<This, V> = Rc<dyn Fn(&This, V)>;
#[doc(hidden)]
pub struct TypedPathProbe<This, V>(PhantomData<(This, V)>);
impl<This, V> TypedPathProbe<This, V> {
#[allow(clippy::new_without_default)]
pub const fn new() -> Self {
Self(PhantomData)
}
}
#[doc(hidden)]
pub trait TypedPathNotifying<This, V> {
fn typed_path_element(
&self,
builder: &CompiledBindingPathBuilder,
accepts_null: bool,
name: &str,
get: Option<TypedPathGetter<This, V>>,
set: Option<TypedPathSetter<This, V>>,
) -> Option<CompiledBindingPathBuilder>;
}
impl<S: INotifyPropertyChanged + PartialEq + 'static, V: PropertyValue> TypedPathNotifying<Rc<S>, V>
for &TypedPathProbe<Rc<S>, V>
{
fn typed_path_element(
&self,
builder: &CompiledBindingPathBuilder,
accepts_null: bool,
name: &str,
get: Option<TypedPathGetter<Rc<S>, V>>,
set: Option<TypedPathSetter<Rc<S>, V>>,
) -> Option<CompiledBindingPathBuilder> {
if is_untyped::<V>() {
return None;
}
let info = TypedClrPropertyInfo::<S, V>::from_handle_accessors(name, get, set);
Some(builder.typed_property_info_with(info, accepts_null))
}
}
#[doc(hidden)]
pub trait TypedPathShared<This, V> {
fn typed_path_element(
&self,
builder: &CompiledBindingPathBuilder,
accepts_null: bool,
name: &str,
get: Option<TypedPathGetter<This, V>>,
set: Option<TypedPathSetter<This, V>>,
) -> Option<CompiledBindingPathBuilder>;
}
impl<S: PartialEq + 'static, V: PropertyValue> TypedPathShared<Rc<S>, V> for &&TypedPathProbe<Rc<S>, V> {
fn typed_path_element(
&self,
builder: &CompiledBindingPathBuilder,
accepts_null: bool,
name: &str,
get: Option<TypedPathGetter<Rc<S>, V>>,
set: Option<TypedPathSetter<Rc<S>, V>>,
) -> Option<CompiledBindingPathBuilder> {
if is_untyped::<V>() {
return None;
}
let info = TypedClrPropertyInfo::<S, V>::from_handle_accessors(name, get, set);
Some(builder.typed_plain_property_info_with(info, accepts_null))
}
}
fn is_untyped<V: 'static>() -> bool {
let id = std::any::TypeId::of::<V>();
id == std::any::TypeId::of::<crate::BoxedValue>() || id == std::any::TypeId::of::<Option<crate::BoxedValue>>()
}
#[doc(hidden)]
pub trait TypedPathFallback<This, V> {
fn typed_path_element(
&self,
_builder: &CompiledBindingPathBuilder,
_accepts_null: bool,
_name: &str,
_get: Option<TypedPathGetter<This, V>>,
_set: Option<TypedPathSetter<This, V>>,
) -> Option<CompiledBindingPathBuilder> {
None
}
}
impl<This, V> TypedPathFallback<This, V> for TypedPathProbe<This, V> {}