token_value_map/
generic_value.rs1use crate::{Result, Shutter, Time, traits::*};
4use smallvec::SmallVec;
5use std::hash::{Hash, Hasher};
6
7#[cfg(feature = "rkyv")]
8use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12#[derive(Clone, Debug, PartialEq, Hash)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[cfg_attr(
22 feature = "serde",
23 serde(bound(
24 serialize = "D: Serialize, D::Animated: Serialize",
25 deserialize = "D: Deserialize<'de>, D::Animated: Deserialize<'de>"
26 ))
27)]
28#[cfg_attr(feature = "rkyv", derive(Archive, RkyvSerialize, RkyvDeserialize))]
29pub enum GenericValue<D: DataSystem> {
30 Uniform(D),
32 Animated(D::Animated),
34}
35
36impl<D: DataSystem> GenericValue<D> {
37 pub fn uniform(value: D) -> Self {
39 GenericValue::Uniform(value)
40 }
41
42 pub fn animated<I>(samples: I) -> Result<Self>
47 where
48 I: IntoIterator<Item = (Time, D)>,
49 {
50 let mut samples_vec: Vec<(Time, D)> = samples.into_iter().collect();
51
52 if samples_vec.is_empty() {
53 return Err(crate::Error::EmptySamples);
54 }
55
56 let data_type = samples_vec[0].1.discriminant();
58 let expected_name = samples_vec[0].1.variant_name();
59
60 let mut expected_len: Option<usize> = None;
62 for (time, value) in &mut samples_vec {
63 if value.discriminant() != data_type {
64 return Err(crate::Error::GenericTypeMismatch {
65 expected: expected_name,
66 got: value.variant_name(),
67 });
68 }
69
70 if let Some(vec_len) = value.try_len() {
72 match expected_len {
73 None => expected_len = Some(vec_len),
74 Some(expected) => {
75 if vec_len > expected {
76 return Err(crate::Error::VectorLengthExceeded {
77 actual: vec_len,
78 expected,
79 time: *time,
80 });
81 } else if vec_len < expected {
82 value.pad_to_length(expected);
83 }
84 }
85 }
86 }
87 }
88
89 let (first_time, first_value) = samples_vec.remove(0);
91 let mut animated = D::Animated::from_single(first_time, first_value);
92
93 for (time, value) in samples_vec {
94 animated.try_insert(time, value)?;
95 }
96
97 Ok(GenericValue::Animated(animated))
98 }
99
100 pub fn add_sample(&mut self, time: Time, value: D) -> Result<()> {
104 match self {
105 GenericValue::Uniform(_) => {
106 *self = GenericValue::animated(vec![(time, value)])?;
107 Ok(())
108 }
109 GenericValue::Animated(samples) => {
110 if value.discriminant() != samples.discriminant() {
111 return Err(crate::Error::GenericTypeMismatch {
112 expected: samples.variant_name(),
113 got: value.variant_name(),
114 });
115 }
116 samples.try_insert(time, value)
117 }
118 }
119 }
120
121 pub fn remove_at(&mut self, time: &Time) -> Option<D> {
128 match self {
129 GenericValue::Uniform(_) => None,
130 GenericValue::Animated(samples) => samples.remove_at(time),
131 }
132 }
133
134 #[deprecated(since = "0.2.2", note = "renamed to `remove_at`")]
136 pub fn remove_sample(&mut self, time: &Time) -> Option<D> {
137 self.remove_at(time)
138 }
139
140 pub fn remove_at_or_to_uniform(&mut self, time: &Time) -> Option<D> {
148 match self {
149 GenericValue::Uniform(_) => None,
150 GenericValue::Animated(samples) => {
151 let removed = samples.remove_at(time);
152 if removed.is_some() {
153 return removed;
154 }
155 if samples.sample_at(*time).is_some() {
158 let data = samples.interpolate(Time::default());
160 *self = GenericValue::Uniform(data);
161 }
162 None
163 }
164 }
165 }
166
167 pub fn sample_at(&self, time: Time) -> Option<D> {
172 match self {
173 GenericValue::Uniform(v) => Some(v.clone()),
174 GenericValue::Animated(samples) => samples.sample_at(time),
175 }
176 }
177
178 pub fn interpolate(&self, time: Time) -> D {
183 match self {
184 GenericValue::Uniform(v) => v.clone(),
185 GenericValue::Animated(samples) => samples.interpolate(time),
186 }
187 }
188
189 pub fn is_animated(&self) -> bool {
191 match self {
192 GenericValue::Uniform(_) => false,
193 GenericValue::Animated(samples) => samples.has_animation(),
194 }
195 }
196
197 pub fn sample_count(&self) -> usize {
199 match self {
200 GenericValue::Uniform(_) => 1,
201 GenericValue::Animated(samples) => samples.keyframe_count(),
202 }
203 }
204
205 pub fn times(&self) -> SmallVec<[Time; 10]> {
207 match self {
208 GenericValue::Uniform(_) => SmallVec::new_const(),
209 GenericValue::Animated(samples) => samples.times(),
210 }
211 }
212
213 pub fn discriminant(&self) -> D::DataType {
215 match self {
216 GenericValue::Uniform(data) => data.discriminant(),
217 GenericValue::Animated(animated) => animated.discriminant(),
218 }
219 }
220
221 pub fn variant_name(&self) -> &'static str {
223 match self {
224 GenericValue::Uniform(data) => data.variant_name(),
225 GenericValue::Animated(animated) => animated.variant_name(),
226 }
227 }
228
229 pub fn merge_with<F>(&self, other: &GenericValue<D>, combiner: F) -> Result<GenericValue<D>>
235 where
236 F: Fn(&D, &D) -> D,
237 {
238 match (self, other) {
239 (GenericValue::Uniform(a), GenericValue::Uniform(b)) => {
240 Ok(GenericValue::Uniform(combiner(a, b)))
241 }
242 _ => {
243 let mut all_times = std::collections::BTreeSet::new();
244 for t in self.times() {
245 all_times.insert(t);
246 }
247 for t in other.times() {
248 all_times.insert(t);
249 }
250
251 if all_times.is_empty() {
252 let a = self.interpolate(Time::default());
253 let b = other.interpolate(Time::default());
254 return Ok(GenericValue::Uniform(combiner(&a, &b)));
255 }
256
257 let combined_samples: Vec<(Time, D)> = all_times
258 .into_iter()
259 .map(|time| {
260 let a = self.interpolate(time);
261 let b = other.interpolate(time);
262 (time, combiner(&a, &b))
263 })
264 .collect();
265
266 if combined_samples.len() == 1 {
267 Ok(GenericValue::Uniform(
268 combined_samples.into_iter().next().unwrap().1,
270 ))
271 } else {
272 GenericValue::animated(combined_samples)
273 }
274 }
275 }
276 }
277
278 pub fn hash_with_shutter<H: Hasher>(&self, state: &mut H, shutter: &Shutter) {
283 match self {
284 GenericValue::Uniform(data) => {
285 data.hash(state);
286 }
287 GenericValue::Animated(animated) => {
288 const SAMPLE_POSITIONS: [f32; 5] = [0.0, 0.25, 0.5, 0.75, 1.0];
290
291 let samples: SmallVec<[D; 5]> = SAMPLE_POSITIONS
292 .iter()
293 .map(|&pos| {
294 let time = shutter.evaluate(pos);
295 animated.interpolate(time)
296 })
297 .collect();
298
299 let all_same = samples.windows(2).all(|w| w[0] == w[1]);
300
301 std::mem::discriminant(self).hash(state);
302
303 if all_same {
304 1usize.hash(state);
305 samples[0].hash(state);
306 } else {
307 samples.len().hash(state);
308 for sample in &samples {
309 sample.hash(state);
310 }
311 }
312 }
313 }
314 }
315}
316
317impl<D: DataSystem> From<D> for GenericValue<D> {
318 fn from(value: D) -> Self {
319 GenericValue::uniform(value)
320 }
321}
322
323impl<D: DataSystem> Eq for GenericValue<D> {}