Skip to content

Commit

Permalink
fix(core): 🐛 state split or map from trait
Browse files Browse the repository at this point in the history
  • Loading branch information
wjian23 authored and M-Adoo committed Jan 19, 2024
1 parent 50d4c99 commit 3a22ca1
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 14 deletions.
55 changes: 43 additions & 12 deletions core/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub use stateful::*;
/// The `StateReader` trait allows for reading, clone and map the state.
pub trait StateReader: 'static {
/// The value type of this state.
type Value;
type Value: ?Sized;
/// The origin state type that this state map or split from . Otherwise
/// return itself.
type OriginReader: StateReader;
Expand All @@ -41,6 +41,7 @@ pub trait StateReader: 'static {
#[inline]
fn map_reader<U, F>(&self, map: F) -> MapReader<Self::Reader, F>
where
U: ?Sized,
F: Fn(&Self::Value) -> &U + Clone,
{
MapReader { origin: self.clone_reader(), map }
Expand Down Expand Up @@ -68,7 +69,8 @@ pub trait StateReader: 'static {
/// state, otherwise return an error with self.
fn try_into_value(self) -> Result<Self::Value, Self>
where
Self: Sized;
Self: Sized,
Self::Value: Sized;
}

pub trait StateWriter: StateReader {
Expand Down Expand Up @@ -121,6 +123,7 @@ pub trait StateWriter: StateReader {
#[inline]
fn split_writer<V, R, W>(&self, map: R, mut_map: W) -> SplittedWriter<Self::Writer, R, W>
where
V: ?Sized,
R: Fn(&Self::Value) -> &V + Clone + 'static,
W: Fn(&mut Self::Value) -> &mut V + Clone + 'static,
{
Expand All @@ -145,6 +148,7 @@ pub trait StateWriter: StateReader {
#[inline]
fn map_writer<V, R, W>(&self, map: R, mut_map: W) -> MapWriter<Self::Writer, R, W>
where
V: ?Sized,
R: Fn(&Self::Value) -> &V + Clone,
W: Fn(&mut Self::Value) -> &mut V + Clone,
{
Expand All @@ -155,9 +159,9 @@ pub trait StateWriter: StateReader {

/// Wraps a borrowed reference to a value in a state.
/// A wrapper type for an immutably borrowed value from a `StateReader`.
pub struct ReadRef<'a, V>(Ref<'a, V>);
pub struct ReadRef<'a, V: ?Sized>(Ref<'a, V>);

pub struct WriteRef<'a, V> {
pub struct WriteRef<'a, V: ?Sized> {
value: Option<RefMut<'a, V>>,
control: &'a dyn WriterControl,
modify_scope: ModifyScope,
Expand Down Expand Up @@ -273,31 +277,31 @@ impl<W> State<W> {
}
}

impl<'a, V> ReadRef<'a, V> {
impl<'a, V: ?Sized> ReadRef<'a, V> {
pub(crate) fn new(r: Ref<'a, V>) -> ReadRef<'a, V> { ReadRef(r) }

pub(crate) fn map<U>(r: ReadRef<'a, V>, f: impl FnOnce(&V) -> &U) -> ReadRef<'a, U> {
pub(crate) fn map<U: ?Sized>(r: ReadRef<'a, V>, f: impl FnOnce(&V) -> &U) -> ReadRef<'a, U> {
ReadRef(Ref::map(r.0, f))
}
}

impl<'a, V> WriteRef<'a, V> {
impl<'a, V: ?Sized> WriteRef<'a, V> {
/// Forget all modifies of this reference. So all the modifies occurred on
/// this reference before this call will not be notified. Return true if there
/// is any modifies on this reference.
#[inline]
pub fn forget_modifies(&mut self) -> bool { std::mem::replace(&mut self.modified, false) }
}

impl<'a, W> Deref for ReadRef<'a, W> {
impl<'a, W: ?Sized> Deref for ReadRef<'a, W> {
type Target = W;

#[track_caller]
#[inline]
fn deref(&self) -> &Self::Target { &self.0 }
}

impl<'a, W> Deref for WriteRef<'a, W> {
impl<'a, W: ?Sized> Deref for WriteRef<'a, W> {
type Target = W;
#[track_caller]
#[inline]
Expand All @@ -307,7 +311,7 @@ impl<'a, W> Deref for WriteRef<'a, W> {
}
}

impl<'a, W> DerefMut for WriteRef<'a, W> {
impl<'a, W: ?Sized> DerefMut for WriteRef<'a, W> {
#[track_caller]
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
Expand All @@ -318,7 +322,7 @@ impl<'a, W> DerefMut for WriteRef<'a, W> {
}
}

impl<'a, W> Drop for WriteRef<'a, W> {
impl<'a, W: ?Sized> Drop for WriteRef<'a, W> {
fn drop(&mut self) {
let Self { control, modify_scope, modified, .. } = self;
if !*modified {
Expand Down Expand Up @@ -409,7 +413,7 @@ impl<W: MultiChild + Render> MultiParent for State<W> {

impl<T: StateReader + 'static> Query for T
where
T::Value: 'static,
T::Value: 'static + Sized,
{
#[inline]
fn query_inside_first(
Expand Down Expand Up @@ -690,4 +694,31 @@ mod tests {
split_writer!($s.0)
};
}

use crate::state::{StateReader, StateWriter};

#[test]
fn reader_from_trait() {
reset_test_env!();
struct A {}
trait T {
fn test(&self);
fn test_mut(&mut self);
}

impl T for A {
fn test(&self) {}
fn test_mut(&mut self) {}
}

let a = State::value(A {});
let split_writer = a.split_writer(|a| a as &dyn T, |a| a as &mut dyn T);
split_writer.read().test();
split_writer.write().test_mut();

let map_writer = a.map_writer(|a| a as &dyn T, |a| a as &mut dyn T);
let map_reader = a.map_reader(|a| a as &dyn T);
map_reader.read().test();
map_writer.write().test_mut();
}
}
11 changes: 10 additions & 1 deletion core/src/state/map_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,19 @@ macro_rules! impl_reader_trivial_methods {
fn raw_modifies(&self) -> BoxOp<'static, ModifyScope, Infallible> { self.origin.raw_modifies() }

#[inline]
fn try_into_value(self) -> Result<Self::Value, Self> { Err(self) }
fn try_into_value(self) -> Result<Self::Value, Self>
where
Self::Value: Sized,
{
Err(self)
}
};
}

impl<S, V, R> StateReader for MapReader<S, R>
where
Self: 'static,
V: ?Sized,
S: StateReader,
R: Fn(&S::Value) -> &V + Clone + 'static,
{
Expand All @@ -65,6 +71,7 @@ where
impl<V, S, R, W> StateReader for MapWriter<S, R, W>
where
Self: 'static,
V: ?Sized,
S: StateWriter,
R: Fn(&S::Value) -> &V + Clone,
W: Fn(&mut S::Value) -> &mut V + Clone,
Expand All @@ -75,6 +82,7 @@ where
impl<V, W, RM, WM> StateWriter for MapWriter<W, RM, WM>
where
Self: 'static,
V: ?Sized,
W: StateWriter,
RM: Fn(&W::Value) -> &V + Clone,
WM: Fn(&mut W::Value) -> &mut V + Clone,
Expand Down Expand Up @@ -143,6 +151,7 @@ where
impl<V, S, RM, WM> MapWriter<S, RM, WM>
where
Self: 'static,
V: ?Sized,
S: StateWriter,
RM: Fn(&S::Value) -> &V + Clone,
WM: Fn(&mut S::Value) -> &mut V + Clone,
Expand Down
12 changes: 11 additions & 1 deletion core/src/state/splitted_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,19 @@ macro_rules! splitted_reader_impl {
}

#[inline]
fn try_into_value(self) -> Result<Self::Value, Self> { Err(self) }
fn try_into_value(self) -> Result<Self::Value, Self>
where
Self::Value: Sized,
{
Err(self)
}
};
}

impl<V, O, R> StateReader for SplittedReader<O, R>
where
Self: 'static,
V: ?Sized,
O: StateReader,
R: Fn(&O::Value) -> &V + Clone,
{
Expand All @@ -94,6 +100,7 @@ where
impl<V, O, R, W> StateReader for SplittedWriter<O, R, W>
where
Self: 'static,
V: ?Sized,
O: StateWriter,
R: Fn(&O::Value) -> &V + Clone,
W: Fn(&mut O::Value) -> &mut V + Clone,
Expand All @@ -104,6 +111,7 @@ where
impl<V, O, R, W> StateWriter for SplittedWriter<O, R, W>
where
Self: 'static,
V: ?Sized,
O: StateWriter,
R: Fn(&O::Value) -> &V + Clone,
W: Fn(&mut O::Value) -> &mut V + Clone,
Expand Down Expand Up @@ -139,6 +147,7 @@ where
impl<V, O, R, W> WriterControl for SplittedWriter<O, R, W>
where
Self: 'static,
V: ?Sized,
O: StateWriter,
R: Fn(&O::Value) -> &V + Clone,
W: Fn(&mut O::Value) -> &mut V + Clone,
Expand All @@ -162,6 +171,7 @@ where
O: StateWriter,
R: Fn(&O::Value) -> &V + Clone,
W: Fn(&mut O::Value) -> &mut V + Clone,
V: ?Sized,
{
pub(super) fn new(origin: O, map: R, mut_map: W) -> Self {
let create_at = Instant::now();
Expand Down

0 comments on commit 3a22ca1

Please sign in to comment.