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>>;
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>> {
<UnsyncStorage as AnyStorage>::try_map(ref_, f)
}
}
impl<T: PartialEq + 'static> Readable<T> for GlobalMemo<T> {
#[track_caller]
fn read(&self) -> Self::Ref<T> {
self.signal().read()

View file

@ -1,6 +1,5 @@
use crate::read::Readable;
use crate::write::Writable;
use crate::WritableRef;
use crate::Write;
use dioxus_core::prelude::{IntoAttributeValue, ScopeId};
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>>;
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>> {
<UnsyncStorage as AnyStorage>::try_map(ref_, f)
}
}
impl<T: 'static> Readable<T> for GlobalSignal<T> {
#[track_caller]
fn read(&self) -> Self::Ref<T> {
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>;
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>> {
Write::filter_map(ref_, f)
}
}
impl<T: 'static> Writable<T> for GlobalSignal<T> {
#[track_caller]
fn try_write(&self) -> Result<Self::Mut<T>, generational_box::BorrowMutError> {
self.signal().try_write()

View file

@ -1,25 +1,19 @@
use std::ops::Deref;
/// A trait for utilities around a mutable reference
pub trait ReadableRef {
/// 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 = ()> {
/// The type of the reference.
type Ref<R: ?Sized + 'static>: Deref<Target = R>;
/// Map the reference to a new type.
fn map_ref<I, U: ?Sized + 'static, 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>;
/// 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>,
f: F,
) -> 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.
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 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>;
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>> {
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.
///
/// 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()
}
}
impl<T> IntoAttributeValue for ReadOnlySignal<T>
where
T: Clone + IntoAttributeValue,

View file

@ -11,9 +11,7 @@ use generational_box::{GenerationalBox, Owner, Storage};
use crate::Effect;
use crate::Readable;
use crate::ReadableRef;
use crate::Writable;
use crate::WritableRef;
fn current_owner<S: Storage<T>, T>() -> Rc<Owner<S>> {
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>;
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>> {
S::try_map(ref_, f)
}
}
impl<T: 'static, S: Storage<T>> Readable<T> for CopyValue<T, S> {
fn read(&self) -> Self::Ref<T> {
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>;
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>> {
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> {
self.value.try_write()
}

View file

@ -1,6 +1,6 @@
use crate::{
read::Readable, write::Writable, Effect, EffectInner, GlobalMemo, GlobalSignal, MappedSignal,
ReadOnlySignal, ReadableRef, WritableRef,
ReadOnlySignal,
};
use std::{
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>;
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>> {
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.
///
/// 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>;
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>> {
Write::filter_map(ref_, f)
}
}
impl<T: 'static, S: Storage<SignalData<T>>> Writable<T> for Signal<T, S> {
#[track_caller]
fn try_write(&self) -> Result<Self::Mut<T>, generational_box::BorrowMutError> {
self.inner.try_write().map(|inner| {

View file

@ -2,26 +2,21 @@ use std::ops::DerefMut;
use crate::read::Readable;
/// A trait for utilities around a mutable reference
pub trait WritableRef {
/// 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>: Readable<T> {
/// The type of the reference.
type Mut<R: ?Sized + 'static>: DerefMut<Target = R>;
/// Map the reference to a new type.
fn map_mut<I, U: ?Sized + 'static, F: FnOnce(&mut I) -> &mut U>(
ref_: Self::Mut<I>,
f: F,
) -> Self::Mut<U>;
fn map_mut<I, U: ?Sized, F: FnOnce(&mut I) -> &mut U>(ref_: Self::Mut<I>, f: F)
-> Self::Mut<U>;
/// 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>,
f: F,
) -> 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.
#[track_caller]
fn write(&self) -> Self::Mut<T> {