firewheel_core/diff/
collections.rs

1//! A set of diff and patch implementations for common collections.
2
3use super::{Diff, EventQueue, Patch, PatchError, PathBuilder};
4use crate::event::ParamData;
5
6macro_rules! sequence_diff {
7    ($gen:ident, $ty:ty) => {
8        impl<$gen: Diff> Diff for $ty {
9            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
10                for (i, item) in self.iter().enumerate() {
11                    item.diff(&baseline[i], path.with(i as u32), event_queue);
12                }
13            }
14        }
15
16        impl<$gen: Patch> Patch for $ty {
17            fn patch(&mut self, data: &ParamData, path: &[u32]) -> Result<(), PatchError> {
18                let first = path.first().ok_or(PatchError::InvalidPath)?;
19                let target = self
20                    .get_mut(*first as usize)
21                    .ok_or(PatchError::InvalidPath)?;
22
23                target.patch(data, &path[1..])
24            }
25        }
26    };
27}
28
29sequence_diff!(T, Vec<T>);
30sequence_diff!(T, Box<[T]>);
31sequence_diff!(T, [T]);
32
33impl<T: Diff, const LEN: usize> Diff for [T; LEN] {
34    fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
35        for (i, item) in self.iter().enumerate() {
36            item.diff(&baseline[i], path.with(i as u32), event_queue);
37        }
38    }
39}
40
41impl<T: Patch, const LEN: usize> Patch for [T; LEN] {
42    fn patch(&mut self, data: &ParamData, path: &[u32]) -> Result<(), PatchError> {
43        let first = path.first().ok_or(PatchError::InvalidPath)?;
44        let target = self
45            .get_mut(*first as usize)
46            .ok_or(PatchError::InvalidPath)?;
47
48        target.patch(data, &path[1..])
49    }
50}
51
52macro_rules! tuple_diff {
53    ($($gen:ident, $base:ident, $index:literal),*) => {
54        #[allow(non_snake_case, unused_variables)]
55        impl<$($gen: Diff),*> Diff for ($($gen,)*) {
56            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
57                let ($($gen,)*) = self;
58                let ($($base,)*) = baseline;
59
60                $(
61                    $gen.diff($base, path.with($index), event_queue);
62                )*
63            }
64        }
65
66        #[allow(non_snake_case, unused_variables)]
67        impl<$($gen: Patch),*> Patch for ($($gen,)*) {
68            fn patch(&mut self, data: &ParamData, path: &[u32]) -> Result<(), PatchError> {
69                let ($($gen,)*) = self;
70
71                match path {
72                    $(
73                        [$index, tail @ ..] => $gen.patch(data, tail),
74                    )*
75                    _ => Err(PatchError::InvalidPath),
76                }
77            }
78        }
79    };
80}
81
82tuple_diff!();
83tuple_diff!(A0, A1, 0);
84tuple_diff!(A0, A1, 0, B0, B1, 1);
85tuple_diff!(A0, A1, 0, B0, B1, 1, C0, C1, 2);
86tuple_diff!(A0, A1, 0, B0, B1, 1, C0, C1, 2, D0, D1, 3);
87tuple_diff!(A0, A1, 0, B0, B1, 1, C0, C1, 2, D0, D1, 3, E0, E1, 4);
88tuple_diff!(A0, A1, 0, B0, B1, 1, C0, C1, 2, D0, D1, 3, E0, E1, 4, F0, F1, 5);
89tuple_diff!(A0, A1, 0, B0, B1, 1, C0, C1, 2, D0, D1, 3, E0, E1, 4, F0, F1, 5, G0, G1, 6);
90tuple_diff!(A0, A1, 0, B0, B1, 1, C0, C1, 2, D0, D1, 3, E0, E1, 4, F0, F1, 5, G0, G1, 6, H0, H1, 7);