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).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 let mut map = ::std::collections::BTreeMap::new();
212 map.insert(time, v);
213 $animated_name::$variant($crate::TimeDataMap::from(map))
214 }
215 )+
216 }
217 }
218
219 fn variant_name(&self) -> &'static str {
220 match self {
221 $(
222 $animated_name::$variant(_) => stringify!($variant),
223 )+
224 }
225 }
226 }
227
228 $(
230 impl ::core::convert::From<$inner_ty> for $data_name {
231 fn from(value: $inner_ty) -> Self {
232 $data_name::$variant(value)
233 }
234 }
235 )+
236 };
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242 use crate::{AnimatedDataSystem, DataSystem, GenericValue, Time};
243 use std::ops::{Add, Div, Mul, Sub};
244
245 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
247 struct TestFloat(i64); impl TestFloat {
250 fn new(v: f32) -> Self {
251 Self((v * 1000.0) as i64)
252 }
253
254 fn value(&self) -> f32 {
255 self.0 as f32 / 1000.0
256 }
257 }
258
259 impl Add for TestFloat {
260 type Output = Self;
261 fn add(self, other: Self) -> Self {
262 Self(self.0 + other.0)
263 }
264 }
265
266 impl Sub for TestFloat {
267 type Output = Self;
268 fn sub(self, other: Self) -> Self {
269 Self(self.0 - other.0)
270 }
271 }
272
273 impl Mul<f32> for TestFloat {
274 type Output = Self;
275 fn mul(self, scalar: f32) -> Self {
276 Self((self.0 as f32 * scalar) as i64)
277 }
278 }
279
280 impl Mul<f64> for TestFloat {
281 type Output = Self;
282 fn mul(self, scalar: f64) -> Self {
283 Self((self.0 as f64 * scalar) as i64)
284 }
285 }
286
287 impl Div<f32> for TestFloat {
288 type Output = Self;
289 fn div(self, scalar: f32) -> Self {
290 Self((self.0 as f32 / scalar) as i64)
291 }
292 }
293
294 impl Div<f64> for TestFloat {
295 type Output = Self;
296 fn div(self, scalar: f64) -> Self {
297 Self((self.0 as f64 / scalar) as i64)
298 }
299 }
300
301 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
303 struct TestInt(i64);
304
305 impl Add for TestInt {
306 type Output = Self;
307 fn add(self, other: Self) -> Self {
308 Self(self.0 + other.0)
309 }
310 }
311
312 impl Sub for TestInt {
313 type Output = Self;
314 fn sub(self, other: Self) -> Self {
315 Self(self.0 - other.0)
316 }
317 }
318
319 impl Mul<f32> for TestInt {
320 type Output = Self;
321 fn mul(self, scalar: f32) -> Self {
322 Self((self.0 as f32 * scalar) as i64)
323 }
324 }
325
326 impl Mul<f64> for TestInt {
327 type Output = Self;
328 fn mul(self, scalar: f64) -> Self {
329 Self((self.0 as f64 * scalar) as i64)
330 }
331 }
332
333 impl Div<f32> for TestInt {
334 type Output = Self;
335 fn div(self, scalar: f32) -> Self {
336 Self((self.0 as f32 / scalar) as i64)
337 }
338 }
339
340 impl Div<f64> for TestInt {
341 type Output = Self;
342 fn div(self, scalar: f64) -> Self {
343 Self((self.0 as f64 / scalar) as i64)
344 }
345 }
346
347 define_data_types! {
349 #[derive(Clone, Debug, PartialEq)]
351 pub TestData / TestAnimatedData / TestDataType {
352 Float(TestFloat),
354 Int(TestInt),
356 }
357 }
358
359 #[test]
360 fn test_discriminant() {
361 let data = TestData::Float(TestFloat::new(42.0));
362 assert_eq!(data.discriminant(), TestDataType::Float);
363 assert_eq!(data.variant_name(), "Float");
364
365 let data = TestData::Int(TestInt(42));
366 assert_eq!(data.discriminant(), TestDataType::Int);
367 assert_eq!(data.variant_name(), "Int");
368 }
369
370 #[test]
371 fn test_from_conversion() {
372 let data: TestData = TestFloat::new(42.0).into();
373 assert!(matches!(data, TestData::Float(_)));
374
375 let data: TestData = TestInt(42).into();
376 assert!(matches!(data, TestData::Int(TestInt(42))));
377 }
378
379 #[test]
380 fn test_generic_value_uniform() {
381 let value = GenericValue::<TestData>::uniform(TestData::Float(TestFloat::new(42.0)));
382 assert!(!value.is_animated());
383
384 if let TestData::Float(f) = value.interpolate(Time::default()) {
385 assert!((f.value() - 42.0).abs() < 0.01);
386 } else {
387 panic!("Expected Float variant");
388 }
389 }
390
391 #[test]
392 fn test_generic_value_animated() {
393 let value = GenericValue::<TestData>::animated(vec![
394 (Time::default(), TestData::Float(TestFloat::new(0.0))),
395 (Time::from(10.0), TestData::Float(TestFloat::new(100.0))),
396 ])
397 .unwrap();
398
399 assert!(value.is_animated());
400 assert_eq!(value.sample_count(), 2);
401
402 let mid = value.interpolate(Time::from(5.0));
404 if let TestData::Float(v) = mid {
405 assert!((v.value() - 50.0).abs() < 1.0); } else {
407 panic!("Expected Float variant");
408 }
409 }
410
411 #[test]
412 fn test_animated_data_system() {
413 let animated =
414 TestAnimatedData::from_single(Time::default(), TestData::Float(TestFloat::new(42.0)));
415 assert_eq!(animated.keyframe_count(), 1);
416 assert_eq!(animated.variant_name(), "Float");
417
418 let sample = animated.sample_at(Time::default());
419 assert!(matches!(sample, Some(TestData::Float(_))));
420 }
421}