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_sample(&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 pub fn remove_or_make_uniform(&mut self, time: &Time) -> Option<D> {
142 match self {
143 GenericValue::Uniform(_) => None,
144 GenericValue::Animated(samples) => {
145 let removed = samples.remove_at(time);
146 if removed.is_some() {
147 return removed;
148 }
149 if samples.sample_at(*time).is_some() {
152 let data = samples.interpolate(Time::default());
154 *self = GenericValue::Uniform(data);
155 }
156 None
157 }
158 }
159 }
160
161 pub fn sample_at(&self, time: Time) -> Option<D> {
166 match self {
167 GenericValue::Uniform(v) => Some(v.clone()),
168 GenericValue::Animated(samples) => samples.sample_at(time),
169 }
170 }
171
172 pub fn interpolate(&self, time: Time) -> D {
177 match self {
178 GenericValue::Uniform(v) => v.clone(),
179 GenericValue::Animated(samples) => samples.interpolate(time),
180 }
181 }
182
183 pub fn is_animated(&self) -> bool {
185 match self {
186 GenericValue::Uniform(_) => false,
187 GenericValue::Animated(samples) => samples.has_animation(),
188 }
189 }
190
191 pub fn sample_count(&self) -> usize {
193 match self {
194 GenericValue::Uniform(_) => 1,
195 GenericValue::Animated(samples) => samples.keyframe_count(),
196 }
197 }
198
199 pub fn times(&self) -> SmallVec<[Time; 10]> {
201 match self {
202 GenericValue::Uniform(_) => SmallVec::new_const(),
203 GenericValue::Animated(samples) => samples.times(),
204 }
205 }
206
207 pub fn discriminant(&self) -> D::DataType {
209 match self {
210 GenericValue::Uniform(data) => data.discriminant(),
211 GenericValue::Animated(animated) => animated.discriminant(),
212 }
213 }
214
215 pub fn variant_name(&self) -> &'static str {
217 match self {
218 GenericValue::Uniform(data) => data.variant_name(),
219 GenericValue::Animated(animated) => animated.variant_name(),
220 }
221 }
222
223 pub fn merge_with<F>(&self, other: &GenericValue<D>, combiner: F) -> Result<GenericValue<D>>
229 where
230 F: Fn(&D, &D) -> D,
231 {
232 match (self, other) {
233 (GenericValue::Uniform(a), GenericValue::Uniform(b)) => {
234 Ok(GenericValue::Uniform(combiner(a, b)))
235 }
236 _ => {
237 let mut all_times = std::collections::BTreeSet::new();
238 for t in self.times() {
239 all_times.insert(t);
240 }
241 for t in other.times() {
242 all_times.insert(t);
243 }
244
245 if all_times.is_empty() {
246 let a = self.interpolate(Time::default());
247 let b = other.interpolate(Time::default());
248 return Ok(GenericValue::Uniform(combiner(&a, &b)));
249 }
250
251 let combined_samples: Vec<(Time, D)> = all_times
252 .into_iter()
253 .map(|time| {
254 let a = self.interpolate(time);
255 let b = other.interpolate(time);
256 (time, combiner(&a, &b))
257 })
258 .collect();
259
260 if combined_samples.len() == 1 {
261 Ok(GenericValue::Uniform(
262 combined_samples.into_iter().next().unwrap().1,
264 ))
265 } else {
266 GenericValue::animated(combined_samples)
267 }
268 }
269 }
270 }
271
272 pub fn hash_with_shutter<H: Hasher>(&self, state: &mut H, shutter: &Shutter) {
277 match self {
278 GenericValue::Uniform(data) => {
279 data.hash(state);
280 }
281 GenericValue::Animated(animated) => {
282 const SAMPLE_POSITIONS: [f32; 5] = [0.0, 0.25, 0.5, 0.75, 1.0];
284
285 let samples: SmallVec<[D; 5]> = SAMPLE_POSITIONS
286 .iter()
287 .map(|&pos| {
288 let time = shutter.evaluate(pos);
289 animated.interpolate(time)
290 })
291 .collect();
292
293 let all_same = samples.windows(2).all(|w| w[0] == w[1]);
294
295 std::mem::discriminant(self).hash(state);
296
297 if all_same {
298 1usize.hash(state);
299 samples[0].hash(state);
300 } else {
301 samples.len().hash(state);
302 for sample in &samples {
303 sample.hash(state);
304 }
305 }
306 }
307 }
308 }
309}
310
311impl<D: DataSystem> From<D> for GenericValue<D> {
312 fn from(value: D) -> Self {
313 GenericValue::uniform(value)
314 }
315}
316
317impl<D: DataSystem> Eq for GenericValue<D> {}