From 3a22ca1242c20bb615be13c5d9f6d4373786aa54 Mon Sep 17 00:00:00 2001 From: wjian23 Date: Fri, 19 Jan 2024 10:17:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(core):=20=F0=9F=90=9B=20state=20split=20or?= =?UTF-8?q?=20map=20from=20trait?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/state.rs | 55 +++++++++++++++++++++++++------- core/src/state/map_state.rs | 11 ++++++- core/src/state/splitted_state.rs | 12 ++++++- 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/core/src/state.rs b/core/src/state.rs index a1f3fb508..fe8a82c30 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -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; @@ -41,6 +41,7 @@ pub trait StateReader: 'static { #[inline] fn map_reader(&self, map: F) -> MapReader where + U: ?Sized, F: Fn(&Self::Value) -> &U + Clone, { MapReader { origin: self.clone_reader(), map } @@ -68,7 +69,8 @@ pub trait StateReader: 'static { /// state, otherwise return an error with self. fn try_into_value(self) -> Result where - Self: Sized; + Self: Sized, + Self::Value: Sized; } pub trait StateWriter: StateReader { @@ -121,6 +123,7 @@ pub trait StateWriter: StateReader { #[inline] fn split_writer(&self, map: R, mut_map: W) -> SplittedWriter where + V: ?Sized, R: Fn(&Self::Value) -> &V + Clone + 'static, W: Fn(&mut Self::Value) -> &mut V + Clone + 'static, { @@ -145,6 +148,7 @@ pub trait StateWriter: StateReader { #[inline] fn map_writer(&self, map: R, mut_map: W) -> MapWriter where + V: ?Sized, R: Fn(&Self::Value) -> &V + Clone, W: Fn(&mut Self::Value) -> &mut V + Clone, { @@ -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>, control: &'a dyn WriterControl, modify_scope: ModifyScope, @@ -273,15 +277,15 @@ impl State { } } -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(r: ReadRef<'a, V>, f: impl FnOnce(&V) -> &U) -> ReadRef<'a, U> { + pub(crate) fn map(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. @@ -289,7 +293,7 @@ impl<'a, V> WriteRef<'a, V> { 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] @@ -297,7 +301,7 @@ impl<'a, W> Deref for ReadRef<'a, W> { 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] @@ -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 { @@ -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 { @@ -409,7 +413,7 @@ impl MultiParent for State { impl Query for T where - T::Value: 'static, + T::Value: 'static + Sized, { #[inline] fn query_inside_first( @@ -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(); + } } diff --git a/core/src/state/map_state.rs b/core/src/state/map_state.rs index 6384495b1..6355de9e6 100644 --- a/core/src/state/map_state.rs +++ b/core/src/state/map_state.rs @@ -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 { Err(self) } + fn try_into_value(self) -> Result + where + Self::Value: Sized, + { + Err(self) + } }; } impl StateReader for MapReader where Self: 'static, + V: ?Sized, S: StateReader, R: Fn(&S::Value) -> &V + Clone + 'static, { @@ -65,6 +71,7 @@ where impl StateReader for MapWriter where Self: 'static, + V: ?Sized, S: StateWriter, R: Fn(&S::Value) -> &V + Clone, W: Fn(&mut S::Value) -> &mut V + Clone, @@ -75,6 +82,7 @@ where impl StateWriter for MapWriter where Self: 'static, + V: ?Sized, W: StateWriter, RM: Fn(&W::Value) -> &V + Clone, WM: Fn(&mut W::Value) -> &mut V + Clone, @@ -143,6 +151,7 @@ where impl MapWriter where Self: 'static, + V: ?Sized, S: StateWriter, RM: Fn(&S::Value) -> &V + Clone, WM: Fn(&mut S::Value) -> &mut V + Clone, diff --git a/core/src/state/splitted_state.rs b/core/src/state/splitted_state.rs index 585970cda..27758372e 100644 --- a/core/src/state/splitted_state.rs +++ b/core/src/state/splitted_state.rs @@ -78,13 +78,19 @@ macro_rules! splitted_reader_impl { } #[inline] - fn try_into_value(self) -> Result { Err(self) } + fn try_into_value(self) -> Result + where + Self::Value: Sized, + { + Err(self) + } }; } impl StateReader for SplittedReader where Self: 'static, + V: ?Sized, O: StateReader, R: Fn(&O::Value) -> &V + Clone, { @@ -94,6 +100,7 @@ where impl StateReader for SplittedWriter where Self: 'static, + V: ?Sized, O: StateWriter, R: Fn(&O::Value) -> &V + Clone, W: Fn(&mut O::Value) -> &mut V + Clone, @@ -104,6 +111,7 @@ where impl StateWriter for SplittedWriter where Self: 'static, + V: ?Sized, O: StateWriter, R: Fn(&O::Value) -> &V + Clone, W: Fn(&mut O::Value) -> &mut V + Clone, @@ -139,6 +147,7 @@ where impl WriterControl for SplittedWriter where Self: 'static, + V: ?Sized, O: StateWriter, R: Fn(&O::Value) -> &V + Clone, W: Fn(&mut O::Value) -> &mut V + Clone, @@ -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();