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    collector::ArcGc,
6    event::{NodeEventType, ParamData, Vec2, Vec3},
7};
8
9macro_rules! primitive_diff {
10    ($ty:ty, $variant:ident) => {
11        impl Diff for $ty {
12            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
13                if self != baseline {
14                    event_queue.push_param(*self, path);
15                }
16            }
17        }
18
19        impl Patch for $ty {
20            type Patch = Self;
21
22            fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
23                match data {
24                    ParamData::$variant(value) => Ok(*value),
25                    _ => Err(PatchError::InvalidData),
26                }
27            }
28
29            fn apply(&mut self, value: Self::Patch) {
30                *self = value;
31            }
32        }
33    };
34
35    ($ty:ty, $cast:ty, $variant:ident) => {
36        impl Diff for $ty {
37            fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
38                if self != baseline {
39                    event_queue.push_param(*self as $cast, path);
40                }
41            }
42        }
43
44        impl Patch for $ty {
45            type Patch = Self;
46
47            fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
48                match data {
49                    ParamData::$variant(value) => Ok(*value as $ty),
50                    _ => Err(PatchError::InvalidData),
51                }
52            }
53
54            fn apply(&mut self, value: Self::Patch) {
55                *self = value;
56            }
57        }
58    };
59}
60
61primitive_diff!(bool, Bool);
62
63primitive_diff!(u8, u32, U32);
64primitive_diff!(u16, u32, U32);
65primitive_diff!(u32, U32);
66primitive_diff!(u64, U64);
67
68primitive_diff!(i8, i32, I32);
69primitive_diff!(i16, i32, I32);
70primitive_diff!(i32, I32);
71primitive_diff!(i64, u64, U64);
72
73primitive_diff!(f32, F32);
74primitive_diff!(f64, F64);
75
76// This may be questionable.
77impl<A: ?Sized + Send + Sync + 'static> Diff for ArcGc<A> {
78    fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
79        if ArcGc::ptr_eq(self, baseline) {
80            event_queue.push(NodeEventType::Param {
81                data: ParamData::Any(Box::new(Box::new(self.clone()))),
82                path: path.build(),
83            });
84        }
85    }
86}
87
88impl<A: ?Sized + Send + Sync + 'static> Patch for ArcGc<A> {
89    type Patch = Self;
90
91    fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
92        if let ParamData::Any(any) = data {
93            if let Some(data) = any.downcast_ref::<Self>() {
94                return Ok(data.clone());
95            }
96        }
97
98        Err(PatchError::InvalidData)
99    }
100
101    fn apply(&mut self, patch: Self::Patch) {
102        *self = patch;
103    }
104}
105
106impl Diff for Vec2 {
107    fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
108        if self != baseline {
109            event_queue.push_param(*self, path);
110        }
111    }
112}
113
114impl Patch for Vec2 {
115    type Patch = Self;
116
117    fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
118        data.try_into()
119    }
120
121    fn apply(&mut self, patch: Self::Patch) {
122        *self = patch;
123    }
124}
125
126impl Diff for Vec3 {
127    fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
128        if self != baseline {
129            event_queue.push_param(*self, path);
130        }
131    }
132}
133
134impl Patch for Vec3 {
135    type Patch = Self;
136
137    fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
138        data.try_into()
139    }
140
141    fn apply(&mut self, patch: Self::Patch) {
142        *self = patch;
143    }
144}
145
146impl<T: Send + Sync + Clone + PartialEq + 'static> Diff for Option<T> {
147    fn diff<E: EventQueue>(&self, baseline: &Self, path: PathBuilder, event_queue: &mut E) {
148        if self != baseline {
149            event_queue.push_param(ParamData::any(self.clone()), path);
150        }
151    }
152}
153
154impl<T: Send + Sync + Clone + PartialEq + 'static> Patch for Option<T> {
155    type Patch = Self;
156
157    fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError> {
158        data.downcast_ref().cloned().ok_or(PatchError::InvalidData)
159    }
160
161    fn apply(&mut self, patch: Self::Patch) {
162        *self = patch;
163    }
164}