micromegas_transit/
value.rs

1use anyhow::{Result, bail};
2use std::sync::Arc;
3
4#[derive(Debug, Clone)]
5pub struct Object {
6    pub type_name: Arc<String>,
7    pub members: Vec<(Arc<String>, Value)>,
8}
9
10impl Object {
11    pub fn get<T>(&self, member_name: &str) -> Result<T>
12    where
13        T: TransitValue,
14    {
15        for m in &self.members {
16            if *m.0 == member_name {
17                return T::get(&m.1);
18            }
19        }
20        bail!("member {} not found in {:?}", member_name, self);
21    }
22
23    pub fn get_ref(&self, member_name: &str) -> Result<&Value> {
24        for m in &self.members {
25            if *m.0 == member_name {
26                return Ok(&m.1);
27            }
28        }
29        bail!("member {} not found", member_name);
30    }
31}
32
33pub trait TransitValue {
34    fn get(value: &Value) -> Result<Self>
35    where
36        Self: Sized;
37}
38
39impl TransitValue for u8 {
40    fn get(value: &Value) -> Result<Self> {
41        if let Value::U8(val) = value {
42            Ok(*val)
43        } else {
44            bail!("bad type cast u8 for value {:?}", value);
45        }
46    }
47}
48
49impl TransitValue for u32 {
50    fn get(value: &Value) -> Result<Self> {
51        match value {
52            Value::U32(val) => Ok(*val),
53            Value::U8(val) => Ok(Self::from(*val)),
54            _ => {
55                bail!("bad type cast u32 for value {:?}", value);
56            }
57        }
58    }
59}
60
61impl TransitValue for u64 {
62    fn get(value: &Value) -> Result<Self> {
63        match value {
64            Value::I64(val) => Ok(*val as Self),
65            Value::U64(val) => Ok(*val),
66            _ => {
67                bail!("bad type cast u64 for value {:?}", value)
68            }
69        }
70    }
71}
72
73impl TransitValue for i64 {
74    #[allow(clippy::cast_possible_wrap)]
75    fn get(value: &Value) -> Result<Self> {
76        match value {
77            Value::I64(val) => Ok(*val),
78            Value::U64(val) => Ok(*val as Self),
79            _ => {
80                bail!("bad type cast i64 for value {:?}", value)
81            }
82        }
83    }
84}
85
86impl TransitValue for f64 {
87    fn get(value: &Value) -> Result<Self> {
88        if let Value::F64(val) = value {
89            Ok(*val)
90        } else {
91            bail!("bad type cast f64 for value {:?}", value);
92        }
93    }
94}
95
96impl TransitValue for Arc<String> {
97    fn get(value: &Value) -> Result<Self> {
98        if let Value::String(val) = value {
99            Ok(val.clone())
100        } else {
101            bail!("bad type cast String for value {:?}", value);
102        }
103    }
104}
105
106impl TransitValue for Arc<Object> {
107    fn get(value: &Value) -> Result<Self> {
108        if let Value::Object(val) = value {
109            Ok(val.clone())
110        } else {
111            bail!("bad type cast String for value {:?}", value);
112        }
113    }
114}
115
116#[derive(Debug, Clone)]
117pub enum Value {
118    String(Arc<String>),
119    Object(Arc<Object>),
120    U8(u8),
121    U32(u32),
122    U64(u64),
123    I64(i64),
124    F64(f64),
125    None,
126}
127
128impl Value {
129    pub fn as_str(&self) -> Option<&str> {
130        if let Value::String(s) = &self {
131            Some(s.as_str())
132        } else {
133            None
134        }
135    }
136}