1use std::cell::Cell;
2
3use ribir_algo::Sc;
4use rxrust::{
5 ops::box_it::CloneableBoxOp,
6 prelude::{BoxIt, ObservableExt},
7};
8
9use super::{
10 state_cell::PartData, MapWriterAsReader, ModifyScope, Notifier, ReadRef, StateReader,
11 StateWatcher, StateWriter, WriteRef, WriterControl,
12};
13use crate::{
14 context::BuildCtx,
15 prelude::AppCtx,
16 state::state_cell::ValueMutRef,
17 ticker::Instant,
18 widget::{Render, RenderBuilder, Widget},
19};
20
21pub struct SplittedWriter<O, W> {
23 origin: O,
24 splitter: W,
25 notifier: Notifier,
26 batched_modify: Sc<Cell<ModifyScope>>,
27 create_at: Instant,
28 last_modified: Sc<Cell<Instant>>,
29 ref_count: Sc<Cell<usize>>,
30}
31
32impl<O, W> Drop for SplittedWriter<O, W> {
33 fn drop(&mut self) {
34 if self.ref_count.get() == 1 {
35 let mut notifier = self.notifier.clone();
36 let _ = AppCtx::spawn_local(async move {
39 notifier.unsubscribe();
40 });
41 }
42 }
43}
44
45impl<V, O, W> StateReader for SplittedWriter<O, W>
46where
47 Self: 'static,
48 O: StateWriter,
49 W: Fn(&mut O::Value) -> PartData<V> + Clone,
50{
51 type Value = V;
52 type OriginReader = O;
53 type Reader = MapWriterAsReader<O::Reader, W>;
54
55 #[track_caller]
56 fn read(&self) -> ReadRef<Self::Value> {
57 ReadRef::mut_as_ref_map(self.origin.read(), &self.splitter)
58 }
59
60 #[inline]
61 fn clone_reader(&self) -> Self::Reader {
62 MapWriterAsReader { origin: self.origin.clone_reader(), part_map: self.splitter.clone() }
63 }
64
65 #[inline]
66 fn origin_reader(&self) -> &Self::OriginReader { &self.origin }
67
68 #[inline]
69 fn try_into_value(self) -> Result<Self::Value, Self>
70 where
71 Self::Value: Sized,
72 {
73 Err(self)
74 }
75}
76
77struct StampCheck<R> {
79 stamp: Instant,
80 reader: R,
81}
82
83impl<R: StateReader> CloneableChecker for StampCheck<R> {
84 fn check(&self) -> bool { true }
85 fn box_clone(&self) -> Box<dyn CloneableChecker> {
86 Box::new(StampCheck { stamp: self.stamp, reader: self.reader.clone_reader() })
87 }
88}
89
90trait CloneableChecker {
91 fn check(&self) -> bool;
92 fn box_clone(&self) -> Box<dyn CloneableChecker>;
93}
94
95impl Clone for Box<dyn CloneableChecker> {
96 fn clone(&self) -> Self { self.box_clone() }
97}
98
99impl<V, O, W> StateWatcher for SplittedWriter<O, W>
100where
101 Self: 'static,
102 O: StateWriter,
103 W: Fn(&mut O::Value) -> PartData<V> + Clone,
104{
105 fn raw_modifies(&self) -> CloneableBoxOp<'static, ModifyScope, std::convert::Infallible> {
106 let origin = self.origin.clone_reader();
107 let create_at = self.create_at;
108
109 let checker: Box<dyn CloneableChecker> =
111 Box::new(StampCheck { stamp: create_at, reader: origin.clone_reader() });
112
113 self
114 .notifier
115 .raw_modifies()
116 .take_while(move |_| checker.check())
117 .box_it()
118 }
119}
120
121impl<V, O, W> StateWriter for SplittedWriter<O, W>
122where
123 Self: 'static,
124 O: StateWriter,
125 W: Fn(&mut O::Value) -> PartData<V> + Clone,
126{
127 type Writer = SplittedWriter<O::Writer, W>;
128 type OriginWriter = O;
129
130 #[inline]
131 fn write(&self) -> WriteRef<Self::Value> { self.split_ref(self.origin.write()) }
132
133 #[inline]
134 fn silent(&self) -> WriteRef<Self::Value> { self.split_ref(self.origin.silent()) }
135
136 #[inline]
137 fn shallow(&self) -> WriteRef<Self::Value> { self.split_ref(self.origin.shallow()) }
138
139 fn clone_writer(&self) -> Self::Writer {
140 SplittedWriter {
141 origin: self.origin.clone_writer(),
142 splitter: self.splitter.clone(),
143 notifier: self.notifier.clone(),
144 batched_modify: self.batched_modify.clone(),
145 last_modified: self.last_modified.clone(),
146 create_at: self.create_at,
147 ref_count: self.ref_count.clone(),
148 }
149 }
150
151 #[inline]
152 fn origin_writer(&self) -> &Self::OriginWriter { &self.origin }
153}
154
155impl<V, O, W> WriterControl for SplittedWriter<O, W>
156where
157 Self: 'static,
158 O: StateWriter,
159 W: Fn(&mut O::Value) -> PartData<V> + Clone,
160{
161 #[inline]
162 fn batched_modifies(&self) -> &Cell<ModifyScope> { &self.batched_modify }
163
164 #[inline]
165 fn notifier(&self) -> &Notifier { &self.notifier }
166
167 #[inline]
168 fn dyn_clone(&self) -> Box<dyn WriterControl> { Box::new(self.clone_writer()) }
169}
170
171impl<V, O, W> SplittedWriter<O, W>
172where
173 Self: 'static,
174 O: StateWriter,
175 W: Fn(&mut O::Value) -> PartData<V> + Clone,
176{
177 pub(super) fn new(origin: O, mut_map: W) -> Self {
178 let create_at = Instant::now();
179
180 Self {
181 origin,
182 splitter: mut_map,
183 notifier: Notifier::default(),
184 batched_modify: <_>::default(),
185 last_modified: Sc::new(Cell::new(create_at)),
186 create_at,
187 ref_count: Sc::new(Cell::new(1)),
188 }
189 }
190
191 #[track_caller]
192 fn split_ref<'a>(&'a self, mut orig: WriteRef<'a, O::Value>) -> WriteRef<'a, V> {
193 let modify_scope = orig.modify_scope;
194
195 assert!(!orig.modified);
198 orig.modify_scope.remove(ModifyScope::FRAMEWORK);
199 orig.modified = true;
200 let value =
201 ValueMutRef { value: (self.splitter)(&mut orig.value), borrow: orig.value.borrow.clone() };
202
203 WriteRef { value, modified: false, modify_scope, control: self }
204 }
205}
206
207impl<V, O, W> RenderBuilder for SplittedWriter<O, W>
208where
209 O: StateWriter,
210 W: Fn(&mut O::Value) -> PartData<V> + Clone + 'static,
211 V: Render,
212{
213 fn build(self, ctx: &BuildCtx) -> Widget {
214 MapWriterAsReader { origin: self.origin.clone_reader(), part_map: self.splitter.clone() }
215 .build(ctx)
216 }
217}