1#[cfg(test)]
2mod tests;
3
4use serde::de::DeserializeOwned;
5use serde_intermediate::{from_intermediate, Change, Intermediate};
6use std::{
7 collections::{HashMap, HashSet},
8 hash::Hash,
9};
10
11#[cfg(feature = "derive")]
12pub use serde_reflect_intermediate_derive::*;
13
14pub trait ReflectIntermediate {
15 fn patch_change(&mut self, _change: &Change) {}
16
17 fn before_patch_change(&mut self) {}
18
19 fn after_patch_change(&mut self) {}
20}
21
22macro_rules! impl_reflect {
23 (@atom $type:ty => $( $variant:ident ),+ ) => {
24 impl ReflectIntermediate for $type {
25 fn patch_change(&mut self, change: &Change) {
26 #[allow(clippy::collapsible_match)]
27 if let Change::Changed(v) = change {
28 match v {
29 $(
30 Intermediate::$variant(v) => if let Ok(v) = Self::try_from(*v) {
31 *self = v;
32 }
33 )+
34 _ => {}
35 }
36 }
37 }
38 }
39 };
40}
41
42impl ReflectIntermediate for () {}
43
44impl_reflect! { @atom bool => Bool }
45impl_reflect! { @atom i8 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128 }
46impl_reflect! { @atom i16 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128 }
47impl_reflect! { @atom i32 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128 }
48impl_reflect! { @atom i64 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128 }
49impl_reflect! { @atom i128 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128 }
50impl_reflect! { @atom isize => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128 }
51impl_reflect! { @atom u8 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128, Char }
52impl_reflect! { @atom u16 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128 }
53impl_reflect! { @atom u32 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128, Char }
54impl_reflect! { @atom u64 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128, Char }
55impl_reflect! { @atom u128 => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128, Char }
56impl_reflect! { @atom usize => Bool, I8, I16, I32, I64, I128, U8, U16, U32, U64, U128 }
57impl_reflect! { @atom f32 => I8, I16, U8, U16, F32 }
58impl_reflect! { @atom f64 => I8, I16, I32, U8, U16, U32, F32, F64 }
59impl_reflect! { @atom char => U8, U32, Char }
60
61impl ReflectIntermediate for String {
62 fn patch_change(&mut self, change: &Change) {
63 if let Change::Changed(v) = change {
64 match v {
65 Intermediate::Char(v) => {
66 if let Ok(v) = Self::try_from(*v) {
67 *self = v;
68 }
69 }
70 Intermediate::String(v) => *self = v.to_owned(),
71 _ => {}
72 }
73 }
74 }
75}
76
77impl<T> ReflectIntermediate for Option<T>
78where
79 T: ReflectIntermediate + DeserializeOwned,
80{
81 fn patch_change(&mut self, change: &Change) {
82 match change {
83 Change::Changed(v) => {
84 if let Ok(v) = from_intermediate(v) {
85 *self = v;
86 }
87 }
88 Change::PartialChange(change) => {
89 if let Some(content) = self {
90 content.patch_change(change);
91 }
92 }
93 _ => {}
94 }
95 }
96}
97
98impl<T, E> ReflectIntermediate for Result<T, E>
99where
100 T: ReflectIntermediate + DeserializeOwned,
101 E: ReflectIntermediate + DeserializeOwned,
102{
103 fn patch_change(&mut self, change: &Change) {
104 match change {
105 Change::Changed(v) => {
106 if let Ok(v) = from_intermediate(v) {
107 *self = v;
108 }
109 }
110 Change::PartialChange(change) => match self {
111 Ok(content) => content.patch_change(change),
112 Err(content) => content.patch_change(change),
113 },
114 _ => {}
115 }
116 }
117}
118
119impl<T, const N: usize> ReflectIntermediate for [T; N]
120where
121 T: ReflectIntermediate + DeserializeOwned,
122{
123 fn patch_change(&mut self, change: &Change) {
124 match change {
125 Change::Changed(Intermediate::Seq(v)) => {
126 for (item, v) in self.iter_mut().zip(v.iter()) {
127 if let Ok(v) = from_intermediate(v) {
128 *item = v;
129 }
130 }
131 }
132 Change::PartialSeq(v) => {
133 for (index, change) in v {
134 if *index < N {
135 self[*index].patch_change(change);
136 }
137 }
138 }
139 _ => {}
140 }
141 }
142}
143
144impl<T> ReflectIntermediate for (T,)
145where
146 T: ReflectIntermediate + DeserializeOwned,
147{
148 fn patch_change(&mut self, change: &Change) {
149 match change {
150 Change::Changed(Intermediate::Seq(v)) => {
151 if let Some(v) = v.get(0) {
152 if let Ok(v) = from_intermediate(v) {
153 self.0 = v;
154 }
155 }
156 }
157 Change::PartialSeq(v) => {
158 for (index, change) in v {
159 if *index == 0 {
160 self.0.patch_change(change);
161 }
162 }
163 }
164 _ => {}
165 }
166 }
167}
168
169macro_rules! impl_tuple {
170 ( $( $id:ident : $index:tt ),+ ) => {
171 impl< $( $id ),+ > ReflectIntermediate for ( $( $id ),+ )
172 where
173 $( $id: ReflectIntermediate + DeserializeOwned ),+
174 {
175 fn patch_change(&mut self, change: &Change) {
176 match change {
177 Change::Changed(Intermediate::Seq(v)) => {
178 $(
179 if let Some(v) = v.get($index) {
180 if let Ok(v) = from_intermediate(v) {
181 self.$index = v;
182 }
183 }
184 )+
185 }
186 Change::PartialSeq(v) => {
187 $(
188 if let Some((_,change)) = v.iter().find(|(i,_)| *i == $index) {
189 self.$index.patch_change(change);
190 }
191 )+
192 }
193 _ => {}
194 }
195 }
196 }
197 };
198}
199
200impl_tuple! { A:0, B:1 }
201impl_tuple! { A:0, B:1, C:2 }
202impl_tuple! { A:0, B:1, C:2, D:3 }
203impl_tuple! { A:0, B:1, C:2, D:3, E:4 }
204impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5 }
205impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6 }
206impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7 }
207impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8 }
208impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9 }
209impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10 }
210impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11 }
211impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12 }
212impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13 }
213impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14 }
214impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15 }
215impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16 }
216impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17 }
217impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18 }
218impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19 }
219impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20 }
220impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20, V:21 }
221impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20, V:21, X:22 }
222impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20, V:21, X:22, Y:23 }
223impl_tuple! { A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20, V:21, X:22, Y:23, Z:24 }
224
225impl<T> ReflectIntermediate for Vec<T>
226where
227 T: ReflectIntermediate + DeserializeOwned,
228{
229 fn patch_change(&mut self, change: &Change) {
230 match change {
231 Change::Changed(v) => {
232 if let Ok(v) = from_intermediate(v) {
233 *self = v;
234 }
235 }
236 Change::PartialSeq(v) => {
237 for (index, change) in v {
238 match change {
239 Change::Removed => {
240 self.remove(*index);
241 }
242 Change::Added(v) => {
243 if let Ok(v) = from_intermediate(v) {
244 self.insert(*index, v);
245 }
246 }
247 change => {
248 if let Some(item) = self.get_mut(*index) {
249 item.patch_change(change);
250 }
251 }
252 }
253 }
254 }
255 _ => {}
256 }
257 }
258}
259
260impl<T> ReflectIntermediate for HashSet<T>
261where
262 T: ReflectIntermediate + DeserializeOwned + Hash + Eq + Clone,
263{
264 fn patch_change(&mut self, change: &Change) {
265 match change {
266 Change::Changed(v) => {
267 if let Ok(v) = from_intermediate(v) {
268 *self = v;
269 }
270 }
271 Change::PartialSeq(v) => {
272 let mut data = self.iter().cloned().collect::<Vec<_>>();
273 for (index, change) in v {
274 match change {
275 Change::Removed => {
276 data.remove(*index);
277 }
278 Change::Added(v) => {
279 if let Ok(v) = from_intermediate(v) {
280 data.insert(*index, v);
281 }
282 }
283 change => {
284 if let Some(item) = data.get_mut(*index) {
285 item.patch_change(change);
286 }
287 }
288 }
289 }
290 *self = data.into_iter().collect();
291 }
292 _ => {}
293 }
294 }
295}
296
297impl<K, V> ReflectIntermediate for HashMap<K, V>
298where
299 K: ReflectIntermediate + DeserializeOwned + Hash + Eq,
300 V: ReflectIntermediate + DeserializeOwned,
301{
302 fn patch_change(&mut self, change: &Change) {
303 match change {
304 Change::Changed(v) => {
305 if let Ok(v) = from_intermediate(v) {
306 *self = v;
307 }
308 }
309 Change::PartialMap(v) => {
310 for (key, change) in v {
311 if let Ok(key) = from_intermediate(key) {
312 match change {
313 Change::Removed => {
314 self.remove(&key);
315 }
316 Change::Added(v) => {
317 if let Ok(v) = from_intermediate(v) {
318 self.insert(key, v);
319 }
320 }
321 change => {
322 if let Some(item) = self.get_mut(&key) {
323 item.patch_change(change);
324 }
325 }
326 }
327 }
328 }
329 }
330 _ => {}
331 }
332 }
333}
334
335impl<T> ReflectIntermediate for Box<T>
336where
337 T: ReflectIntermediate + DeserializeOwned,
338{
339 fn patch_change(&mut self, change: &Change) {
340 match change {
341 Change::Changed(v) => {
342 if let Ok(v) = from_intermediate(v) {
343 *self = v;
344 }
345 }
346 Change::PartialChange(change) => {
347 self.patch_change(change);
348 }
349 _ => {}
350 }
351 }
352}