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