1use crate::{
2 apply::ApplyContext,
3 difference::{DiffCommandRef, DiffContext, DiffPathElementValue},
4 SerdeDiff,
5};
6
7use serde::{de, ser::SerializeSeq, Deserialize, Serialize};
8
9use std::{
10 collections::{BTreeMap, HashMap},
11 hash::Hash,
12};
13
14macro_rules! array_impls {
15 ($($len:tt)+) => {
16 $(
17 impl<T: $crate::SerdeDiff + serde::Serialize + for<'a> serde::Deserialize<'a>> $crate::SerdeDiff for [T; $len] {
18 fn diff<'a, S: serde::ser::SerializeSeq>(
19 &self,
20 ctx: &mut $crate::difference::DiffContext<'a, S>,
21 other: &Self,
22 ) -> Result<bool, S::Error> {
23 use $crate::difference::DiffCommandRef;
24
25 let mut need_exit = false;
26 let mut changed = false;
27 for (idx, (self_item, other_item)) in self.iter().zip(other.iter()).enumerate() {
28 ctx.push_collection_index(idx);
29 if <T as $crate::SerdeDiff>::diff(self_item, ctx, other_item)? {
30 need_exit = true;
31 changed = true;
32 }
33 ctx.pop_path_element()?;
34 }
35 if need_exit {
36 ctx.save_command::<()>(&DiffCommandRef::Exit, true, false)?;
37 }
38 Ok(changed)
39 }
40
41 fn apply<'de, A>(
42 &mut self,
43 seq: &mut A,
44 ctx: &mut $crate::apply::ApplyContext,
45 ) -> Result<bool, <A as serde::de::SeqAccess<'de>>::Error>
46 where
47 A: serde::de::SeqAccess<'de>,
48 {
49 let mut changed = false;
50 while let Some(cmd) = ctx.read_next_command::<A, T>(seq)? {
51 use $crate::difference::DiffCommandValue::*;
52 use $crate::difference::DiffPathElementValue::*;
53 match cmd {
54 Enter(Field(_)) => {
56 ctx.skip_value(seq)?;
57 break;
58 }
59 Enter(CollectionIndex(idx)) => {
60 if let Some(value_ref) = self.get_mut(idx) {
61 changed |= <T as $crate::SerdeDiff>::apply(value_ref, seq, ctx)?;
62 } else {
63 ctx.skip_value(seq)?;
64 }
65 }
66 _ => break,
67 }
68 }
69 Ok(changed)
70 }
71 }
72 )+
73 }
74}
75
76array_impls! {
77 01 02 03 04 05 06 07 08 09 10
78 11 12 13 14 15 16 17 18 19 20
79 21 22 23 24 25 26 27 28 29 30
80 31 32
81 40 48 50 56 64 72 96 100 128 160 192 200 224 256 384 512
82 768 1024 2048 4096 8192 16384 32768 65536
83}
84
85macro_rules! tuple_impls {
86 ($($len:expr => ($($n:tt $name:ident)+))+) => {
87 $(
88 impl<$($name),+> $crate::SerdeDiff for ($($name,)+)
89 where
90 $($name: $crate::SerdeDiff + serde::Serialize + for<'a> serde::Deserialize<'a>,)+
91 {
92 fn diff<'a, S: serde::ser::SerializeSeq>(
93 &self,
94 ctx: &mut $crate::difference::DiffContext<'a, S>,
95 other: &Self,
96 ) -> Result<bool, S::Error> {
97 let mut changed = false;
98 $(
99 ctx.push_field(stringify!($n));
100 changed |= <$name as $crate::SerdeDiff>::diff(&self.$n, ctx, &other.$n)?;
101 ctx.pop_path_element()?;
102 )+
103 Ok(changed)
104 }
105
106 fn apply<'de, A>(
107 &mut self,
108 seq: &mut A,
109 ctx: &mut $crate::apply::ApplyContext,
110 ) -> Result<bool, <A as serde::de::SeqAccess<'de>>::Error>
111 where
112 A: serde::de::SeqAccess<'de>,
113 {
114 let mut changed = false;
115 while let Some($crate::difference::DiffPathElementValue::Field(element)) = ctx.next_path_element(seq)? {
116 match element.as_ref() {
117 $(
118 stringify!($n) => changed |= <$name as $crate::SerdeDiff>::apply(&mut self.$n, seq, ctx)?,
119 )+
120 _ => ctx.skip_value(seq)?,
121 }
122 }
123 Ok(changed)
124 }
125 }
126 )+
127 }
128}
129
130tuple_impls! {
131 1 => (0 T0)
132 2 => (0 T0 1 T1)
133 3 => (0 T0 1 T1 2 T2)
134 4 => (0 T0 1 T1 2 T2 3 T3)
135 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
136 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
137 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
138 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
139 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
140 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
141 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
142 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
143 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
144 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
145 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
146 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
147}
148macro_rules! map_serde_diff {
150 ($t:ty, $($extra_traits:path),*) => {
151 impl<K, V> SerdeDiff for $t
152 where
153 K: SerdeDiff + Serialize + for<'a> Deserialize<'a> $(+ $extra_traits)*, V: SerdeDiff + Serialize + for<'a> Deserialize<'a>,
155 {
156 fn diff<'a, S: SerializeSeq>(
157 &self,
158 ctx: &mut $crate::difference::DiffContext<'a, S>,
159 other: &Self,
160 ) -> Result<bool, S::Error> {
161 use $crate::difference::DiffCommandRef;
162
163 let mut changed = false;
164
165 for (key, self_value) in self.iter() {
167 match other.get(key) {
168 Some(other_value) => {
169 let save_closure = |serializer: &mut S| serializer.serialize_element(&DiffCommandRef::EnterKey(key));
170 let mut subctx = ctx.reborrow();
171 subctx.push_field_element(&save_closure);
172 if <V as SerdeDiff>::diff(self_value, &mut subctx, other_value)? {
173 changed = true;
174 }
175 },
176 None => {
177 ctx.save_command(&DiffCommandRef::RemoveKey(key), true, true)?;
178 changed = true;
179 },
180 }
181 }
182
183 for (key, other_value) in other.iter() {
184 if !self.contains_key(key) {
185 ctx.save_command(&DiffCommandRef::AddKey(key), true, true)?;
186 ctx.save_command(&DiffCommandRef::Value(other_value), true, true)?;
187 changed = true;
188 }
189 }
190
191 if changed {
192 ctx.save_command::<()>(&DiffCommandRef::Exit, true, false)?;
193 }
194 Ok(changed)
195 }
196
197 fn apply<'de, A>(
198 &mut self,
199 seq: &mut A,
200 ctx: &mut ApplyContext,
201 ) -> Result<bool, <A as de::SeqAccess<'de>>::Error>
202 where
203 A: de::SeqAccess<'de>,
204 {
205 let mut changed = false;
206 while let Some(cmd) = ctx.read_next_command::<A, K>(seq)? {
207 use $crate::difference::DiffCommandValue::*;
208 use $crate::difference::DiffPathElementValue::*;
209 match cmd {
210 Enter(Field(_)) => {
212 ctx.skip_value(seq)?;
213 break;
214 }
215 AddKey(key) => if let Some(Value(v)) = ctx.read_next_command(seq)? {
216 self.insert(key, v);
218 changed = true;
219 } else {
220 panic!("Expected value after AddKey");
221 }
222 EnterKey(key) => if let Some(value_ref) = self.get_mut(&key) {
223 changed |= <V as SerdeDiff>::apply(value_ref, seq, ctx)?;
224 } else {
225 ctx.skip_value(seq)?;
226 }
227 RemoveKey(key) => changed |= self.remove(&key).is_some(),
228 _ => break,
229 }
230 }
231 Ok(changed)
232 }
233 }
234 };
235}
236
237map_serde_diff!(HashMap<K, V>, Hash, Eq);
238map_serde_diff!(BTreeMap<K, V>, Ord);
239
240#[macro_export]
244macro_rules! opaque_serde_diff {
245 ($t:ty) => {
246 impl SerdeDiff for $t {
247 fn diff<'a, S: $crate::_serde::ser::SerializeSeq>(
248 &self,
249 ctx: &mut $crate::DiffContext<'a, S>,
250 other: &Self,
251 ) -> Result<bool, S::Error> {
252 if self != other {
253 ctx.save_value(other)?;
254 Ok(true)
255 } else {
256 Ok(false)
257 }
258 }
259
260 fn apply<'de, A>(
261 &mut self,
262 seq: &mut A,
263 ctx: &mut $crate::ApplyContext,
264 ) -> Result<bool, <A as $crate::_serde::de::SeqAccess<'de>>::Error>
265 where
266 A: $crate::_serde::de::SeqAccess<'de>,
267 {
268 ctx.read_value(seq, self)
269 }
270 }
271 };
272}
273
274opaque_serde_diff!(bool);
276opaque_serde_diff!(isize);
277opaque_serde_diff!(i8);
278opaque_serde_diff!(i16);
279opaque_serde_diff!(i32);
280opaque_serde_diff!(i64);
281opaque_serde_diff!(usize);
282opaque_serde_diff!(u8);
283opaque_serde_diff!(u16);
284opaque_serde_diff!(u32);
285opaque_serde_diff!(u64);
286opaque_serde_diff!(i128);
287opaque_serde_diff!(u128);
288opaque_serde_diff!(f32);
289opaque_serde_diff!(f64);
290opaque_serde_diff!(char);
291opaque_serde_diff!(String);
292opaque_serde_diff!(std::ffi::CString);
293#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
294opaque_serde_diff!(std::ffi::OsString);
295opaque_serde_diff!(std::num::NonZeroU8);
296opaque_serde_diff!(std::num::NonZeroU16);
297opaque_serde_diff!(std::num::NonZeroU32);
298opaque_serde_diff!(std::num::NonZeroU64);
299opaque_serde_diff!(std::time::Duration);
300opaque_serde_diff!(std::time::SystemTime);
301opaque_serde_diff!(std::net::IpAddr);
302opaque_serde_diff!(std::net::Ipv4Addr);
303opaque_serde_diff!(std::net::Ipv6Addr);
304opaque_serde_diff!(std::net::SocketAddr);
305opaque_serde_diff!(std::net::SocketAddrV4);
306opaque_serde_diff!(std::net::SocketAddrV6);
307opaque_serde_diff!(std::path::PathBuf);
308
309impl<T: SerdeDiff + Serialize + for<'a> Deserialize<'a>> SerdeDiff for Option<T> {
310 fn diff<'a, S: SerializeSeq>(
311 &self,
312 ctx: &mut DiffContext<'a, S>,
313 other: &Self,
314 ) -> Result<bool, S::Error> {
315 let mut self_iter = self.iter();
316 let mut other_iter = other.iter();
317 let mut idx = 0;
318 let mut need_exit = false;
319 let mut changed = false;
320 loop {
321 let self_item = self_iter.next();
322 let other_item = other_iter.next();
323 match (self_item, other_item) {
324 (None, None) => break,
325 (Some(_), None) => {
326 let mut num_to_remove = 1;
327 while self_iter.next().is_some() {
328 num_to_remove += 1;
329 }
330 ctx.save_command::<()>(&DiffCommandRef::Remove(num_to_remove), true, true)?;
331 changed = true;
332 }
333 (None, Some(other_item)) => {
334 ctx.save_command::<()>(
335 &DiffCommandRef::Enter(DiffPathElementValue::AddToCollection),
336 false,
337 true,
338 )?;
339 ctx.save_command(&DiffCommandRef::Value(other_item), true, true)?;
340 need_exit = true;
341 changed = true;
342 }
343 (Some(self_item), Some(other_item)) => {
344 ctx.push_collection_index(idx);
345 if <T as SerdeDiff>::diff(self_item, ctx, other_item)? {
346 need_exit = true;
347 changed = true;
348 }
349 ctx.pop_path_element()?;
350 }
351 }
352 idx += 1;
353 }
354 if need_exit {
355 ctx.save_command::<()>(&DiffCommandRef::Exit, true, false)?;
356 }
357 Ok(changed)
358 }
359
360 fn apply<'de, A>(
361 &mut self,
362 seq: &mut A,
363 ctx: &mut ApplyContext,
364 ) -> Result<bool, <A as de::SeqAccess<'de>>::Error>
365 where
366 A: de::SeqAccess<'de>,
367 {
368 let mut changed = false;
369 while let Some(cmd) = ctx.read_next_command::<A, T>(seq)? {
370 use crate::difference::DiffCommandValue::*;
371 use DiffPathElementValue::*;
372
373 match cmd {
374 Enter(Field(_)) => {
376 ctx.skip_value(seq)?;
377 break;
378 }
379 Enter(CollectionIndex(0)) => {
380 if let Some(value_ref) = self {
381 changed |= <T as SerdeDiff>::apply(value_ref, seq, ctx)?;
382 } else {
383 ctx.skip_value(seq)?;
384 }
385 }
386 Enter(AddToCollection) => {
387 if let Value(v) = ctx
388 .read_next_command(seq)?
389 .expect("Expected value after AddToCollection")
390 {
391 debug_assert!(self.is_none());
392 changed = true;
393 *self = Some(v);
394 } else {
395 panic!("Expected value after AddToCollection");
396 }
397 }
398 Remove(1) => {
399 *self = None;
400 changed = true;
401 break;
402 }
403 _ => break,
404 }
405 }
406 Ok(changed)
407 }
408}
409
410type Unit = ();
411opaque_serde_diff!(Unit);