token_value_map/
define_data_macro.rs1#[macro_export]
65macro_rules! define_data_types {
66 (
67 $(#[$meta:meta])*
68 $vis:vis $data_name:ident / $animated_name:ident / $discriminant_name:ident {
69 $(
70 $(#[$variant_meta:meta])*
71 $variant:ident($inner_ty:ty)
72 ),+ $(,)?
73 }
74 ) => {
75 $(#[$meta])*
77 #[derive(Copy, Eq, Hash)]
78 $vis enum $discriminant_name {
79 $(
80 $(#[$variant_meta])*
81 $variant,
82 )+
83 }
84
85 $(#[$meta])*
87 #[derive(Eq, Hash)]
88 $vis enum $data_name {
89 $(
90 $(#[$variant_meta])*
91 $variant($inner_ty),
92 )+
93 }
94
95 $(#[$meta])*
97 #[derive(Eq, Hash)]
98 $vis enum $animated_name {
99 $(
100 $(#[$variant_meta])*
101 $variant($crate::TimeDataMap<$inner_ty>),
102 )+
103 }
104
105 impl $crate::DataSystem for $data_name {
107 type Animated = $animated_name;
108 type DataType = $discriminant_name;
109
110 fn discriminant(&self) -> Self::DataType {
111 match self {
112 $(
113 $data_name::$variant(_) => $discriminant_name::$variant,
114 )+
115 }
116 }
117
118 fn variant_name(&self) -> &'static str {
119 match self {
120 $(
121 $data_name::$variant(_) => stringify!($variant),
122 )+
123 }
124 }
125 }
126
127 impl $crate::AnimatedDataSystem for $animated_name {
129 type Data = $data_name;
130
131 fn keyframe_count(&self) -> usize {
132 match self {
133 $(
134 $animated_name::$variant(map) => map.len(),
135 )+
136 }
137 }
138
139 fn times(&self) -> ::smallvec::SmallVec<[$crate::Time; 10]> {
140 match self {
141 $(
142 $animated_name::$variant(map) => {
143 map.iter().map(|(t, _)| *t).collect()
144 }
145 )+
146 }
147 }
148
149 fn interpolate(&self, time: $crate::Time) -> Self::Data {
150 match self {
151 $(
152 $animated_name::$variant(map) => {
153 $data_name::$variant(map.interpolate(time))
154 }
155 )+
156 }
157 }
158
159 fn sample_at(&self, time: $crate::Time) -> ::core::option::Option<Self::Data> {
160 match self {
161 $(
162 $animated_name::$variant(map) => {
163 map.get(&time).cloned().map($data_name::$variant)
164 }
165 )+
166 }
167 }
168
169 fn try_insert(
170 &mut self,
171 time: $crate::Time,
172 value: Self::Data,
173 ) -> $crate::Result<()> {
174 match (self, value) {
175 $(
176 ($animated_name::$variant(map), $data_name::$variant(v)) => {
177 map.insert(time, v);
178 Ok(())
179 }
180 )+
181 #[allow(unreachable_patterns)]
182 (this, val) => Err($crate::Error::GenericTypeMismatch {
183 expected: this.variant_name(),
184 got: val.variant_name(),
185 }),
186 }
187 }
188
189 fn remove_at(&mut self, time: &$crate::Time) -> ::core::option::Option<Self::Data> {
190 match self {
191 $(
192 $animated_name::$variant(map) => {
193 map.remove(time).ok()?.map($data_name::$variant)
194 }
195 )+
196 }
197 }
198
199 fn discriminant(&self) -> <Self::Data as $crate::DataSystem>::DataType {
200 match self {
201 $(
202 $animated_name::$variant(_) => $discriminant_name::$variant,
203 )+
204 }
205 }
206
207 fn from_single(time: $crate::Time, value: Self::Data) -> Self {
208 match value {
209 $(
210 $data_name::$variant(v) => {
211 $animated_name::$variant($crate::KeyDataMap::from_single(time, v))
212 }
213 )+
214 }
215 }
216
217 fn variant_name(&self) -> &'static str {
218 match self {
219 $(
220 $animated_name::$variant(_) => stringify!($variant),
221 )+
222 }
223 }
224 }
225
226 $(
228 impl ::core::convert::From<$inner_ty> for $data_name {
229 fn from(value: $inner_ty) -> Self {
230 $data_name::$variant(value)
231 }
232 }
233 )+
234 };
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240 use crate::{AnimatedDataSystem, DataSystem, GenericValue, Time};
241 use std::ops::{Add, Div, Mul, Sub};
242
243 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
245 struct TestFloat(i64); impl TestFloat {
248 fn new(v: f32) -> Self {
249 Self((v * 1000.0) as i64)
250 }
251
252 fn value(&self) -> f32 {
253 self.0 as f32 / 1000.0
254 }
255 }
256
257 impl Add for TestFloat {
258 type Output = Self;
259 fn add(self, other: Self) -> Self {
260 Self(self.0 + other.0)
261 }
262 }
263
264 impl Sub for TestFloat {
265 type Output = Self;
266 fn sub(self, other: Self) -> Self {
267 Self(self.0 - other.0)
268 }
269 }
270
271 impl Mul<f32> for TestFloat {
272 type Output = Self;
273 fn mul(self, scalar: f32) -> Self {
274 Self((self.0 as f32 * scalar) as i64)
275 }
276 }
277
278 impl Mul<f64> for TestFloat {
279 type Output = Self;
280 fn mul(self, scalar: f64) -> Self {
281 Self((self.0 as f64 * scalar) as i64)
282 }
283 }
284
285 impl Div<f32> for TestFloat {
286 type Output = Self;
287 fn div(self, scalar: f32) -> Self {
288 Self((self.0 as f32 / scalar) as i64)
289 }
290 }
291
292 impl Div<f64> for TestFloat {
293 type Output = Self;
294 fn div(self, scalar: f64) -> Self {
295 Self((self.0 as f64 / scalar) as i64)
296 }
297 }
298
299 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
301 struct TestInt(i64);
302
303 impl Add for TestInt {
304 type Output = Self;
305 fn add(self, other: Self) -> Self {
306 Self(self.0 + other.0)
307 }
308 }
309
310 impl Sub for TestInt {
311 type Output = Self;
312 fn sub(self, other: Self) -> Self {
313 Self(self.0 - other.0)
314 }
315 }
316
317 impl Mul<f32> for TestInt {
318 type Output = Self;
319 fn mul(self, scalar: f32) -> Self {
320 Self((self.0 as f32 * scalar) as i64)
321 }
322 }
323
324 impl Mul<f64> for TestInt {
325 type Output = Self;
326 fn mul(self, scalar: f64) -> Self {
327 Self((self.0 as f64 * scalar) as i64)
328 }
329 }
330
331 impl Div<f32> for TestInt {
332 type Output = Self;
333 fn div(self, scalar: f32) -> Self {
334 Self((self.0 as f32 / scalar) as i64)
335 }
336 }
337
338 impl Div<f64> for TestInt {
339 type Output = Self;
340 fn div(self, scalar: f64) -> Self {
341 Self((self.0 as f64 / scalar) as i64)
342 }
343 }
344
345 define_data_types! {
347 #[derive(Clone, Debug, PartialEq)]
349 pub TestData / TestAnimatedData / TestDataType {
350 Float(TestFloat),
352 Int(TestInt),
354 }
355 }
356
357 #[test]
358 fn test_discriminant() {
359 let data = TestData::Float(TestFloat::new(42.0));
360 assert_eq!(data.discriminant(), TestDataType::Float);
361 assert_eq!(data.variant_name(), "Float");
362
363 let data = TestData::Int(TestInt(42));
364 assert_eq!(data.discriminant(), TestDataType::Int);
365 assert_eq!(data.variant_name(), "Int");
366 }
367
368 #[test]
369 fn test_from_conversion() {
370 let data: TestData = TestFloat::new(42.0).into();
371 assert!(matches!(data, TestData::Float(_)));
372
373 let data: TestData = TestInt(42).into();
374 assert!(matches!(data, TestData::Int(TestInt(42))));
375 }
376
377 #[test]
378 fn test_generic_value_uniform() {
379 let value = GenericValue::<TestData>::uniform(TestData::Float(TestFloat::new(42.0)));
380 assert!(!value.is_animated());
381
382 if let TestData::Float(f) = value.interpolate(Time::default()) {
383 assert!((f.value() - 42.0).abs() < 0.01);
384 } else {
385 panic!("Expected Float variant");
386 }
387 }
388
389 #[test]
390 fn test_generic_value_animated() {
391 let value = GenericValue::<TestData>::animated(vec![
392 (Time::default(), TestData::Float(TestFloat::new(0.0))),
393 (Time::from(10.0), TestData::Float(TestFloat::new(100.0))),
394 ])
395 .unwrap();
396
397 assert!(value.is_animated());
398 assert_eq!(value.sample_count(), 2);
399
400 let mid = value.interpolate(Time::from(5.0));
402 if let TestData::Float(v) = mid {
403 assert!((v.value() - 50.0).abs() < 1.0); } else {
405 panic!("Expected Float variant");
406 }
407 }
408
409 #[test]
410 fn test_animated_data_system() {
411 let animated =
412 TestAnimatedData::from_single(Time::default(), TestData::Float(TestFloat::new(42.0)));
413 assert_eq!(animated.keyframe_count(), 1);
414 assert_eq!(animated.variant_name(), "Float");
415
416 let sample = animated.sample_at(Time::default());
417 assert!(matches!(sample, Some(TestData::Float(_))));
418 }
419}