Skip to content

Commit 9bd2049

Browse files
committed
wip: redesign pinned_render_init
1 parent abbfc3f commit 9bd2049

File tree

33 files changed

+1923
-1864
lines changed

33 files changed

+1923
-1864
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 76 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -1,258 +1,164 @@
1-
pub use self::render_value::{
2-
RenderValueMut, RenderValueOnce, RenderValueWithFn, RenderValueWithFnMutAndData,
3-
RenderValueWithFnOnceAndData,
4-
};
5-
61
use std::{pin::Pin, task::Poll};
72

83
use crate::csr::StateUnmount;
94

10-
mod render_value;
11-
12-
mod option;
13-
pub mod str;
5+
pub mod csr_str;
6+
pub mod simple_non_reactive;
147

158
pub trait ReactiveValueKind: 'static {
169
type Value<'a>;
1710
}
1811

19-
impl ReactiveValueKind for str {
20-
type Value<'a> = &'a str;
21-
}
22-
2312
pub trait ReactiveValueState: StateUnmount {
2413
type ReactiveValueKind: ?Sized + ReactiveValueKind;
2514

26-
fn reactive_value_state_poll_render(
15+
fn poll_render(
2716
self: Pin<&mut Self>,
28-
renderer: &mut impl RenderValueMut<Self::ReactiveValueKind, RenderOutput = ()>,
17+
renderer: impl FnMut(<Self::ReactiveValueKind as ReactiveValueKind>::Value<'_>),
2918
cx: &mut std::task::Context<'_>,
3019
) -> Poll<()>;
3120
}
3221

3322
impl<T: ReactiveValueState> ReactiveValueState for Option<T> {
3423
type ReactiveValueKind = T::ReactiveValueKind;
3524

36-
fn reactive_value_state_poll_render(
25+
fn poll_render(
3726
self: Pin<&mut Self>,
38-
renderer: &mut impl RenderValueMut<Self::ReactiveValueKind, RenderOutput = ()>,
27+
renderer: impl FnMut(<Self::ReactiveValueKind as ReactiveValueKind>::Value<'_>),
3928
cx: &mut std::task::Context<'_>,
4029
) -> Poll<()> {
4130
if let Some(this) = self.as_pin_mut() {
42-
this.reactive_value_state_poll_render(renderer, cx)
31+
this.poll_render(renderer, cx)
4332
} else {
4433
Poll::Ready(())
4534
}
4635
}
4736
}
4837

49-
mod sealed {
50-
pub trait AsOptionMut<T: ?Sized> {}
51-
}
52-
53-
/// This trait is sealed to ensure correct implementation:
54-
/// - `as_option_mut()` returning `None` indicates [`<Self as StateUnmount>::state_unmount()`](StateUnmount::state_unmount) is noop.
55-
/// - `as_option_mut()` returning `None` indicates the renderer has been called with `renderer.*_remove()`
56-
///
57-
/// (Search the code for *Correct AsOptionMut Implementation* to find the code relying on this behavior.)
58-
pub trait AsOptionMut<T: ?Sized>: sealed::AsOptionMut<T> {
59-
// Not using the receiver `&mut self` so that calling this method must be qualified.
60-
fn as_option_mut(this: &mut Self) -> Option<&mut T>;
38+
pub trait ReactiveValueRenderInitPinned<VK: ?Sized + ReactiveValueKind> {
39+
type State;
6140

62-
fn as_option_pin_mut(this: Pin<&mut Self>) -> Option<Pin<&mut T>>;
41+
fn render_init_pinned<Out>(
42+
self,
43+
renderer: impl FnOnce(VK::Value<'_>) -> Out,
44+
state: Pin<&mut Self::State>,
45+
) -> Out;
6346
}
6447

65-
impl<T: ?Sized> sealed::AsOptionMut<T> for T {}
66-
impl<T: ?Sized> AsOptionMut<T> for T {
67-
fn as_option_mut(this: &mut Self) -> Option<&mut T> {
68-
Some(this)
69-
}
70-
71-
fn as_option_pin_mut(this: Pin<&mut Self>) -> Option<Pin<&mut T>> {
72-
Some(this)
73-
}
48+
pub trait ProvideValueOfKind<VK: ?Sized + ReactiveValueKind> {
49+
fn provide_value_of_kind<Out>(self, f: impl FnOnce(VK::Value<'_>) -> Out) -> Out;
7450
}
7551

76-
impl<T> sealed::AsOptionMut<T> for Option<T> {}
77-
impl<T> AsOptionMut<T> for Option<T> {
78-
fn as_option_mut(this: &mut Self) -> Option<&mut T> {
79-
this.as_mut()
80-
}
81-
82-
fn as_option_pin_mut(this: Pin<&mut Self>) -> Option<Pin<&mut T>> {
83-
this.as_pin_mut()
84-
}
52+
pub trait ReusableRendererOfKind<VK: ?Sized + ReactiveValueKind> {
53+
type Output;
54+
fn render(self, value: VK::Value<'_>) -> Self::Output;
55+
/// The provide_value might be ignored or called by renderer to check whether reusing is correct.
56+
fn reuse(self, provide_value: impl ProvideValueOfKind<VK>) -> Self::Output;
8557
}
8658

87-
/// The value is optional. That's why [`RenderValueOnce`] and [`RenderValueMut`] have a `remove*` method.
8859
pub trait ReactiveValue<VK: ?Sized + ReactiveValueKind> {
89-
type PinnedState;
60+
type PinnedState: ReactiveValueState<ReactiveValueKind = VK>;
61+
type PinnedRenderInit: ReactiveValueRenderInitPinned<VK, State = Self::PinnedState>;
9062

91-
/// Requires [`Default`] so that it can be initialized and pinned safely.
92-
type PinnedStateDefault: Default
93-
+ From<Self::PinnedState>
94-
+ AsOptionMut<Self::PinnedState>
95-
+ ReactiveValueState<ReactiveValueKind = VK>;
96-
97-
/// Requires [`Unpin`] so that [`CsrReactiveStrStateUnmount`] can be reused without defining another trait taking `&mut self`.
63+
/// Requires [`Unpin`] so that [`ReactiveValueState`] can be reused without defining another trait taking `&mut self`.
9864
type UnpinnedState: Unpin + ReactiveValueState<ReactiveValueKind = VK>;
9965

100-
/// Requires `Unpin + ReactiveValueState` so that implementations for `Option` like types doesn't need to
101-
/// introduce a wrapper type to implement `type StateUnpinned`.
102-
/// `Unpin + ReactiveValueState` is usually already implemented because `Option<_>` derives them.
103-
type UnpinnedStateDefault: Default
104-
+ From<Self::UnpinnedState>
105-
+ AsOptionMut<Self::UnpinnedState>
106-
+ Unpin
107-
+ ReactiveValueState<ReactiveValueKind = VK>;
108-
10966
/// `state` is `Default::default()` at a pinned place.
110-
fn reactive_value_render_init_pinned<Out>(
111-
self,
112-
renderer: impl RenderValueOnce<VK, RenderOutput = Out>,
113-
state: Pin<&mut Self::PinnedStateDefault>,
114-
) -> Out;
67+
fn pinned_render_init(self) -> (Self::PinnedState, Self::PinnedRenderInit);
11568

11669
/// `old_state` has been [unmounted](ReactiveStrStateUnmount::reactive_value_state_unmount) but not necessarily set to `Default::default()`.
117-
fn reactive_value_render_init_with_old_state_pinned<Out>(
70+
fn pinned_render_init_by_reusing<Out>(
11871
self,
119-
renderer: impl RenderValueOnce<VK, RenderOutput = Out>,
120-
old_state: Pin<&mut Self::PinnedStateDefault>,
72+
renderer: impl ReusableRendererOfKind<VK, Output = Out>,
73+
reused_state: Pin<&mut Self::PinnedState>,
12174
) -> Out;
12275

12376
/// `renderer` doesn't need to be updated if unnecessary.
124-
fn reactive_value_render_update_pinned<Out>(
77+
fn pinned_render_update<Out>(
12578
self,
126-
renderer: impl RenderValueOnce<VK, RenderOutput = Out>,
127-
state: Pin<&mut Self::PinnedStateDefault>,
79+
renderer: impl FnOnce(VK::Value<'_>) -> Out,
80+
state: Pin<&mut Self::PinnedState>,
12881
) -> Option<Out>;
12982

130-
fn reactive_value_render_init_unpinned<Out>(
83+
fn unpinned_render_init<Out>(
13184
self,
132-
renderer: impl RenderValueOnce<VK, RenderOutput = Out>,
85+
renderer: impl FnOnce(VK::Value<'_>) -> Out,
13386
) -> (Self::UnpinnedState, Out);
13487

135-
fn reactive_value_render_init_with_old_state_unpinned<Out>(
88+
fn unpinned_render_init_by_reusing<Out>(
13689
self,
137-
renderer: impl RenderValueOnce<VK, RenderOutput = Out>,
138-
old_state: &mut Self::UnpinnedState,
90+
renderer: impl ReusableRendererOfKind<VK, Output = Out>,
91+
reused_state: &mut Self::UnpinnedState,
13992
) -> Out;
14093

14194
/// `renderer` doesn't need to be updated if unnecessary.
142-
fn reactive_value_render_update_unpinned<Out>(
95+
fn unpinned_render_update<Out>(
14396
self,
144-
renderer: impl RenderValueOnce<VK, RenderOutput = Out>,
97+
renderer: impl FnOnce(VK::Value<'_>) -> Out,
14598
state: &mut Self::UnpinnedState,
14699
) -> Option<Out>;
147100
}
148101

149-
pub trait ReactiveValueExt<VK: ?Sized + ReactiveValueKind>: ReactiveValue<VK> + Sized {
150-
fn reactive_value_render_init_unpinned_default<Out>(
151-
self,
152-
renderer: impl RenderValueOnce<VK, RenderOutput = Out>,
153-
) -> (Self::UnpinnedStateDefault, Out) {
154-
let (state, out) = self.reactive_value_render_init_unpinned(renderer);
155-
(state.into(), out)
156-
}
157-
158-
fn reactive_value_render_init_with_old_state_unpinned_default<Out>(
159-
self,
160-
renderer: impl RenderValueOnce<VK, RenderOutput = Out>,
161-
old_state: &mut Self::UnpinnedStateDefault,
162-
) -> Out {
163-
if let Some(old_state) = AsOptionMut::<Self::UnpinnedState>::as_option_mut(old_state) {
164-
self.reactive_value_render_init_with_old_state_unpinned(renderer, old_state)
165-
} else {
166-
// I pray for the compiler to optimize out this branch when StateUnpinnedDefault::as_option_mut() always returns Some(_)
167-
let out;
168-
(*old_state, out) = self.reactive_value_render_init_unpinned_default(renderer);
169-
out
170-
}
171-
}
172-
173-
/// Note that this method requires `state` to be Some or will panic.
174-
///
175-
/// `renderer` doesn't need to be updated if unnecessary.
176-
fn reactive_value_render_update_unpinned_default<Out>(
177-
self,
178-
renderer: impl RenderValueOnce<VK, RenderOutput = Out>,
179-
state: &mut Self::UnpinnedStateDefault,
180-
) -> Option<Out> {
181-
if let Some(state) = AsOptionMut::<Self::UnpinnedState>::as_option_mut(state) {
182-
self.reactive_value_render_update_unpinned(renderer, state)
183-
} else {
184-
::core::panic!("state should have been initialized before render_update")
185-
}
186-
}
187-
}
102+
pub trait ReactiveValueExt<VK: ?Sized + ReactiveValueKind>: ReactiveValue<VK> + Sized {}
188103
impl<T: ReactiveValue<VK>, VK: ?Sized + ReactiveValueKind> ReactiveValueExt<VK> for T {}
189104

190-
macro_rules! impl_reactive_value_pinned_with_unpinned {
105+
#[macro_export]
106+
macro_rules! impl_reactive_value_unpinned_with_pinned {
191107
(
192108
type ReactiveValueKind = $ReactiveValueKind:ty;
193109
) => {
194-
type PinnedState = Self::UnpinnedState;
195-
type PinnedStateDefault = Self::UnpinnedStateDefault;
110+
type UnpinnedState = Self::PinnedState;
196111

197-
fn reactive_value_render_init_pinned<Out>(
112+
fn unpinned_render_init<Out>(
198113
self,
199-
renderer: impl $crate::reactive_value::RenderValueOnce<
114+
renderer: impl ::core::ops::FnOnce(
115+
<$ReactiveValueKind as $crate::reactive_value::ReactiveValueKind>::Value<'_>,
116+
) -> Out,
117+
) -> (Self::UnpinnedState, Out) {
118+
let (mut state, render_init) = <Self as $crate::reactive_value::ReactiveValue<
200119
$ReactiveValueKind,
201-
RenderOutput = Out,
202-
>,
203-
default_state: ::core::pin::Pin<&mut Self::PinnedStateDefault>,
204-
) -> Out {
205-
let default_state = default_state.get_mut();
206-
207-
::core::debug_assert!(
208-
<Self::PinnedStateDefault as $crate::reactive_value::AsOptionMut<
209-
Self::PinnedState,
210-
>>::as_option_mut(default_state)
211-
.is_none(),
212-
"state must be set to default before render_init"
213-
);
214-
215-
let out;
216-
(*default_state, out) = <Self as $crate::reactive_value::ReactiveValueExt<
217-
$ReactiveValueKind,
218-
>>::reactive_value_render_init_unpinned_default(
219-
self, renderer
220-
);
221-
222-
out
120+
>>::pinned_render_init(self);
121+
122+
let out =
123+
<Self::PinnedRenderInit as $crate::reactive_value::ReactiveValueRenderInitPinned<
124+
$ReactiveValueKind,
125+
>>::render_init_pinned(
126+
render_init, renderer, ::core::pin::Pin::new(&mut state)
127+
);
128+
(state, out)
223129
}
224130

225-
fn reactive_value_render_init_with_old_state_pinned<Out>(
131+
fn unpinned_render_init_by_reusing<Out>(
226132
self,
227-
renderer: impl $crate::reactive_value::RenderValueOnce<
133+
renderer: impl $crate::reactive_value::ReusableRendererOfKind<
228134
$ReactiveValueKind,
229-
RenderOutput = Out,
135+
Output = Out,
230136
>,
231-
old_state: ::core::pin::Pin<&mut Self::PinnedStateDefault>,
137+
reused_state: &mut Self::UnpinnedState,
232138
) -> Out {
233139
#[rustfmt::skip]
234-
let out = <Self as $crate::reactive_value::ReactiveValueExt<
235-
$ReactiveValueKind,
236-
>>::reactive_value_render_init_with_old_state_unpinned_default(
237-
self, renderer, old_state.get_mut()
140+
return <Self as $crate::reactive_value::ReactiveValue::<
141+
$ReactiveValueKind
142+
>>::pinned_render_init_by_reusing(
143+
self,
144+
renderer,
145+
::core::pin::Pin::new(reused_state),
238146
);
239-
out
240147
}
241148

242-
fn reactive_value_render_update_pinned<Out>(
149+
fn unpinned_render_update<Out>(
243150
self,
244-
renderer: impl $crate::reactive_value::RenderValueOnce<str, RenderOutput = Out>,
245-
state: ::core::pin::Pin<&mut Self::PinnedStateDefault>,
246-
) -> ::core::option::Option<Out> {
151+
renderer: impl ::core::ops::FnOnce(
152+
<$ReactiveValueKind as $crate::reactive_value::ReactiveValueKind>::Value<'_>,
153+
) -> Out,
154+
state: &mut Self::UnpinnedState,
155+
) -> Option<Out> {
247156
#[rustfmt::skip]
248-
let out = <Self as $crate::reactive_value::ReactiveValueExt<
157+
return <Self as $crate::reactive_value::ReactiveValue::<
249158
$ReactiveValueKind,
250-
>>::reactive_value_render_update_unpinned_default(
251-
self, renderer, state.get_mut()
252-
);
253-
out
159+
>>::pinned_render_update(self, renderer, ::core::pin::Pin::new(state));
254160
}
255161
};
256162
}
257163

258-
use impl_reactive_value_pinned_with_unpinned;
164+
use impl_reactive_value_unpinned_with_pinned;

0 commit comments

Comments
 (0)