Added initial support for Signal<impl ?Sized>.

This commit is contained in:
Filipe Rodrigues 2024-02-05 22:36:08 +00:00
parent c19c2ecddc
commit 4f63e55653
Signed by: zenithsiz
SSH Key Fingerprint: SHA256:Mb5ppb3Sh7IarBO/sBTXLHbYEOz37hJAlslLQPPAPaU
3 changed files with 39 additions and 10 deletions

View File

@ -1,5 +1,8 @@
//! Reactivity for [`dynatos`]
// Features
#![feature(unsize, coerce_unsized)]
// Modules
pub mod effect;
pub mod signal;
@ -26,7 +29,7 @@ pub trait SignalGet {
/// Signal with
pub trait SignalWith {
/// Value type
type Value;
type Value: ?Sized;
/// Uses the signal value
fn with<F, O>(&self, f: F) -> O
@ -49,7 +52,7 @@ pub trait SignalReplace<Value> {
/// Signal update
pub trait SignalUpdate {
/// Value type
type Value;
type Value: ?Sized;
/// Updates the signal value
fn update<F, O>(&self, f: F) -> O

View File

@ -6,20 +6,23 @@
// Imports
use {
crate::{Effect, SignalGet, SignalReplace, SignalSet, SignalUpdate, SignalWith, Trigger, WeakEffect},
std::{cell::RefCell, fmt, mem, rc::Rc},
std::{cell::RefCell, fmt, marker::Unsize, mem, ops::CoerceUnsized, rc::Rc},
};
/// Inner
struct Inner<T> {
/// Value
value: RefCell<T>,
struct Inner<T: ?Sized> {
/// Trigger
trigger: Trigger,
/// Value
value: RefCell<T>,
}
// TODO: Add `T: ?Sized, U: ?Sized` once `RefCell` supports it.
impl<T, U> CoerceUnsized<Inner<U>> for Inner<T> where T: CoerceUnsized<U> {}
/// Signal
pub struct Signal<T> {
pub struct Signal<T: ?Sized> {
/// Inner
inner: Rc<Inner<T>>,
}
@ -35,6 +38,11 @@ impl<T> Signal<T> {
}
}
// TODO: Add `Signal::<dyn Any>::downcast` once we add `{T, U}: ?Sized` to the `CoerceUnsized` impl of `Inner`.
// Use `Rc::downcast::<Inner<T>>(self.inner as Rc<dyn Any>)`
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Signal<U>> for Signal<T> where T: Unsize<U> {}
impl<T> SignalGet for Signal<T>
where
T: Copy,
@ -46,7 +54,7 @@ where
}
}
impl<T> SignalWith for Signal<T> {
impl<T: ?Sized> SignalWith for Signal<T> {
type Value = T;
fn with<F, O>(&self, f: F) -> O
@ -78,7 +86,7 @@ impl<T> SignalReplace<T> for Signal<T> {
}
}
impl<T> SignalUpdate for Signal<T> {
impl<T: ?Sized> SignalUpdate for Signal<T> {
type Value = T;
fn update<F, O>(&self, f: F) -> O

View File

@ -0,0 +1,18 @@
//! `!Sized` tests.
// Imports
use {
dynatos_reactive::{Signal, SignalWith},
std::any::Any,
};
#[test]
fn create_unsized() {
let value: i32 = 5;
let sig = Signal::<i32>::new(value) as Signal<dyn Any>;
sig.with(|dyn_value| {
assert_eq!(dyn_value.type_id(), value.type_id());
assert_eq!(dyn_value.downcast_ref::<i32>(), Some(&value))
});
}