Skip to main content

cumulo_dipa/
tuple.rs

1use crate::delta_n::{Delta2, DeltaOwned2};
2use crate::{CreatedDelta, Diffable, Patchable};
3
4// TODO: 3-tuple and 4-tuple implementations. Similar to 2-tuple just with more fields.
5//  We already generate code like this in dipa-derive so we can probably look to re-use that
6//  in dipa's build script in order to generate the tuple-2 .. tuple-n implementations that we
7//  need.
8
9impl<'s, 'e, A: Diffable<'s, 'e, A>, B: Diffable<'s, 'e, B>> Diffable<'s, 'e, (A, B)> for (A, B) {
10    type Delta = Delta2<<A as Diffable<'s, 'e, A>>::Delta, <B as Diffable<'s, 'e, B>>::Delta>;
11    type DeltaOwned =
12        DeltaOwned2<<A as Diffable<'s, 'e, A>>::DeltaOwned, <B as Diffable<'s, 'e, B>>::DeltaOwned>;
13
14    fn create_delta_towards(&'s self, end_state: &'e (A, B)) -> CreatedDelta<Self::Delta> {
15        let diff0 = self.0.create_delta_towards(&end_state.0);
16        let diff1 = self.1.create_delta_towards(&end_state.1);
17
18        let did_change = diff0.did_change || diff1.did_change;
19
20        let delta = match (diff0.did_change, diff1.did_change) {
21            (false, false) => Delta2::NoChange,
22            (true, false) => Delta2::Change_0(diff0.delta),
23            (false, true) => Delta2::Change_1(diff1.delta),
24            (true, true) => Delta2::Change_0_1(diff0.delta, diff1.delta),
25        };
26
27        CreatedDelta { delta, did_change }
28    }
29}
30
31impl<
32        's,
33        'e,
34        A: Diffable<'s, 'e, A> + Patchable<<A as Diffable<'s, 'e, A>>::DeltaOwned>,
35        B: Diffable<'s, 'e, B> + Patchable<<B as Diffable<'s, 'e, B>>::DeltaOwned>,
36    >
37    Patchable<
38        DeltaOwned2<<A as Diffable<'s, 'e, A>>::DeltaOwned, <B as Diffable<'s, 'e, B>>::DeltaOwned>,
39    > for (A, B)
40{
41    fn apply_patch(
42        &mut self,
43        patch: DeltaOwned2<
44            <A as Diffable<'s, 'e, A>>::DeltaOwned,
45            <B as Diffable<'s, 'e, B>>::DeltaOwned,
46        >,
47    ) {
48        match patch {
49            DeltaOwned2::NoChange => {}
50            DeltaOwned2::Change_0(patch0) => {
51                self.0.apply_patch(patch0);
52            }
53            DeltaOwned2::Change_1(patch1) => {
54                self.1.apply_patch(patch1);
55            }
56            DeltaOwned2::Change_0_1(patch0, patch1) => {
57                self.0.apply_patch(patch0);
58                self.1.apply_patch(patch1);
59            }
60        }
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use crate::DipaImplTester;
68
69    /// Verify that we can diff and patch a 2-tuple
70    #[test]
71    fn two_tuple() {
72        DipaImplTester {
73            label: Some("2 tuple no change"),
74            start: &mut (1u16, 2u32),
75            end: &(1u16, 2u32),
76            expected_delta: Delta2::NoChange,
77            expected_serialized_patch_size: 1,
78            expected_did_change: false,
79        }
80        .test();
81
82        DipaImplTester {
83            label: Some("2 tuple Change_1"),
84            start: &mut (1u16, 2u32),
85            end: &(5u16, 2u32),
86            expected_delta: Delta2::Change_0(Some(5)),
87            expected_serialized_patch_size: 3,
88            expected_did_change: true,
89        }
90        .test();
91
92        DipaImplTester {
93            label: Some("2 tuple Change_1"),
94            start: &mut (1u16, 2u32),
95            end: &(1u16, 6u32),
96            expected_delta: Delta2::Change_1(Some(6)),
97            expected_serialized_patch_size: 3,
98            expected_did_change: true,
99        }
100        .test();
101
102        DipaImplTester {
103            label: Some("2 tuple Change_0_1"),
104            start: &mut (1u16, 2u32),
105            end: &(5u16, 6u32),
106            expected_delta: Delta2::Change_0_1(Some(5), Some(6)),
107            expected_serialized_patch_size: 5,
108            expected_did_change: true,
109        }
110        .test();
111    }
112}