serde_diff/config.rs
1use crate::{Apply, Diff, FieldPathMode, SerdeDiff};
2use serde::{de, Serialize, Serializer};
3use std::cell::Cell;
4
5/// Configures creation of `Apply` and `Diff`
6///
7/// # Examples
8///
9/// ```rust
10/// use serde_diff::{SerdeDiff, Config, FieldPathMode};
11/// use serde::{Serialize, Deserialize};
12/// #[derive(SerdeDiff, Serialize, Deserialize, PartialEq)]
13/// struct Test {
14/// a: i32,
15/// }
16/// let diff = Config::new()
17/// .with_field_path_mode(FieldPathMode::Index)
18/// .serializable_diff(&Test { a: 3 }, &Test { a: 5 });
19/// ```
20pub struct Config {
21 field_path_mode: FieldPathMode,
22}
23
24impl Default for Config {
25 fn default() -> Self {
26 Self {
27 field_path_mode: FieldPathMode::Name,
28 }
29 }
30}
31
32impl Config {
33 /// Creates a `Config` with default values
34 pub fn new() -> Self {
35 <Self as Default>::default()
36 }
37
38 /// Sets the `FieldPathMode` to use when serializing a Diff
39 pub fn with_field_path_mode(mut self, mode: FieldPathMode) -> Self {
40 self.field_path_mode = mode;
41 self
42 }
43
44 /// Create a serializable Diff, which when serialized will write the differences between the old
45 /// and new value into the serializer in the form of a sequence of diff commands
46 pub fn serializable_diff<'a, 'b, T: SerdeDiff + 'a + 'b>(
47 self,
48 old: &'a T,
49 new: &'b T,
50 ) -> Diff<'a, 'b, T> {
51 Diff {
52 old,
53 new,
54 field_path_mode: self.field_path_mode,
55 has_changes: Cell::new(false),
56 }
57 }
58
59 /// Writes the differences between the old and new value into the given serializer in the form
60 /// of a sequence of diff commands
61 pub fn diff<'a, 'b, S: Serializer, T: SerdeDiff + 'a + 'b>(
62 self,
63 serializer: S,
64 old: &'a T,
65 new: &'b T,
66 ) -> Result<S::Ok, S::Error> {
67 self.serializable_diff(old, new).serialize(serializer)
68 }
69
70 /// Create a deserializable Apply, where the given target will be changed when the resulting
71 /// Apply struct is deserialized
72 pub fn deserializable_apply<'a, T: SerdeDiff>(self, target: &'a mut T) -> Apply<'a, T> {
73 Apply { target }
74 }
75
76 /// Applies a sequence of diff commands to the target, as read by the deserializer
77 pub fn apply<'de, D, T: SerdeDiff>(
78 self,
79 deserializer: D,
80 target: &mut T,
81 ) -> Result<(), <D as de::Deserializer<'de>>::Error>
82 where
83 D: de::Deserializer<'de>,
84 {
85 deserializer.deserialize_seq(self.deserializable_apply(target))
86 }
87}