use crate::{read::Readable, read_impls, ReadableExt, ReadableRef}; use dioxus_core::{IntoAttributeValue, Subscribers}; use generational_box::{AnyStorage, BorrowResult}; use std::ops::Deref; /// A read only signal that has been mapped to a new type. pub struct MappedSignal::Target) -> &O> { value: V, map_fn: F, _marker: std::marker::PhantomData, } impl Clone for MappedSignal where V: Readable + Clone, F: Clone, { fn clone(&self) -> Self { MappedSignal { value: self.value.clone(), map_fn: self.map_fn.clone(), _marker: std::marker::PhantomData, } } } impl Copy for MappedSignal where V: Readable + Copy, F: Copy, { } impl MappedSignal where O: ?Sized, { /// Create a new mapped signal. pub fn new(value: V, map_fn: F) -> Self { MappedSignal { value, map_fn, _marker: std::marker::PhantomData, } } } impl Readable for MappedSignal where O: ?Sized, V: Readable, V::Target: 'static, F: Fn(&V::Target) -> &O, { type Target = O; type Storage = V::Storage; fn try_read_unchecked( &self, ) -> Result, generational_box::BorrowError> { let value = self.value.try_read_unchecked()?; Ok(V::Storage::map(value, |v| (self.map_fn)(v))) } fn try_peek_unchecked(&self) -> BorrowResult> { let value = self.value.try_peek_unchecked()?; Ok(V::Storage::map(value, |v| (self.map_fn)(v))) } fn subscribers(&self) -> Subscribers { self.value.subscribers() } } impl IntoAttributeValue for MappedSignal where O: Clone + IntoAttributeValue + 'static, V: Readable, V::Target: 'static, F: Fn(&V::Target) -> &O, { fn into_value(self) -> dioxus_core::AttributeValue { self.with(|f| f.clone().into_value()) } } impl PartialEq for MappedSignal where O: ?Sized, V: Readable + PartialEq, F: PartialEq, { fn eq(&self, other: &Self) -> bool { self.value == other.value && self.map_fn == other.map_fn } } /// Allow calling a signal with signal() syntax /// /// Currently only limited to clone types, though could probably specialize for string/arc/rc impl Deref for MappedSignal where O: Clone + 'static, V: Readable + 'static, F: Fn(&V::Target) -> &O + 'static, { type Target = dyn Fn() -> O; fn deref(&self) -> &Self::Target { unsafe { ReadableExt::deref_impl(self) } } } read_impls!(MappedSignal where V: Readable, F: Fn(&V::Target) -> &T);