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> {
126 match self {
127 GenericValue::Uniform(_) => None,
128 GenericValue::Animated(samples) => samples.remove_at(time),
129 }
130 }
131
132 pub fn sample_at(&self, time: Time) -> Option<D> {
137 match self {
138 GenericValue::Uniform(v) => Some(v.clone()),
139 GenericValue::Animated(samples) => samples.sample_at(time),
140 }
141 }
142
143 pub fn interpolate(&self, time: Time) -> D {
148 match self {
149 GenericValue::Uniform(v) => v.clone(),
150 GenericValue::Animated(samples) => samples.interpolate(time),
151 }
152 }
153
154 pub fn is_animated(&self) -> bool {
156 match self {
157 GenericValue::Uniform(_) => false,
158 GenericValue::Animated(samples) => samples.has_animation(),
159 }
160 }
161
162 pub fn sample_count(&self) -> usize {
164 match self {
165 GenericValue::Uniform(_) => 1,
166 GenericValue::Animated(samples) => samples.keyframe_count(),
167 }
168 }
169
170 pub fn times(&self) -> SmallVec<[Time; 10]> {
172 match self {
173 GenericValue::Uniform(_) => SmallVec::new_const(),
174 GenericValue::Animated(samples) => samples.times(),
175 }
176 }
177
178 pub fn discriminant(&self) -> D::DataType {
180 match self {
181 GenericValue::Uniform(data) => data.discriminant(),
182 GenericValue::Animated(animated) => animated.discriminant(),
183 }
184 }
185
186 pub fn variant_name(&self) -> &'static str {
188 match self {
189 GenericValue::Uniform(data) => data.variant_name(),
190 GenericValue::Animated(animated) => animated.variant_name(),
191 }
192 }
193
194 pub fn merge_with<F>(&self, other: &GenericValue<D>, combiner: F) -> Result<GenericValue<D>>
200 where
201 F: Fn(&D, &D) -> D,
202 {
203 match (self, other) {
204 (GenericValue::Uniform(a), GenericValue::Uniform(b)) => {
205 Ok(GenericValue::Uniform(combiner(a, b)))
206 }
207 _ => {
208 let mut all_times = std::collections::BTreeSet::new();
209 for t in self.times() {
210 all_times.insert(t);
211 }
212 for t in other.times() {
213 all_times.insert(t);
214 }
215
216 if all_times.is_empty() {
217 let a = self.interpolate(Time::default());
218 let b = other.interpolate(Time::default());
219 return Ok(GenericValue::Uniform(combiner(&a, &b)));
220 }
221
222 let combined_samples: Vec<(Time, D)> = all_times
223 .into_iter()
224 .map(|time| {
225 let a = self.interpolate(time);
226 let b = other.interpolate(time);
227 (time, combiner(&a, &b))
228 })
229 .collect();
230
231 if combined_samples.len() == 1 {
232 Ok(GenericValue::Uniform(
233 combined_samples.into_iter().next().unwrap().1,
234 ))
235 } else {
236 GenericValue::animated(combined_samples)
237 }
238 }
239 }
240 }
241
242 pub fn hash_with_shutter<H: Hasher>(&self, state: &mut H, shutter: &Shutter) {
247 match self {
248 GenericValue::Uniform(data) => {
249 data.hash(state);
250 }
251 GenericValue::Animated(animated) => {
252 const SAMPLE_POSITIONS: [f32; 5] = [0.0, 0.25, 0.5, 0.75, 1.0];
254
255 let samples: SmallVec<[D; 5]> = SAMPLE_POSITIONS
256 .iter()
257 .map(|&pos| {
258 let time = shutter.evaluate(pos);
259 animated.interpolate(time)
260 })
261 .collect();
262
263 let all_same = samples.windows(2).all(|w| w[0] == w[1]);
264
265 std::mem::discriminant(self).hash(state);
266
267 if all_same {
268 1usize.hash(state);
269 samples[0].hash(state);
270 } else {
271 samples.len().hash(state);
272 for sample in &samples {
273 sample.hash(state);
274 }
275 }
276 }
277 }
278 }
279}
280
281impl<D: DataSystem> From<D> for GenericValue<D> {
282 fn from(value: D) -> Self {
283 GenericValue::uniform(value)
284 }
285}
286
287impl<D: DataSystem> Eq for GenericValue<D> {}