simplify the readable and writable traits a bit

This commit is contained in:
Evan Almloff 2024-01-23 12:07:55 -06:00
parent c172914b21
commit 6bc0332052
7 changed files with 20 additions and 49 deletions

View file

@ -51,7 +51,7 @@ impl<T: PartialEq + 'static> GlobalMemo<T> {
} }
} }
impl<T: PartialEq + 'static> crate::ReadableRef for GlobalMemo<T> { impl<T: PartialEq + 'static> Readable<T> for GlobalMemo<T> {
type Ref<R: ?Sized + 'static> = generational_box::GenerationalRef<std::cell::Ref<'static, R>>; type Ref<R: ?Sized + 'static> = generational_box::GenerationalRef<std::cell::Ref<'static, R>>;
fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> { fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> {
@ -64,9 +64,7 @@ impl<T: PartialEq + 'static> crate::ReadableRef for GlobalMemo<T> {
) -> Option<Self::Ref<U>> { ) -> Option<Self::Ref<U>> {
<UnsyncStorage as AnyStorage>::try_map(ref_, f) <UnsyncStorage as AnyStorage>::try_map(ref_, f)
} }
}
impl<T: PartialEq + 'static> Readable<T> for GlobalMemo<T> {
#[track_caller] #[track_caller]
fn read(&self) -> Self::Ref<T> { fn read(&self) -> Self::Ref<T> {
self.signal().read() self.signal().read()

View file

@ -1,6 +1,5 @@
use crate::read::Readable; use crate::read::Readable;
use crate::write::Writable; use crate::write::Writable;
use crate::WritableRef;
use crate::Write; use crate::Write;
use dioxus_core::prelude::{IntoAttributeValue, ScopeId}; use dioxus_core::prelude::{IntoAttributeValue, ScopeId};
use generational_box::{AnyStorage, GenerationalRef, UnsyncStorage}; use generational_box::{AnyStorage, GenerationalRef, UnsyncStorage};
@ -70,7 +69,7 @@ impl<T: 'static> GlobalSignal<T> {
} }
} }
impl<T: 'static> crate::ReadableRef for GlobalSignal<T> { impl<T: 'static> Readable<T> for GlobalSignal<T> {
type Ref<R: ?Sized + 'static> = generational_box::GenerationalRef<std::cell::Ref<'static, R>>; type Ref<R: ?Sized + 'static> = generational_box::GenerationalRef<std::cell::Ref<'static, R>>;
fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> { fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> {
@ -83,9 +82,7 @@ impl<T: 'static> crate::ReadableRef for GlobalSignal<T> {
) -> Option<Self::Ref<U>> { ) -> Option<Self::Ref<U>> {
<UnsyncStorage as AnyStorage>::try_map(ref_, f) <UnsyncStorage as AnyStorage>::try_map(ref_, f)
} }
}
impl<T: 'static> Readable<T> for GlobalSignal<T> {
#[track_caller] #[track_caller]
fn read(&self) -> Self::Ref<T> { fn read(&self) -> Self::Ref<T> {
self.signal().read() self.signal().read()
@ -97,7 +94,7 @@ impl<T: 'static> Readable<T> for GlobalSignal<T> {
} }
} }
impl<T: 'static> WritableRef for GlobalSignal<T> { impl<T: 'static> Writable<T> for GlobalSignal<T> {
type Mut<R: ?Sized + 'static> = Write<R, UnsyncStorage>; type Mut<R: ?Sized + 'static> = Write<R, UnsyncStorage>;
fn map_mut<I, U: ?Sized + 'static, F: FnOnce(&mut I) -> &mut U>( fn map_mut<I, U: ?Sized + 'static, F: FnOnce(&mut I) -> &mut U>(
@ -113,9 +110,7 @@ impl<T: 'static> WritableRef for GlobalSignal<T> {
) -> Option<Self::Mut<U>> { ) -> Option<Self::Mut<U>> {
Write::filter_map(ref_, f) Write::filter_map(ref_, f)
} }
}
impl<T: 'static> Writable<T> for GlobalSignal<T> {
#[track_caller] #[track_caller]
fn try_write(&self) -> Result<Self::Mut<T>, generational_box::BorrowMutError> { fn try_write(&self) -> Result<Self::Mut<T>, generational_box::BorrowMutError> {
self.signal().try_write() self.signal().try_write()

View file

@ -1,25 +1,19 @@
use std::ops::Deref; use std::ops::Deref;
/// A trait for utilities around a mutable reference /// A trait for states that can be read from like [`crate::Signal`], [`crate::GlobalSignal`], or [`crate::ReadOnlySignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Readable`] type.
pub trait ReadableRef { pub trait Readable<T: 'static = ()> {
/// The type of the reference. /// The type of the reference.
type Ref<R: ?Sized + 'static>: Deref<Target = R>; type Ref<R: ?Sized + 'static>: Deref<Target = R>;
/// Map the reference to a new type. /// Map the reference to a new type.
fn map_ref<I, U: ?Sized + 'static, F: FnOnce(&I) -> &U>( fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U>;
ref_: Self::Ref<I>,
f: F,
) -> Self::Ref<U>;
/// Try to map the reference to a new type. /// Try to map the reference to a new type.
fn try_map_ref<I, U: ?Sized + 'static, F: FnOnce(&I) -> Option<&U>>( fn try_map_ref<I, U: ?Sized, F: FnOnce(&I) -> Option<&U>>(
ref_: Self::Ref<I>, ref_: Self::Ref<I>,
f: F, f: F,
) -> Option<Self::Ref<U>>; ) -> Option<Self::Ref<U>>;
}
/// A trait for states that can be read from like [`crate::Signal`], [`crate::GlobalSignal`], or [`crate::ReadOnlySignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Readable`] type.
pub trait Readable<T: 'static>: ReadableRef {
/// Get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. /// Get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic.
fn read(&self) -> Self::Ref<T>; fn read(&self) -> Self::Ref<T>;

View file

@ -1,4 +1,4 @@
use crate::{read::Readable, ReadableRef, Signal, SignalData}; use crate::{read::Readable, Signal, SignalData};
use std::{mem::MaybeUninit, ops::Deref}; use std::{mem::MaybeUninit, ops::Deref};
use dioxus_core::{prelude::IntoAttributeValue, ScopeId}; use dioxus_core::{prelude::IntoAttributeValue, ScopeId};
@ -41,7 +41,7 @@ impl<T: 'static, S: Storage<SignalData<T>>> ReadOnlySignal<T, S> {
} }
} }
impl<T, S: Storage<SignalData<T>>> ReadableRef for ReadOnlySignal<T, S> { impl<T, S: Storage<SignalData<T>>> Readable<T> for ReadOnlySignal<T, S> {
type Ref<R: ?Sized + 'static> = S::Ref<R>; type Ref<R: ?Sized + 'static> = S::Ref<R>;
fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> { fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> {
@ -54,9 +54,7 @@ impl<T, S: Storage<SignalData<T>>> ReadableRef for ReadOnlySignal<T, S> {
) -> Option<Self::Ref<U>> { ) -> Option<Self::Ref<U>> {
S::try_map(ref_, f) S::try_map(ref_, f)
} }
}
impl<T, S: Storage<SignalData<T>>> Readable<T> for ReadOnlySignal<T, S> {
/// Get the current value of the signal. This will subscribe the current scope to the signal. If you would like to read the signal without subscribing to it, you can use [`Self::peek`] instead. /// Get the current value of the signal. This will subscribe the current scope to the signal. If you would like to read the signal without subscribing to it, you can use [`Self::peek`] instead.
/// ///
/// If the signal has been dropped, this will panic. /// If the signal has been dropped, this will panic.
@ -72,6 +70,7 @@ impl<T, S: Storage<SignalData<T>>> Readable<T> for ReadOnlySignal<T, S> {
self.inner.peek() self.inner.peek()
} }
} }
impl<T> IntoAttributeValue for ReadOnlySignal<T> impl<T> IntoAttributeValue for ReadOnlySignal<T>
where where
T: Clone + IntoAttributeValue, T: Clone + IntoAttributeValue,

View file

@ -11,9 +11,7 @@ use generational_box::{GenerationalBox, Owner, Storage};
use crate::Effect; use crate::Effect;
use crate::Readable; use crate::Readable;
use crate::ReadableRef;
use crate::Writable; use crate::Writable;
use crate::WritableRef;
fn current_owner<S: Storage<T>, T>() -> Rc<Owner<S>> { fn current_owner<S: Storage<T>, T>() -> Rc<Owner<S>> {
match Effect::current() { match Effect::current() {
@ -150,7 +148,7 @@ impl<T: 'static, S: Storage<T>> CopyValue<T, S> {
} }
} }
impl<T: 'static, S: Storage<T>> ReadableRef for CopyValue<T, S> { impl<T: 'static, S: Storage<T>> Readable<T> for CopyValue<T, S> {
type Ref<R: ?Sized + 'static> = S::Ref<R>; type Ref<R: ?Sized + 'static> = S::Ref<R>;
fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> { fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> {
@ -163,9 +161,7 @@ impl<T: 'static, S: Storage<T>> ReadableRef for CopyValue<T, S> {
) -> Option<Self::Ref<U>> { ) -> Option<Self::Ref<U>> {
S::try_map(ref_, f) S::try_map(ref_, f)
} }
}
impl<T: 'static, S: Storage<T>> Readable<T> for CopyValue<T, S> {
fn read(&self) -> Self::Ref<T> { fn read(&self) -> Self::Ref<T> {
self.value.read() self.value.read()
} }
@ -175,7 +171,7 @@ impl<T: 'static, S: Storage<T>> Readable<T> for CopyValue<T, S> {
} }
} }
impl<T: 'static, S: Storage<T>> WritableRef for CopyValue<T, S> { impl<T: 'static, S: Storage<T>> Writable<T> for CopyValue<T, S> {
type Mut<R: ?Sized + 'static> = S::Mut<R>; type Mut<R: ?Sized + 'static> = S::Mut<R>;
fn map_mut<I, U: ?Sized, F: FnOnce(&mut I) -> &mut U>( fn map_mut<I, U: ?Sized, F: FnOnce(&mut I) -> &mut U>(
@ -191,9 +187,7 @@ impl<T: 'static, S: Storage<T>> WritableRef for CopyValue<T, S> {
) -> Option<Self::Mut<U>> { ) -> Option<Self::Mut<U>> {
S::try_map_mut(mut_, f) S::try_map_mut(mut_, f)
} }
}
impl<T: 'static, S: Storage<T>> Writable<T> for CopyValue<T, S> {
fn try_write(&self) -> Result<Self::Mut<T>, generational_box::BorrowMutError> { fn try_write(&self) -> Result<Self::Mut<T>, generational_box::BorrowMutError> {
self.value.try_write() self.value.try_write()
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
read::Readable, write::Writable, Effect, EffectInner, GlobalMemo, GlobalSignal, MappedSignal, read::Readable, write::Writable, Effect, EffectInner, GlobalMemo, GlobalSignal, MappedSignal,
ReadOnlySignal, ReadableRef, WritableRef, ReadOnlySignal,
}; };
use std::{ use std::{
any::Any, any::Any,
@ -399,7 +399,7 @@ impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {
} }
} }
impl<T, S: Storage<SignalData<T>>> ReadableRef for Signal<T, S> { impl<T, S: Storage<SignalData<T>>> Readable<T> for Signal<T, S> {
type Ref<R: ?Sized + 'static> = S::Ref<R>; type Ref<R: ?Sized + 'static> = S::Ref<R>;
fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> { fn map_ref<I, U: ?Sized, F: FnOnce(&I) -> &U>(ref_: Self::Ref<I>, f: F) -> Self::Ref<U> {
@ -412,9 +412,7 @@ impl<T, S: Storage<SignalData<T>>> ReadableRef for Signal<T, S> {
) -> Option<Self::Ref<U>> { ) -> Option<Self::Ref<U>> {
S::try_map(ref_, f) S::try_map(ref_, f)
} }
}
impl<T, S: Storage<SignalData<T>>> Readable<T> for Signal<T, S> {
/// Get the current value of the signal. This will subscribe the current scope to the signal. If you would like to read the signal without subscribing to it, you can use [`Self::peek`] instead. /// Get the current value of the signal. This will subscribe the current scope to the signal. If you would like to read the signal without subscribing to it, you can use [`Self::peek`] instead.
/// ///
/// If the signal has been dropped, this will panic. /// If the signal has been dropped, this will panic.
@ -458,7 +456,7 @@ impl<T, S: Storage<SignalData<T>>> Readable<T> for Signal<T, S> {
} }
} }
impl<T: 'static, S: Storage<SignalData<T>>> WritableRef for Signal<T, S> { impl<T: 'static, S: Storage<SignalData<T>>> Writable<T> for Signal<T, S> {
type Mut<R: ?Sized + 'static> = Write<R, S>; type Mut<R: ?Sized + 'static> = Write<R, S>;
fn map_mut<I, U: ?Sized + 'static, F: FnOnce(&mut I) -> &mut U>( fn map_mut<I, U: ?Sized + 'static, F: FnOnce(&mut I) -> &mut U>(
@ -474,9 +472,7 @@ impl<T: 'static, S: Storage<SignalData<T>>> WritableRef for Signal<T, S> {
) -> Option<Self::Mut<U>> { ) -> Option<Self::Mut<U>> {
Write::filter_map(ref_, f) Write::filter_map(ref_, f)
} }
}
impl<T: 'static, S: Storage<SignalData<T>>> Writable<T> for Signal<T, S> {
#[track_caller] #[track_caller]
fn try_write(&self) -> Result<Self::Mut<T>, generational_box::BorrowMutError> { fn try_write(&self) -> Result<Self::Mut<T>, generational_box::BorrowMutError> {
self.inner.try_write().map(|inner| { self.inner.try_write().map(|inner| {

View file

@ -2,26 +2,21 @@ use std::ops::DerefMut;
use crate::read::Readable; use crate::read::Readable;
/// A trait for utilities around a mutable reference /// A trait for states that can be read from like [`crate::Signal`], or [`crate::GlobalSignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Writable`] type.
pub trait WritableRef { pub trait Writable<T: 'static>: Readable<T> {
/// The type of the reference. /// The type of the reference.
type Mut<R: ?Sized + 'static>: DerefMut<Target = R>; type Mut<R: ?Sized + 'static>: DerefMut<Target = R>;
/// Map the reference to a new type. /// Map the reference to a new type.
fn map_mut<I, U: ?Sized + 'static, F: FnOnce(&mut I) -> &mut U>( fn map_mut<I, U: ?Sized, F: FnOnce(&mut I) -> &mut U>(ref_: Self::Mut<I>, f: F)
ref_: Self::Mut<I>, -> Self::Mut<U>;
f: F,
) -> Self::Mut<U>;
/// Try to map the reference to a new type. /// Try to map the reference to a new type.
fn try_map_mut<I, U: ?Sized + 'static, F: FnOnce(&mut I) -> Option<&mut U>>( fn try_map_mut<I, U: ?Sized, F: FnOnce(&mut I) -> Option<&mut U>>(
ref_: Self::Mut<I>, ref_: Self::Mut<I>,
f: F, f: F,
) -> Option<Self::Mut<U>>; ) -> Option<Self::Mut<U>>;
}
/// A trait for states that can be read from like [`crate::Signal`], or [`crate::GlobalSignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Writable`] type.
pub trait Writable<T: 'static>: WritableRef + Readable<T> {
/// Get a mutable reference to the value. If the value has been dropped, this will panic. /// Get a mutable reference to the value. If the value has been dropped, this will panic.
#[track_caller] #[track_caller]
fn write(&self) -> Self::Mut<T> { fn write(&self) -> Self::Mut<T> {