serde_reflect_intermediate/
lib.rs

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}