1use crate::{
2 apply::ApplyContext, counting_serializer::CountingSerializer, Config, ElementStackEntry,
3 FieldPathMode, SerdeDiff,
4};
5use serde::{de, ser::SerializeSeq, Deserialize, Serialize, Serializer};
6use std::{borrow::Cow, cell::Cell};
7
8#[doc(hidden)]
10pub struct DiffContext<'a, S: SerializeSeq> {
11 element_stack: Option<Vec<ElementStackEntry<'a, S>>>,
14 serializer: &'a mut S,
16 implicit_exit_written: bool,
18 parent_element_stack: Option<&'a mut Option<Vec<ElementStackEntry<'a, S>>>>,
21 element_stack_start: usize,
27 field_path_mode: FieldPathMode,
29 has_changes: bool,
31}
32
33impl<'a, S: SerializeSeq> Drop for DiffContext<'a, S> {
34 fn drop(&mut self) {
35 if let Some(parent) = self.parent_element_stack.take() {
36 if let Some(mut stack) = self.element_stack.take() {
37 if self.element_stack_start < stack.len() {
38 stack.drain(self.element_stack_start..);
39 }
40 parent.replace(stack);
41 }
42 }
43 }
44}
45
46#[doc(hidden)]
47impl<'a, S: SerializeSeq> DiffContext<'a, S> {
48 pub fn field_path_mode(&self) -> FieldPathMode {
50 self.field_path_mode
51 }
52
53 pub fn has_changes(&self) -> bool {
55 self.has_changes
56 }
57
58 pub fn push_field(&mut self, field_name: &'static str) {
62 self.element_stack
63 .as_mut()
64 .unwrap()
65 .push(ElementStackEntry::PathElement(DiffPathElementValue::Field(
66 Cow::Borrowed(field_name),
67 )));
68 }
69
70 pub fn push_variant(&mut self, variant_name: &'static str) {
71 self.element_stack
72 .as_mut()
73 .unwrap()
74 .push(ElementStackEntry::PathElement(
75 DiffPathElementValue::EnumVariant(Cow::Borrowed(variant_name)),
76 ));
77 }
78
79 pub fn push_full_variant(&mut self) {
80 self.element_stack
81 .as_mut()
82 .unwrap()
83 .push(ElementStackEntry::PathElement(
84 DiffPathElementValue::FullEnumVariant,
85 ));
86 }
87
88 pub fn push_field_index(&mut self, field_idx: u16) {
92 self.element_stack
93 .as_mut()
94 .unwrap()
95 .push(ElementStackEntry::PathElement(
96 DiffPathElementValue::FieldIndex(field_idx),
97 ));
98 }
99
100 pub fn push_collection_index(&mut self, idx: usize) {
102 self.element_stack
103 .as_mut()
104 .unwrap()
105 .push(ElementStackEntry::PathElement(
106 DiffPathElementValue::CollectionIndex(idx),
107 ));
108 }
109 pub fn push_collection_add(&mut self) {
111 self.element_stack
112 .as_mut()
113 .unwrap()
114 .push(ElementStackEntry::PathElement(
115 DiffPathElementValue::AddToCollection,
116 ));
117 }
118
119 pub fn push_field_element(&mut self, f: &'a dyn Fn(&mut S) -> Result<(), S::Error>) {
120 self.element_stack
121 .as_mut()
122 .unwrap()
123 .push(ElementStackEntry::Closure(f));
124 }
125
126 pub fn pop_path_element(&mut self) -> Result<(), S::Error> {
128 let element_stack = self.element_stack.as_mut().unwrap();
129 if element_stack.is_empty() {
130 if !self.implicit_exit_written {
133 let cmd = DiffCommandRef::<()>::Exit;
134 self.serializer.serialize_element(&cmd)
135 } else {
136 self.implicit_exit_written = false;
137 Ok(())
138 }
139 } else {
140 element_stack.pop();
141 self.element_stack_start = std::cmp::min(element_stack.len(), self.element_stack_start);
142 Ok(())
143 }
144 }
145
146 pub fn save_value<T: Serialize>(&mut self, value: &T) -> Result<(), S::Error> {
148 self.save_command(&DiffCommandRef::Value(value), true, true)
149 }
150
151 pub fn save_command<'b, T: Serialize>(
154 &mut self,
155 value: &DiffCommandRef<'b, T>,
156 implicit_exit: bool,
157 is_change: bool,
158 ) -> Result<(), S::Error> {
159 let element_stack = self.element_stack.as_mut().unwrap();
160 if !element_stack.is_empty() {
161 for element in element_stack.drain(0..element_stack.len()) {
163 match element {
164 ElementStackEntry::PathElement(element) => self
165 .serializer
166 .serialize_element(&DiffCommandRef::<()>::Enter(element))?,
167 ElementStackEntry::Closure(closure) => (closure)(&mut self.serializer)?,
168 };
169 }
170 self.element_stack_start = 0;
171 }
172 self.has_changes |= is_change;
173 self.implicit_exit_written = implicit_exit;
174 self.serializer.serialize_element(value)
175 }
176
177 pub fn reborrow<'c, 'd: 'c>(&'d mut self) -> DiffContext<'c, S>
178 where
179 'a: 'c,
180 'a: 'd,
181 {
182 let element_stack = self.element_stack.take();
183 let element_stack_ref = unsafe {
198 std::mem::transmute::<
199 &'d mut Option<Vec<ElementStackEntry<'a, S>>>,
200 &'c mut Option<Vec<ElementStackEntry<'c, S>>>,
201 >(&mut self.element_stack)
202 };
203
204 DiffContext {
205 element_stack_start: element_stack.as_ref().unwrap().len(),
206 element_stack,
207 parent_element_stack: Some(element_stack_ref),
208 serializer: &mut *self.serializer,
209 implicit_exit_written: self.implicit_exit_written,
210 field_path_mode: self.field_path_mode,
211 has_changes: false,
212 }
213 }
214}
215
216pub struct Diff<'a, 'b, T> {
232 pub(crate) old: &'a T,
233 pub(crate) new: &'b T,
234 pub(crate) field_path_mode: FieldPathMode,
235
236 pub(crate) has_changes: Cell<bool>,
238}
239
240impl<'a, 'b, T: SerdeDiff + 'a + 'b> Diff<'a, 'b, T> {
241 pub fn serializable(old: &'a T, new: &'b T) -> Self {
244 Config::default().serializable_diff(old, new)
245 }
246
247 pub fn diff<S: Serializer>(serializer: S, old: &'a T, new: &'b T) -> Result<S::Ok, S::Error> {
250 Config::default().diff(serializer, old, new)
251 }
252
253 pub fn has_changes(&self) -> bool {
255 self.has_changes.get()
256 }
257}
258
259impl<'a, 'b, T: SerdeDiff> Serialize for Diff<'a, 'b, T> {
260 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
261 where
262 S: Serializer,
263 {
264 self.has_changes.set(false);
265
266 let num_elements = if !serializer.is_human_readable() {
270 let mut serializer = CountingSerializer { num_elements: 0 };
271 let mut seq = serializer.serialize_seq(None).unwrap();
272 {
273 let mut ctx = DiffContext {
274 element_stack_start: 0,
275 element_stack: Some(Vec::new()),
276 serializer: &mut seq,
277 implicit_exit_written: false,
278 parent_element_stack: None,
279 field_path_mode: self.field_path_mode,
280 has_changes: false,
281 };
282 self.old.diff(&mut ctx, &self.new).unwrap();
283 }
284 seq.end().unwrap();
285 Some(serializer.num_elements)
286 } else {
287 None
288 };
289
290 let mut seq = serializer.serialize_seq(num_elements)?;
292 {
293 let mut ctx = DiffContext {
294 element_stack_start: 0,
295 element_stack: Some(Vec::new()),
296 serializer: &mut seq,
297 implicit_exit_written: false,
298 parent_element_stack: None,
299 field_path_mode: self.field_path_mode,
300 has_changes: false,
301 };
302
303 self.old.diff(&mut ctx, &self.new)?;
306 self.has_changes.set(ctx.has_changes);
307 }
308
309 Ok(seq.end()?)
311 }
312}
313
314pub(crate) struct DeserWrapper<'a, T> {
315 pub(crate) val: &'a mut T,
316}
317
318pub(crate) struct DiffCommandDeserWrapper<'a, T> {
319 pub(crate) val_wrapper: DeserWrapper<'a, T>,
320}
321
322pub(crate) enum DiffCommandField {
328 Enter,
329 Value,
330 Remove,
331 AddKey,
332 EnterKey,
333 RemoveKey,
334 Exit,
335}
336
337pub(crate) struct DiffCommandFieldVisitor;
338
339const VARIANTS: &'static [&'static str] = &[
340 "Enter",
341 "Value",
342 "Remove",
343 "AddKey",
344 "EnterKey",
345 "RemoveKey",
346 "Exit",
347];
348
349impl<'de> de::Visitor<'de> for DiffCommandFieldVisitor {
350 type Value = DiffCommandField;
351 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
352 std::fmt::Formatter::write_str(formatter, "variant identifier")
353 }
354 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
355 where
356 E: de::Error,
357 {
358 match value {
359 0u64 => Ok(DiffCommandField::Enter),
360 1u64 => Ok(DiffCommandField::Value),
361 2u64 => Ok(DiffCommandField::Remove),
362 3u64 => Ok(DiffCommandField::AddKey),
363 4u64 => Ok(DiffCommandField::EnterKey),
364 5u64 => Ok(DiffCommandField::RemoveKey),
365 6u64 => Ok(DiffCommandField::Exit),
366 _ => Err(de::Error::invalid_value(
367 de::Unexpected::Unsigned(value),
368 &"variant index 0 <= i < 7",
369 )),
370 }
371 }
372 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
373 where
374 E: de::Error,
375 {
376 match value {
377 "Enter" => Ok(DiffCommandField::Enter),
378 "Value" => Ok(DiffCommandField::Value),
379 "Remove" => Ok(DiffCommandField::Remove),
380 "AddKey" => Ok(DiffCommandField::AddKey),
381 "EnterKey" => Ok(DiffCommandField::EnterKey),
382 "RemoveKey" => Ok(DiffCommandField::RemoveKey),
383 "Exit" => Ok(DiffCommandField::Exit),
384 _ => Err(de::Error::unknown_variant(value, VARIANTS)),
385 }
386 }
387 fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
388 where
389 E: de::Error,
390 {
391 match value {
392 b"Enter" => Ok(DiffCommandField::Enter),
393 b"Value" => Ok(DiffCommandField::Value),
394 b"Remove" => Ok(DiffCommandField::Remove),
395 b"AddKey" => Ok(DiffCommandField::AddKey),
396 b"EnterKey" => Ok(DiffCommandField::EnterKey),
397 b"RemoveKey" => Ok(DiffCommandField::RemoveKey),
398 b"Exit" => Ok(DiffCommandField::Exit),
399 _ => {
400 let value = &String::from_utf8_lossy(value);
401 Err(de::Error::unknown_variant(value, VARIANTS))
402 }
403 }
404 }
405}
406
407impl<'de> Deserialize<'de> for DiffCommandField {
408 #[inline]
409 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
410 where
411 D: de::Deserializer<'de>,
412 {
413 de::Deserializer::deserialize_identifier(deserializer, DiffCommandFieldVisitor)
414 }
415}
416
417impl<'a, 'de, T> de::DeserializeSeed<'de> for DiffCommandDeserWrapper<'a, T>
418where
419 T: de::Deserialize<'de>,
420{
421 type Value = DiffCommandValue<'de, T>;
422 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
423 where
424 D: de::Deserializer<'de>,
425 {
426 struct Visitor<'de, 'a, T>
427 where
428 T: de::Deserialize<'de>,
429 {
430 seed: DeserWrapper<'a, T>,
431 lifetime: std::marker::PhantomData<&'de ()>,
432 }
433 impl<'de, 'a, T> de::Visitor<'de> for Visitor<'de, 'a, T>
434 where
435 T: de::Deserialize<'de>,
436 {
437 type Value = DiffCommandValue<'de, T>;
438 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
439 std::fmt::Formatter::write_str(formatter, "enum DiffCommandValueTest")
440 }
441 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
442 where
443 A: de::EnumAccess<'de>,
444 {
445 match de::EnumAccess::variant(data)? {
446 (DiffCommandField::Enter, variant) => {
447 let enter =
448 de::VariantAccess::newtype_variant::<DiffPathElementValue>(variant)?;
449 Ok(DiffCommandValue::Enter(enter))
450 }
451 (DiffCommandField::Value, variant)
452 | (DiffCommandField::AddKey, variant)
453 | (DiffCommandField::EnterKey, variant)
454 | (DiffCommandField::RemoveKey, variant) => {
455 de::VariantAccess::newtype_variant_seed::<DeserWrapper<T>>(
456 variant, self.seed,
457 )?;
458 Ok(DiffCommandValue::DeserializedValue)
459 }
460 (DiffCommandField::Remove, variant) => {
461 let num_elements = de::VariantAccess::newtype_variant::<usize>(variant)?;
462 Ok(DiffCommandValue::Remove(num_elements))
463 }
464 (DiffCommandField::Exit, variant) => {
465 de::VariantAccess::unit_variant(variant)?;
466 Ok(DiffCommandValue::Exit)
467 }
468 }
469 }
470 }
471 de::Deserializer::deserialize_enum(
472 deserializer,
473 "DiffCommandValueTest",
474 VARIANTS,
475 Visitor {
476 seed: self.val_wrapper,
477 lifetime: std::marker::PhantomData,
478 },
479 )
480 }
481}
482
483impl<'a, 'de, T: Deserialize<'de>> de::DeserializeSeed<'de> for DeserWrapper<'a, T> {
484 type Value = Self;
485 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
486 where
487 D: de::Deserializer<'de>,
488 {
489 Deserialize::deserialize_in_place(deserializer, self.val)?;
490 Ok(self)
491 }
492}
493
494pub(crate) struct DiffCommandIgnoreValue;
496
497impl<'de> de::DeserializeSeed<'de> for DiffCommandIgnoreValue {
498 type Value = DiffCommandValue<'de, ()>;
499 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
500 where
501 D: de::Deserializer<'de>,
502 {
503 struct Visitor<'de> {
504 lifetime: std::marker::PhantomData<&'de ()>,
505 }
506 impl<'de> de::Visitor<'de> for Visitor<'de> {
507 type Value = DiffCommandValue<'de, ()>;
508 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
509 std::fmt::Formatter::write_str(formatter, "enum DiffCommandValueTest")
510 }
511 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
512 where
513 A: de::EnumAccess<'de>,
514 {
515 match de::EnumAccess::variant(data)? {
516 (DiffCommandField::Enter, variant) => {
517 let enter =
518 de::VariantAccess::newtype_variant::<DiffPathElementValue>(variant)?;
519 Ok(DiffCommandValue::Enter(enter))
520 }
521 (DiffCommandField::Value, variant)
522 | (DiffCommandField::AddKey, variant)
523 | (DiffCommandField::EnterKey, variant)
524 | (DiffCommandField::RemoveKey, variant) => {
525 de::VariantAccess::newtype_variant::<de::IgnoredAny>(variant)?;
526 Ok(DiffCommandValue::Value(()))
527 }
528 (DiffCommandField::Remove, variant) => {
529 let num_elements = de::VariantAccess::newtype_variant::<usize>(variant)?;
530 Ok(DiffCommandValue::Remove(num_elements))
531 }
532 (DiffCommandField::Exit, variant) => {
533 de::VariantAccess::unit_variant(variant)?;
534 Ok(DiffCommandValue::Exit)
535 }
536 }
537 }
538 }
539 de::Deserializer::deserialize_enum(
540 deserializer,
541 "DiffCommandValueTest",
542 VARIANTS,
543 Visitor {
544 lifetime: std::marker::PhantomData,
545 },
546 )
547 }
548}
549
550#[doc(hidden)]
551#[derive(Serialize, Debug)]
552pub enum DiffCommandRef<'a, T: Serialize> {
553 Enter(DiffPathElementValue<'a>),
555 Value(&'a T),
558 Remove(usize),
560 AddKey(&'a T),
562 EnterKey(&'a T),
566 RemoveKey(&'a T),
568 Exit,
570}
571
572#[doc(hidden)]
573#[derive(Deserialize, Debug)]
574pub enum DiffCommandValue<'a, T> {
575 #[serde(borrow)]
577 Enter(DiffPathElementValue<'a>),
578 Value(T),
580 Remove(usize),
582 AddKey(T),
584 EnterKey(T),
586 RemoveKey(T),
588 Exit,
590 Nothing,
592 DeserializedValue,
594}
595
596#[doc(hidden)]
597#[derive(Serialize, Deserialize, Debug)]
598pub enum DiffPathElementValue<'a> {
599 #[serde(borrow)]
601 Field(Cow<'a, str>),
602 FieldIndex(u16),
603 EnumVariant(Cow<'a, str>),
604 FullEnumVariant,
605 CollectionIndex(usize),
606 AddToCollection,
607}
608
609impl<T: SerdeDiff + Serialize + for<'a> Deserialize<'a>> SerdeDiff for Vec<T> {
610 fn diff<'a, S: SerializeSeq>(
611 &self,
612 ctx: &mut DiffContext<'a, S>,
613 other: &Self,
614 ) -> Result<bool, S::Error> {
615 let mut self_iter = self.iter();
616 let mut other_iter = other.iter();
617 let mut idx = 0;
618 let mut need_exit = false;
619 let mut changed = false;
620 loop {
621 let self_item = self_iter.next();
622 let other_item = other_iter.next();
623 match (self_item, other_item) {
624 (None, None) => break,
625 (Some(_), None) => {
626 let mut num_to_remove = 1;
627 while self_iter.next().is_some() {
628 num_to_remove += 1;
629 }
630 ctx.save_command::<()>(&DiffCommandRef::Remove(num_to_remove), true, true)?;
631 changed = true;
632 need_exit = false;
633 }
634 (None, Some(other_item)) => {
635 ctx.save_command::<()>(
636 &DiffCommandRef::Enter(DiffPathElementValue::AddToCollection),
637 false,
638 true,
639 )?;
640 ctx.save_command(&DiffCommandRef::Value(other_item), true, true)?;
641 need_exit = true;
642 changed = true;
643 }
644 (Some(self_item), Some(other_item)) => {
645 ctx.push_collection_index(idx);
646 if <T as SerdeDiff>::diff(self_item, ctx, other_item)? {
647 need_exit = true;
648 changed = true;
649 }
650 ctx.pop_path_element()?;
651 }
652 }
653 idx += 1;
654 }
655 if need_exit {
656 ctx.save_command::<()>(&DiffCommandRef::Exit, true, false)?;
657 }
658 Ok(changed)
659 }
660
661 fn apply<'de, A>(
662 &mut self,
663 seq: &mut A,
664 ctx: &mut ApplyContext,
665 ) -> Result<bool, <A as de::SeqAccess<'de>>::Error>
666 where
667 A: de::SeqAccess<'de>,
668 {
669 let mut changed = false;
670 while let Some(cmd) = ctx.read_next_command::<A, T>(seq)? {
671 use DiffCommandValue::*;
672 use DiffPathElementValue::*;
673 match cmd {
674 Enter(Field(_)) => {
676 ctx.skip_value(seq)?;
677 break;
678 }
679 Enter(CollectionIndex(idx)) => {
680 if let Some(value_ref) = self.get_mut(idx) {
681 changed |= <T as SerdeDiff>::apply(value_ref, seq, ctx)?;
682 } else {
683 ctx.skip_value(seq)?;
684 }
685 }
686 Enter(AddToCollection) => {
687 if let Value(v) = ctx
688 .read_next_command(seq)?
689 .expect("Expected value after AddToCollection")
690 {
691 changed = true;
692 self.push(v);
693 } else {
694 panic!("Expected value after AddToCollection");
695 }
696 }
697 Remove(num_elements) => {
698 let new_length = self.len().saturating_sub(num_elements);
699 self.truncate(new_length);
700 changed = true;
701 break;
702 }
703 _ => break,
704 }
705 }
706 Ok(changed)
707 }
708}