d2_stampede/
field_value.rs

1use std::fmt::{Display, Formatter};
2
3/// Special type for [`Entity`](crate::Entity) field value that can be converted
4/// into Rust type using `try_into`.
5#[derive(Debug, Clone, PartialEq)]
6pub enum FieldValue {
7    Boolean(bool),
8    String(String),
9    Float(f32),
10
11    Vector2D([f32; 2]),
12    Vector3D([f32; 3]),
13    Vector4D([f32; 4]),
14
15    Signed8(i8),
16    Signed16(i16),
17    Signed32(i32),
18    Signed64(i64),
19
20    Unsigned8(u8),
21    Unsigned16(u16),
22    Unsigned32(u32),
23    Unsigned64(u64),
24}
25
26#[derive(thiserror::Error, Debug)]
27pub enum FieldValueError {
28    #[error("Cannot convert {0} into {1}")]
29    ConversionError(String, String),
30}
31
32impl Display for FieldValue {
33    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
34        match self {
35            FieldValue::Boolean(val) => write!(f, "{}", val),
36            FieldValue::String(val) => write!(f, "\"{}\"", val),
37            FieldValue::Float(val) => write!(f, "{}", val),
38            FieldValue::Vector2D(val) => write!(f, "[{}, {}]", val[0], val[1]),
39            FieldValue::Vector3D(val) => write!(f, "[{}, {}, {}]", val[0], val[1], val[2]),
40            FieldValue::Vector4D(val) => {
41                write!(f, "[{}, {}, {}, {}]", val[0], val[1], val[2], val[3])
42            }
43            FieldValue::Signed8(val) => write!(f, "{}", val),
44            FieldValue::Signed16(val) => write!(f, "{}", val),
45            FieldValue::Signed32(val) => write!(f, "{}", val),
46            FieldValue::Signed64(val) => write!(f, "{}", val),
47            FieldValue::Unsigned8(val) => write!(f, "{}", val),
48            FieldValue::Unsigned16(val) => write!(f, "{}", val),
49            FieldValue::Unsigned32(val) => write!(f, "{}", val),
50            FieldValue::Unsigned64(val) => write!(f, "{}", val),
51        }
52    }
53}
54
55impl TryInto<String> for FieldValue {
56    type Error = FieldValueError;
57
58    fn try_into(self) -> Result<String, FieldValueError> {
59        if let FieldValue::String(x) = self {
60            Ok(x)
61        } else {
62            Err(FieldValueError::ConversionError(
63                format!("{:?}", self),
64                "String".to_string(),
65            ))
66        }
67    }
68}
69
70impl TryInto<String> for &FieldValue {
71    type Error = FieldValueError;
72
73    fn try_into(self) -> Result<String, FieldValueError> {
74        if let FieldValue::String(x) = self {
75            Ok(x.to_owned())
76        } else {
77            Err(FieldValueError::ConversionError(
78                format!("{:?}", self),
79                "String".to_string(),
80            ))
81        }
82    }
83}
84
85impl TryInto<[f32; 2]> for FieldValue {
86    type Error = FieldValueError;
87
88    fn try_into(self) -> Result<[f32; 2], FieldValueError> {
89        if let FieldValue::Vector2D(x) = self {
90            Ok(x)
91        } else {
92            Err(FieldValueError::ConversionError(
93                format!("{:?}", self),
94                "[f32; 2]".to_string(),
95            ))
96        }
97    }
98}
99
100impl TryInto<[f32; 2]> for &FieldValue {
101    type Error = FieldValueError;
102
103    fn try_into(self) -> Result<[f32; 2], FieldValueError> {
104        if let FieldValue::Vector2D(x) = self {
105            Ok(*x)
106        } else {
107            Err(FieldValueError::ConversionError(
108                format!("{:?}", self),
109                "[f32; 2]".to_string(),
110            ))
111        }
112    }
113}
114
115impl TryInto<(f32, f32)> for FieldValue {
116    type Error = FieldValueError;
117
118    fn try_into(self) -> Result<(f32, f32), FieldValueError> {
119        if let FieldValue::Vector2D(x) = self {
120            Ok(x.into())
121        } else {
122            Err(FieldValueError::ConversionError(
123                format!("{:?}", self),
124                "(f32, f32)".to_string(),
125            ))
126        }
127    }
128}
129
130impl TryInto<(f32, f32)> for &FieldValue {
131    type Error = FieldValueError;
132
133    fn try_into(self) -> Result<(f32, f32), FieldValueError> {
134        if let FieldValue::Vector2D(x) = self {
135            Ok((*x).into())
136        } else {
137            Err(FieldValueError::ConversionError(
138                format!("{:?}", self),
139                "(f32, f32)".to_string(),
140            ))
141        }
142    }
143}
144
145impl TryInto<[f32; 3]> for FieldValue {
146    type Error = FieldValueError;
147
148    fn try_into(self) -> Result<[f32; 3], FieldValueError> {
149        if let FieldValue::Vector3D(x) = self {
150            Ok(x)
151        } else {
152            Err(FieldValueError::ConversionError(
153                format!("{:?}", self),
154                "[f32; 3]".to_string(),
155            ))
156        }
157    }
158}
159
160impl TryInto<[f32; 3]> for &FieldValue {
161    type Error = FieldValueError;
162
163    fn try_into(self) -> Result<[f32; 3], FieldValueError> {
164        if let FieldValue::Vector3D(x) = self {
165            Ok(*x)
166        } else {
167            Err(FieldValueError::ConversionError(
168                format!("{:?}", self),
169                "[f32; 3]".to_string(),
170            ))
171        }
172    }
173}
174
175impl TryInto<(f32, f32, f32)> for FieldValue {
176    type Error = FieldValueError;
177
178    fn try_into(self) -> Result<(f32, f32, f32), FieldValueError> {
179        if let FieldValue::Vector3D(x) = self {
180            Ok(x.into())
181        } else {
182            Err(FieldValueError::ConversionError(
183                format!("{:?}", self),
184                "(f32, f32, f32)".to_string(),
185            ))
186        }
187    }
188}
189
190impl TryInto<(f32, f32, f32)> for &FieldValue {
191    type Error = FieldValueError;
192
193    fn try_into(self) -> Result<(f32, f32, f32), FieldValueError> {
194        if let FieldValue::Vector3D(x) = self {
195            Ok((*x).into())
196        } else {
197            Err(FieldValueError::ConversionError(
198                format!("{:?}", self),
199                "(f32, f32, f32)".to_string(),
200            ))
201        }
202    }
203}
204
205impl TryInto<[f32; 4]> for FieldValue {
206    type Error = FieldValueError;
207
208    fn try_into(self) -> Result<[f32; 4], FieldValueError> {
209        if let FieldValue::Vector4D(x) = self {
210            Ok(x)
211        } else {
212            Err(FieldValueError::ConversionError(
213                format!("{:?}", self),
214                "[f32; 4]".to_string(),
215            ))
216        }
217    }
218}
219
220impl TryInto<[f32; 4]> for &FieldValue {
221    type Error = FieldValueError;
222
223    fn try_into(self) -> Result<[f32; 4], FieldValueError> {
224        if let FieldValue::Vector4D(x) = self {
225            Ok(*x)
226        } else {
227            Err(FieldValueError::ConversionError(
228                format!("{:?}", self),
229                "[f32; 4]".to_string(),
230            ))
231        }
232    }
233}
234
235impl TryInto<(f32, f32, f32, f32)> for FieldValue {
236    type Error = FieldValueError;
237
238    fn try_into(self) -> Result<(f32, f32, f32, f32), FieldValueError> {
239        if let FieldValue::Vector4D(x) = self {
240            Ok(x.into())
241        } else {
242            Err(FieldValueError::ConversionError(
243                format!("{:?}", self),
244                "(f32, f32, f32, f32)".to_string(),
245            ))
246        }
247    }
248}
249
250impl TryInto<(f32, f32, f32, f32)> for &FieldValue {
251    type Error = FieldValueError;
252
253    fn try_into(self) -> Result<(f32, f32, f32, f32), FieldValueError> {
254        if let FieldValue::Vector4D(x) = self {
255            Ok((*x).into())
256        } else {
257            Err(FieldValueError::ConversionError(
258                format!("{:?}", self),
259                "(f32, f32, f32, f32)".to_string(),
260            ))
261        }
262    }
263}
264
265impl TryInto<Vec<f32>> for FieldValue {
266    type Error = FieldValueError;
267
268    fn try_into(self) -> Result<Vec<f32>, FieldValueError> {
269        match self {
270            FieldValue::Vector2D(x) => Ok(x.to_vec()),
271            FieldValue::Vector3D(x) => Ok(x.to_vec()),
272            FieldValue::Vector4D(x) => Ok(x.to_vec()),
273            _ => Err(FieldValueError::ConversionError(
274                format!("{:?}", self),
275                "Vec<f32>".to_string(),
276            )),
277        }
278    }
279}
280
281impl TryInto<Vec<f32>> for &FieldValue {
282    type Error = FieldValueError;
283
284    fn try_into(self) -> Result<Vec<f32>, FieldValueError> {
285        match self {
286            FieldValue::Vector2D(x) => Ok(x.to_vec()),
287            FieldValue::Vector3D(x) => Ok(x.to_vec()),
288            FieldValue::Vector4D(x) => Ok(x.to_vec()),
289            _ => Err(FieldValueError::ConversionError(
290                format!("{:?}", self),
291                "Vec<f32>".to_string(),
292            )),
293        }
294    }
295}
296
297impl TryInto<f32> for FieldValue {
298    type Error = FieldValueError;
299
300    fn try_into(self) -> Result<f32, FieldValueError> {
301        if let FieldValue::Float(x) = self {
302            Ok(x)
303        } else {
304            Err(FieldValueError::ConversionError(
305                format!("{:?}", self),
306                "f32".to_string(),
307            ))
308        }
309    }
310}
311
312impl TryInto<f32> for &FieldValue {
313    type Error = FieldValueError;
314
315    fn try_into(self) -> Result<f32, FieldValueError> {
316        if let FieldValue::Float(x) = self {
317            Ok(*x)
318        } else {
319            Err(FieldValueError::ConversionError(
320                format!("{:?}", self),
321                "f32".to_string(),
322            ))
323        }
324    }
325}
326
327impl TryInto<bool> for FieldValue {
328    type Error = FieldValueError;
329
330    fn try_into(self) -> Result<bool, FieldValueError> {
331        if let FieldValue::Boolean(x) = self {
332            Ok(x)
333        } else {
334            Err(FieldValueError::ConversionError(
335                format!("{:?}", self),
336                "bool".to_string(),
337            ))
338        }
339    }
340}
341
342impl TryInto<bool> for &FieldValue {
343    type Error = FieldValueError;
344
345    fn try_into(self) -> Result<bool, FieldValueError> {
346        if let FieldValue::Boolean(x) = self {
347            Ok(*x)
348        } else {
349            Err(FieldValueError::ConversionError(
350                format!("{:?}", self),
351                "bool".to_string(),
352            ))
353        }
354    }
355}
356
357macro_rules! impl_try_into_for_integers {
358    ($target:ty) => {
359        impl TryInto<$target> for FieldValue {
360            type Error = FieldValueError;
361
362            fn try_into(self) -> Result<$target, FieldValueError> {
363                match self {
364                    // EntityFieldType::Boolean(x) => Ok((x == 1) as $target),
365                    FieldValue::Signed8(x) => {
366                        Ok(TryInto::<$target>::try_into(x).map_err(|_| {
367                            FieldValueError::ConversionError(
368                                format!("{:?}", x),
369                                stringify!($target).to_string(),
370                            )
371                        })?)
372                    }
373                    FieldValue::Signed16(x) => {
374                        Ok(TryInto::<$target>::try_into(x).map_err(|_| {
375                            FieldValueError::ConversionError(
376                                format!("{:?}", x),
377                                stringify!($target).to_string(),
378                            )
379                        })?)
380                    }
381                    FieldValue::Signed32(x) => {
382                        Ok(TryInto::<$target>::try_into(x).map_err(|_| {
383                            FieldValueError::ConversionError(
384                                format!("{:?}", x),
385                                stringify!($target).to_string(),
386                            )
387                        })?)
388                    }
389                    FieldValue::Signed64(x) => {
390                        Ok(TryInto::<$target>::try_into(x).map_err(|_| {
391                            FieldValueError::ConversionError(
392                                format!("{:?}", x),
393                                stringify!($target).to_string(),
394                            )
395                        })?)
396                    }
397                    FieldValue::Unsigned8(x) => {
398                        Ok(TryInto::<$target>::try_into(x).map_err(|_| {
399                            FieldValueError::ConversionError(
400                                format!("{:?}", x),
401                                stringify!($target).to_string(),
402                            )
403                        })?)
404                    }
405                    FieldValue::Unsigned16(x) => {
406                        Ok(TryInto::<$target>::try_into(x).map_err(|_| {
407                            FieldValueError::ConversionError(
408                                format!("{:?}", x),
409                                stringify!($target).to_string(),
410                            )
411                        })?)
412                    }
413                    FieldValue::Unsigned32(x) => {
414                        Ok(TryInto::<$target>::try_into(x).map_err(|_| {
415                            FieldValueError::ConversionError(
416                                format!("{:?}", x),
417                                stringify!($target).to_string(),
418                            )
419                        })?)
420                    }
421                    FieldValue::Unsigned64(x) => {
422                        Ok(TryInto::<$target>::try_into(x).map_err(|_| {
423                            FieldValueError::ConversionError(
424                                format!("{:?}", x),
425                                stringify!($target).to_string(),
426                            )
427                        })?)
428                    }
429                    FieldValue::Float(x) => Ok(x as $target),
430                    _ => Err(FieldValueError::ConversionError(
431                        format!("{:?}", self),
432                        stringify!($target).to_string(),
433                    )),
434                }
435            }
436        }
437
438        impl TryInto<$target> for &FieldValue {
439            type Error = FieldValueError;
440
441            fn try_into(self) -> Result<$target, FieldValueError> {
442                match self {
443                    // EntityFieldType::Boolean(x) => Ok(x == 1 as $target),
444                    FieldValue::Signed8(x) => {
445                        Ok(TryInto::<$target>::try_into(*x).map_err(|_| {
446                            FieldValueError::ConversionError(
447                                format!("{:?}", x),
448                                stringify!($target).to_string(),
449                            )
450                        })?)
451                    }
452                    FieldValue::Signed16(x) => {
453                        Ok(TryInto::<$target>::try_into(*x).map_err(|_| {
454                            FieldValueError::ConversionError(
455                                format!("{:?}", x),
456                                stringify!($target).to_string(),
457                            )
458                        })?)
459                    }
460                    FieldValue::Signed32(x) => {
461                        Ok(TryInto::<$target>::try_into(*x).map_err(|_| {
462                            FieldValueError::ConversionError(
463                                format!("{:?}", x),
464                                stringify!($target).to_string(),
465                            )
466                        })?)
467                    }
468                    FieldValue::Signed64(x) => {
469                        Ok(TryInto::<$target>::try_into(*x).map_err(|_| {
470                            FieldValueError::ConversionError(
471                                format!("{:?}", x),
472                                stringify!($target).to_string(),
473                            )
474                        })?)
475                    }
476                    FieldValue::Unsigned8(x) => {
477                        Ok(TryInto::<$target>::try_into(*x).map_err(|_| {
478                            FieldValueError::ConversionError(
479                                format!("{:?}", x),
480                                stringify!($target).to_string(),
481                            )
482                        })?)
483                    }
484                    FieldValue::Unsigned16(x) => {
485                        Ok(TryInto::<$target>::try_into(*x).map_err(|_| {
486                            FieldValueError::ConversionError(
487                                format!("{:?}", x),
488                                stringify!($target).to_string(),
489                            )
490                        })?)
491                    }
492                    FieldValue::Unsigned32(x) => {
493                        Ok(TryInto::<$target>::try_into(*x).map_err(|_| {
494                            FieldValueError::ConversionError(
495                                format!("{:?}", x),
496                                stringify!($target).to_string(),
497                            )
498                        })?)
499                    }
500                    FieldValue::Unsigned64(x) => {
501                        Ok(TryInto::<$target>::try_into(*x).map_err(|_| {
502                            FieldValueError::ConversionError(
503                                format!("{:?}", x),
504                                stringify!($target).to_string(),
505                            )
506                        })?)
507                    }
508                    FieldValue::Float(x) => Ok(*x as $target),
509                    _ => Err(FieldValueError::ConversionError(
510                        format!("{:?}", self),
511                        stringify!($target).to_string(),
512                    )),
513                }
514            }
515        }
516    };
517}
518
519impl_try_into_for_integers!(i8);
520impl_try_into_for_integers!(i16);
521impl_try_into_for_integers!(i32);
522impl_try_into_for_integers!(i64);
523impl_try_into_for_integers!(i128);
524impl_try_into_for_integers!(u8);
525impl_try_into_for_integers!(u16);
526impl_try_into_for_integers!(u32);
527impl_try_into_for_integers!(u64);
528impl_try_into_for_integers!(u128);
529impl_try_into_for_integers!(usize);
530impl_try_into_for_integers!(isize);
531
532#[allow(dead_code)]
533impl FieldValue {
534    #[inline]
535    pub(crate) fn as_string(&self) -> String {
536        if let FieldValue::String(s) = self {
537            s.to_string()
538        } else {
539            panic!("Tried to read as String, Found {:?}", self);
540        }
541    }
542
543    #[inline]
544    pub(crate) fn as_bool(&self) -> bool {
545        if let FieldValue::Boolean(b) = self {
546            *b
547        } else {
548            panic!("Tried to read as Boolean, Found {:?}", self);
549        }
550    }
551
552    #[inline]
553    pub(crate) fn as_float(&self) -> f32 {
554        if let FieldValue::Float(f) = self {
555            *f
556        } else {
557            panic!("Tried to read as Float, Found {:?}", self);
558        }
559    }
560
561    #[inline]
562    pub(crate) fn as_vector2d(&self) -> &[f32; 2] {
563        if let FieldValue::Vector2D(v) = self {
564            v
565        } else {
566            panic!("Tried to read as Vector2D, Found {:?}", self);
567        }
568    }
569
570    #[inline]
571    pub(crate) fn as_vector(&self) -> &[f32; 3] {
572        if let FieldValue::Vector3D(v) = self {
573            v
574        } else {
575            panic!("Tried to read as Vector3D, Found {:?}", self);
576        }
577    }
578
579    #[inline]
580    pub(crate) fn as_vector4d(&self) -> &[f32; 4] {
581        if let FieldValue::Vector4D(v) = self {
582            v
583        } else {
584            panic!("Tried to read as Vector4D, Found {:?}", self);
585        }
586    }
587}