melodium_common/executive/value/
data.rs1use super::super::Data;
2use super::Value;
3use std::sync::Arc;
4
5pub trait GetData<T>: Sized {
10 fn try_data(self) -> Result<T, ()>;
11}
12
13impl GetData<Value> for Value {
20 fn try_data(self) -> Result<Value, ()> {
21 Ok(self)
22 }
23}
24
25impl From<()> for Value {
26 fn from(value: ()) -> Self {
27 Value::Void(value)
28 }
29}
30
31impl GetData<()> for Value {
32 fn try_data(self) -> Result<(), ()> {
33 match self {
34 Value::Void(_) => Ok(()),
35 _ => Err(()),
36 }
37 }
38}
39
40impl From<i8> for Value {
41 fn from(value: i8) -> Self {
42 Value::I8(value)
43 }
44}
45
46impl GetData<i8> for Value {
47 fn try_data(self) -> Result<i8, ()> {
48 match self {
49 Value::I8(val) => Ok(val),
50 _ => Err(()),
51 }
52 }
53}
54impl From<i16> for Value {
55 fn from(value: i16) -> Self {
56 Value::I16(value)
57 }
58}
59
60impl GetData<i16> for Value {
61 fn try_data(self) -> Result<i16, ()> {
62 match self {
63 Value::I16(val) => Ok(val),
64 _ => Err(()),
65 }
66 }
67}
68impl From<i32> for Value {
69 fn from(value: i32) -> Self {
70 Value::I32(value)
71 }
72}
73
74impl GetData<i32> for Value {
75 fn try_data(self) -> Result<i32, ()> {
76 match self {
77 Value::I32(val) => Ok(val),
78 _ => Err(()),
79 }
80 }
81}
82impl From<i64> for Value {
83 fn from(value: i64) -> Self {
84 Value::I64(value)
85 }
86}
87
88impl GetData<i64> for Value {
89 fn try_data(self) -> Result<i64, ()> {
90 match self {
91 Value::I64(val) => Ok(val),
92 _ => Err(()),
93 }
94 }
95}
96impl From<i128> for Value {
97 fn from(value: i128) -> Self {
98 Value::I128(value)
99 }
100}
101
102impl GetData<i128> for Value {
103 fn try_data(self) -> Result<i128, ()> {
104 match self {
105 Value::I128(val) => Ok(val),
106 _ => Err(()),
107 }
108 }
109}
110
111impl From<u8> for Value {
112 fn from(value: u8) -> Self {
113 Value::U8(value)
114 }
115}
116
117impl GetData<u8> for Value {
118 fn try_data(self) -> Result<u8, ()> {
119 match self {
120 Value::U8(val) => Ok(val),
121 Value::Byte(val) => Ok(val),
122 _ => Err(()),
123 }
124 }
125}
126impl From<u16> for Value {
127 fn from(value: u16) -> Self {
128 Value::U16(value)
129 }
130}
131
132impl GetData<u16> for Value {
133 fn try_data(self) -> Result<u16, ()> {
134 match self {
135 Value::U16(val) => Ok(val),
136 _ => Err(()),
137 }
138 }
139}
140impl From<u32> for Value {
141 fn from(value: u32) -> Self {
142 Value::U32(value)
143 }
144}
145
146impl GetData<u32> for Value {
147 fn try_data(self) -> Result<u32, ()> {
148 match self {
149 Value::U32(val) => Ok(val),
150 _ => Err(()),
151 }
152 }
153}
154impl From<u64> for Value {
155 fn from(value: u64) -> Self {
156 Value::U64(value)
157 }
158}
159
160impl GetData<u64> for Value {
161 fn try_data(self) -> Result<u64, ()> {
162 match self {
163 Value::U64(val) => Ok(val),
164 _ => Err(()),
165 }
166 }
167}
168impl From<u128> for Value {
169 fn from(value: u128) -> Self {
170 Value::U128(value)
171 }
172}
173
174impl GetData<u128> for Value {
175 fn try_data(self) -> Result<u128, ()> {
176 match self {
177 Value::U128(val) => Ok(val),
178 _ => Err(()),
179 }
180 }
181}
182
183impl From<f32> for Value {
184 fn from(value: f32) -> Self {
185 Value::F32(value)
186 }
187}
188
189impl GetData<f32> for Value {
190 fn try_data(self) -> Result<f32, ()> {
191 match self {
192 Value::F32(val) => Ok(val),
193 _ => Err(()),
194 }
195 }
196}
197impl From<f64> for Value {
198 fn from(value: f64) -> Self {
199 Value::F64(value)
200 }
201}
202
203impl GetData<f64> for Value {
204 fn try_data(self) -> Result<f64, ()> {
205 match self {
206 Value::F64(val) => Ok(val),
207 _ => Err(()),
208 }
209 }
210}
211
212impl From<bool> for Value {
213 fn from(value: bool) -> Self {
214 Value::Bool(value)
215 }
216}
217
218impl GetData<bool> for Value {
219 fn try_data(self) -> Result<bool, ()> {
220 match self {
221 Value::Bool(val) => Ok(val),
222 _ => Err(()),
223 }
224 }
225}
226impl From<char> for Value {
227 fn from(value: char) -> Self {
228 Value::Char(value)
229 }
230}
231
232impl GetData<char> for Value {
233 fn try_data(self) -> Result<char, ()> {
234 match self {
235 Value::Char(val) => Ok(val),
236 _ => Err(()),
237 }
238 }
239}
240impl From<String> for Value {
241 fn from(value: String) -> Self {
242 Value::String(value)
243 }
244}
245
246impl GetData<String> for Value {
247 fn try_data(self) -> Result<String, ()> {
248 match self {
249 Value::String(val) => Ok(val),
250 _ => Err(()),
251 }
252 }
253}
254
255impl<T: Into<Value>> From<Option<T>> for Value {
256 fn from(value: Option<T>) -> Self {
257 Value::Option(value.map(|val| Box::new(val.into())))
258 }
259}
260
261impl<T> GetData<Option<T>> for Value
262where
263 Self: GetData<T>,
264{
265 fn try_data(self) -> Result<Option<T>, ()> {
266 match self {
267 Value::Option(val) => {
268 if let Some(val) = val {
269 match val.try_data() {
270 Ok(val) => Ok(Some(val)),
271 Err(_) => Err(()),
272 }
273 } else {
274 Ok(None)
275 }
276 }
277 _ => Err(()),
278 }
279 }
280}
281
282impl<T: Into<Value> + 'static> From<Vec<T>> for Value {
283 fn from(value: Vec<T>) -> Self {
284 match super::PackedArray::try_from_vec(value) {
290 Ok(packed) => Value::Packed(packed),
291 Err(value) => Value::Vec(value.into_iter().map(|val| val.into()).collect()),
292 }
293 }
294}
295
296impl<T: 'static> GetData<Vec<T>> for Value
297where
298 Self: GetData<T>,
299{
300 fn try_data(self) -> Result<Vec<T>, ()> {
301 match self {
302 Value::Vec(val) => {
303 let mut result = Vec::with_capacity(val.len());
304 for val in val {
305 match val.try_data() {
306 Ok(val) => result.push(val),
307 Err(_) => return Err(()),
308 }
309 }
310 Ok(result)
311 }
312 Value::Packed(arr) => match arr.try_into_vec() {
330 Ok(vec) => Ok(vec),
331 Err(arr) => {
332 let val = arr.into_values();
333 let mut result = Vec::with_capacity(val.len());
334 for val in val {
335 match val.try_data() {
336 Ok(val) => result.push(val),
337 Err(_) => return Err(()),
338 }
339 }
340 Ok(result)
341 }
342 },
343 _ => Err(()),
344 }
345 }
346}
347
348impl From<Arc<dyn Data>> for Value {
349 fn from(value: Arc<dyn Data>) -> Self {
350 Value::Data(value)
351 }
352}
353
354impl GetData<Arc<dyn Data>> for Value {
355 fn try_data(self) -> Result<Arc<dyn Data>, ()> {
356 match self {
357 Value::Data(val) => Ok(val),
358 _ => Err(()),
359 }
360 }
361}
362
363impl<D: Data> GetData<Arc<D>> for Value {
370 fn try_data(self) -> Result<Arc<D>, ()> {
371 let data: Arc<dyn Data> = GetData::<Arc<dyn Data>>::try_data(self)?;
372 data.downcast_arc::<D>().map_err(|_| ())
373 }
374}
375
376#[cfg(test)]
377mod arc_data_getdata_tests {
378 use super::*;
379
380 fn _assert_composes<D: Data>()
383 where
384 Value: GetData<Vec<Arc<D>>> + GetData<Option<Arc<D>>> + GetData<Vec<Option<Arc<D>>>>,
385 {
386 }
387}
388
389#[cfg(test)]
390mod auto_packing_tests {
391 use super::*;
392 use crate::executive::PackedArray;
393
394 #[test]
399 fn into_produces_packed_for_a_packable_primitive() {
400 let value: Value = vec![1u8, 2, 3].into();
401 assert!(matches!(value, Value::Packed(PackedArray::U8(_))));
402 }
403
404 #[test]
405 fn into_still_produces_the_boxed_form_for_a_non_packable_type() {
406 let value: Value = vec!["a".to_string(), "b".to_string()].into();
407 assert!(matches!(value, Value::Vec(_)));
408 }
409
410 #[test]
413 fn value_extracts_to_itself() {
414 let value = Value::U64(42);
415 let extracted: Value = value.clone().try_data().unwrap();
416 assert_eq!(extracted, value);
417 }
418
419 #[test]
426 fn vec_of_value_extracts_correctly_from_a_packed_source() {
427 let value = Value::Packed(PackedArray::I64(Arc::new(vec![1, 2, 3])));
428 let extracted: Vec<Value> = value.try_data().unwrap();
429 assert_eq!(extracted, vec![Value::I64(1), Value::I64(2), Value::I64(3)]);
430 }
431
432 #[test]
433 fn vec_of_value_still_extracts_correctly_from_a_boxed_source() {
434 let value = Value::Vec(vec![Value::I64(1), Value::I64(2)]);
435 let extracted: Vec<Value> = value.try_data().unwrap();
436 assert_eq!(extracted, vec![Value::I64(1), Value::I64(2)]);
437 }
438
439 #[test]
442 fn into_auto_packs_through_nested_option() {
443 let value: Value = Some(vec![1u8, 2, 3]).into();
444 match value {
445 Value::Option(Some(inner)) => {
446 assert!(matches!(*inner, Value::Packed(PackedArray::U8(_))));
447 }
448 other => panic!(
449 "expected Value::Option(Some(Value::Packed(_))), got {:?}",
450 other
451 ),
452 }
453 }
454
455 #[test]
458 fn auto_packed_value_extracts_correctly_both_ways() {
459 let value: Value = vec![1u8, 2, 3].into();
460
461 let as_vec: Vec<u8> = value.clone().try_data().unwrap();
462 assert_eq!(as_vec, vec![1, 2, 3]);
463
464 let as_arc: Arc<Vec<u8>> = value.try_data().unwrap();
465 assert_eq!(*as_arc, vec![1, 2, 3]);
466 }
467}