|
1 | | -pub use self::render_value::{ |
2 | | - RenderValueMut, RenderValueOnce, RenderValueWithFn, RenderValueWithFnMutAndData, |
3 | | - RenderValueWithFnOnceAndData, |
4 | | -}; |
5 | | - |
6 | 1 | use std::{pin::Pin, task::Poll}; |
7 | 2 |
|
8 | 3 | use crate::csr::StateUnmount; |
9 | 4 |
|
10 | | -mod render_value; |
11 | | - |
12 | | -mod option; |
13 | | -pub mod str; |
| 5 | +pub mod csr_str; |
| 6 | +pub mod simple_non_reactive; |
14 | 7 |
|
15 | 8 | pub trait ReactiveValueKind: 'static { |
16 | 9 | type Value<'a>; |
17 | 10 | } |
18 | 11 |
|
19 | | -impl ReactiveValueKind for str { |
20 | | - type Value<'a> = &'a str; |
21 | | -} |
22 | | - |
23 | 12 | pub trait ReactiveValueState: StateUnmount { |
24 | 13 | type ReactiveValueKind: ?Sized + ReactiveValueKind; |
25 | 14 |
|
26 | | - fn reactive_value_state_poll_render( |
| 15 | + fn poll_render( |
27 | 16 | self: Pin<&mut Self>, |
28 | | - renderer: &mut impl RenderValueMut<Self::ReactiveValueKind, RenderOutput = ()>, |
| 17 | + renderer: impl FnMut(<Self::ReactiveValueKind as ReactiveValueKind>::Value<'_>), |
29 | 18 | cx: &mut std::task::Context<'_>, |
30 | 19 | ) -> Poll<()>; |
31 | 20 | } |
32 | 21 |
|
33 | 22 | impl<T: ReactiveValueState> ReactiveValueState for Option<T> { |
34 | 23 | type ReactiveValueKind = T::ReactiveValueKind; |
35 | 24 |
|
36 | | - fn reactive_value_state_poll_render( |
| 25 | + fn poll_render( |
37 | 26 | self: Pin<&mut Self>, |
38 | | - renderer: &mut impl RenderValueMut<Self::ReactiveValueKind, RenderOutput = ()>, |
| 27 | + renderer: impl FnMut(<Self::ReactiveValueKind as ReactiveValueKind>::Value<'_>), |
39 | 28 | cx: &mut std::task::Context<'_>, |
40 | 29 | ) -> Poll<()> { |
41 | 30 | if let Some(this) = self.as_pin_mut() { |
42 | | - this.reactive_value_state_poll_render(renderer, cx) |
| 31 | + this.poll_render(renderer, cx) |
43 | 32 | } else { |
44 | 33 | Poll::Ready(()) |
45 | 34 | } |
46 | 35 | } |
47 | 36 | } |
48 | 37 |
|
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; |
61 | 40 |
|
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; |
63 | 46 | } |
64 | 47 |
|
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; |
74 | 50 | } |
75 | 51 |
|
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; |
85 | 57 | } |
86 | 58 |
|
87 | | -/// The value is optional. That's why [`RenderValueOnce`] and [`RenderValueMut`] have a `remove*` method. |
88 | 59 | pub trait ReactiveValue<VK: ?Sized + ReactiveValueKind> { |
89 | | - type PinnedState; |
| 60 | + type PinnedState: ReactiveValueState<ReactiveValueKind = VK>; |
| 61 | + type PinnedRenderInit: ReactiveValueRenderInitPinned<VK, State = Self::PinnedState>; |
90 | 62 |
|
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`. |
98 | 64 | type UnpinnedState: Unpin + ReactiveValueState<ReactiveValueKind = VK>; |
99 | 65 |
|
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 | | - |
109 | 66 | /// `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); |
115 | 68 |
|
116 | 69 | /// `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>( |
118 | 71 | 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>, |
121 | 74 | ) -> Out; |
122 | 75 |
|
123 | 76 | /// `renderer` doesn't need to be updated if unnecessary. |
124 | | - fn reactive_value_render_update_pinned<Out>( |
| 77 | + fn pinned_render_update<Out>( |
125 | 78 | 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>, |
128 | 81 | ) -> Option<Out>; |
129 | 82 |
|
130 | | - fn reactive_value_render_init_unpinned<Out>( |
| 83 | + fn unpinned_render_init<Out>( |
131 | 84 | self, |
132 | | - renderer: impl RenderValueOnce<VK, RenderOutput = Out>, |
| 85 | + renderer: impl FnOnce(VK::Value<'_>) -> Out, |
133 | 86 | ) -> (Self::UnpinnedState, Out); |
134 | 87 |
|
135 | | - fn reactive_value_render_init_with_old_state_unpinned<Out>( |
| 88 | + fn unpinned_render_init_by_reusing<Out>( |
136 | 89 | 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, |
139 | 92 | ) -> Out; |
140 | 93 |
|
141 | 94 | /// `renderer` doesn't need to be updated if unnecessary. |
142 | | - fn reactive_value_render_update_unpinned<Out>( |
| 95 | + fn unpinned_render_update<Out>( |
143 | 96 | self, |
144 | | - renderer: impl RenderValueOnce<VK, RenderOutput = Out>, |
| 97 | + renderer: impl FnOnce(VK::Value<'_>) -> Out, |
145 | 98 | state: &mut Self::UnpinnedState, |
146 | 99 | ) -> Option<Out>; |
147 | 100 | } |
148 | 101 |
|
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 {} |
188 | 103 | impl<T: ReactiveValue<VK>, VK: ?Sized + ReactiveValueKind> ReactiveValueExt<VK> for T {} |
189 | 104 |
|
190 | | -macro_rules! impl_reactive_value_pinned_with_unpinned { |
| 105 | +#[macro_export] |
| 106 | +macro_rules! impl_reactive_value_unpinned_with_pinned { |
191 | 107 | ( |
192 | 108 | type ReactiveValueKind = $ReactiveValueKind:ty; |
193 | 109 | ) => { |
194 | | - type PinnedState = Self::UnpinnedState; |
195 | | - type PinnedStateDefault = Self::UnpinnedStateDefault; |
| 110 | + type UnpinnedState = Self::PinnedState; |
196 | 111 |
|
197 | | - fn reactive_value_render_init_pinned<Out>( |
| 112 | + fn unpinned_render_init<Out>( |
198 | 113 | 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< |
200 | 119 | $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) |
223 | 129 | } |
224 | 130 |
|
225 | | - fn reactive_value_render_init_with_old_state_pinned<Out>( |
| 131 | + fn unpinned_render_init_by_reusing<Out>( |
226 | 132 | self, |
227 | | - renderer: impl $crate::reactive_value::RenderValueOnce< |
| 133 | + renderer: impl $crate::reactive_value::ReusableRendererOfKind< |
228 | 134 | $ReactiveValueKind, |
229 | | - RenderOutput = Out, |
| 135 | + Output = Out, |
230 | 136 | >, |
231 | | - old_state: ::core::pin::Pin<&mut Self::PinnedStateDefault>, |
| 137 | + reused_state: &mut Self::UnpinnedState, |
232 | 138 | ) -> Out { |
233 | 139 | #[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), |
238 | 146 | ); |
239 | | - out |
240 | 147 | } |
241 | 148 |
|
242 | | - fn reactive_value_render_update_pinned<Out>( |
| 149 | + fn unpinned_render_update<Out>( |
243 | 150 | 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> { |
247 | 156 | #[rustfmt::skip] |
248 | | - let out = <Self as $crate::reactive_value::ReactiveValueExt< |
| 157 | + return <Self as $crate::reactive_value::ReactiveValue::< |
249 | 158 | $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)); |
254 | 160 | } |
255 | 161 | }; |
256 | 162 | } |
257 | 163 |
|
258 | | -use impl_reactive_value_pinned_with_unpinned; |
| 164 | +use impl_reactive_value_unpinned_with_pinned; |
0 commit comments