firewheel_core/diff/
leaf.rs

1//! A set of diff and patch implementations for common leaf types.
2
3use super::{Diff, EventQueue, Patch, PatchError, PathBuilder};
4use crate::{
5    clock::{DurationSamples, DurationSeconds, InstantSamples, InstantSeconds},
6    collector::ArcGc,
7    diff::{Notify, RealtimeClone},
8    dsp::volume::Volume,
9    event::{NodeEventType, ParamData},
10    vector::{Vec2, Vec3},
11};
12
13#[cfg(feature = "musical_transport")]
14use crate::clock::{DurationMusical, InstantMusical};
15
16macro_rules! primitive_diff {
17    ($ty:ty, $variant:ident) => {
18        impl Diff for $ty {
19            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
20                if self != baseline {
21                    event_queue.push_param(*self, path);
22                }
23            }
24        }
25
26        impl Patch for $ty {
27            type Patch = Self;
28
29            fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
30                match data {
31                    ParamData::$variant(value) => Ok((*value).into()),
32                    _ => Err(PatchError::InvalidData),
33                }
34            }
35
36            fn apply(&mut self, value: Self::Patch) {
37                *self = value;
38            }
39        }
40
41        impl Diff for Option<$ty> {
42            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
43                if self != baseline {
44                    event_queue.push_param(*self, path);
45                }
46            }
47        }
48
49        impl Patch for Option<$ty> {
50            type Patch = Self;
51
52            fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
53                match data {
54                    ParamData::$variant(value) => Ok(Some((*value).into())),
55                    ParamData::None => Ok(None),
56                    _ => Err(PatchError::InvalidData),
57                }
58            }
59
60            fn apply(&mut self, value: Self::Patch) {
61                *self = value;
62            }
63        }
64
65        impl Diff for Notify<$ty> {
66            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
67                if self != baseline {
68                    event_queue.push_param(*self, path);
69                }
70            }
71        }
72
73        impl Patch for Notify<$ty> {
74            type Patch = Self;
75
76            fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
77                match data {
78                    ParamData::$variant(value) => Ok(Notify::new((*value).into())),
79                    _ => Err(PatchError::InvalidData),
80                }
81            }
82
83            fn apply(&mut self, value: Self::Patch) {
84                *self = value;
85            }
86        }
87    };
88
89    ($ty:ty, $cast:ty, $variant:ident) => {
90        impl Diff for $ty {
91            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
92                if self != baseline {
93                    event_queue.push_param(*self as $cast, path);
94                }
95            }
96        }
97
98        impl Patch for $ty {
99            type Patch = Self;
100
101            fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
102                match data {
103                    ParamData::$variant(value) => Ok(value.clone() as $ty),
104                    _ => Err(PatchError::InvalidData),
105                }
106            }
107
108            fn apply(&mut self, value: Self::Patch) {
109                *self = value;
110            }
111        }
112
113        impl Diff for Option<$ty> {
114            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
115                if self != baseline {
116                    event_queue.push_param(self.map(|v| v as $cast), path);
117                }
118            }
119        }
120
121        impl Patch for Option<$ty> {
122            type Patch = Self;
123
124            fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
125                match data {
126                    ParamData::$variant(value) => Ok(Some(value.clone() as $ty)),
127                    ParamData::None => Ok(None),
128                    _ => Err(PatchError::InvalidData),
129                }
130            }
131
132            fn apply(&mut self, value: Self::Patch) {
133                *self = value;
134            }
135        }
136
137        impl Diff for Notify<$ty> {
138            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
139                if self != baseline {
140                    event_queue.push_param(**self as $cast, path);
141                }
142            }
143        }
144
145        impl Patch for Notify<$ty> {
146            type Patch = Self;
147
148            fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
149                match data {
150                    ParamData::$variant(value) => Ok(Notify::new(value.clone() as $ty)),
151                    _ => Err(PatchError::InvalidData),
152                }
153            }
154
155            fn apply(&mut self, value: Self::Patch) {
156                *self = value;
157            }
158        }
159    };
160}
161
162primitive_diff!(bool, Bool);
163primitive_diff!(u8, u32, U32);
164primitive_diff!(u16, u32, U32);
165primitive_diff!(u32, U32);
166primitive_diff!(u64, U64);
167primitive_diff!(i8, i32, I32);
168primitive_diff!(i16, i32, I32);
169primitive_diff!(i32, I32);
170primitive_diff!(i64, I64);
171primitive_diff!(f32, F32);
172primitive_diff!(f64, F64);
173primitive_diff!(Volume, Volume);
174primitive_diff!(InstantSamples, InstantSamples);
175primitive_diff!(DurationSamples, DurationSamples);
176primitive_diff!(InstantSeconds, InstantSeconds);
177primitive_diff!(DurationSeconds, DurationSeconds);
178#[cfg(feature = "musical_transport")]
179primitive_diff!(InstantMusical, InstantMusical);
180#[cfg(feature = "musical_transport")]
181primitive_diff!(DurationMusical, DurationMusical);
182primitive_diff!(Vec2, Vector2D);
183primitive_diff!(Vec3, Vector3D);
184
185#[cfg(feature = "glam-29")]
186primitive_diff!(glam::Vec2, Vector2D);
187#[cfg(feature = "glam-29")]
188primitive_diff!(glam::Vec3, Vector3D);
189
190impl Diff for Notify<()> {
191    fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
192        if self != baseline {
193            event_queue.push_param(ParamData::None, path);
194        }
195    }
196}
197
198impl Patch for Notify<()> {
199    type Patch = Self;
200
201    fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
202        match data {
203            ParamData::None => Ok(Notify::new((()).into())),
204            _ => Err(PatchError::InvalidData),
205        }
206    }
207
208    fn apply(&mut self, value: Self::Patch) {
209        *self = value;
210    }
211}
212
213impl<A: ?Sized + Send + Sync + 'static> Diff for ArcGc<A> {
214    fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
215        if !ArcGc::ptr_eq(self, baseline) {
216            event_queue.push(NodeEventType::Param {
217                data: ParamData::any(self.clone()),
218                path: path.build(),
219            });
220        }
221    }
222}
223
224impl<A: ?Sized + Send + Sync + 'static> Patch for ArcGc<A> {
225    type Patch = Self;
226
227    fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
228        if let ParamData::Any(any) = data {
229            if let Some(data) = any.downcast_ref::<Self>() {
230                return Ok(data.clone());
231            }
232        }
233
234        Err(PatchError::InvalidData)
235    }
236
237    fn apply(&mut self, patch: Self::Patch) {
238        *self = patch;
239    }
240}
241
242impl<T: Send + Sync + RealtimeClone + PartialEq + 'static> Diff for Option<T> {
243    fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
244        if self != baseline {
245            event_queue.push_param(ParamData::opt_any(self.clone()), path);
246        }
247    }
248}
249
250impl<T: Send + Sync + RealtimeClone + PartialEq + 'static> Patch for Option<T> {
251    type Patch = Self;
252
253    fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
254        Ok(data.downcast_ref::<T>().cloned())
255    }
256
257    fn apply(&mut self, patch: Self::Patch) {
258        *self = patch;
259    }
260}