1use super::{DataValue, Extract};
2
3macro_rules! impl_extract_nums {
4 ($($t:ty),*) => {
5 $(
6 impl Extract for $t {
7 #[inline]
8 fn extract(v: &DataValue) -> $t {
9 use DataValue::*;
10 match v {
11 Bool(b) => (if b == &true { 1 } else { 0 }) as $t,
12 U32(i) => *i as $t,
13 I32(i) => *i as $t,
14 U8(i) => *i as $t,
15 U64(i) => *i as $t,
16 I64(i) => *i as $t,
17 F32(i) => *i as $t,
18 F64(i) => *i as $t,
19 U128(i) => *i as $t,
20 I128(i) => *i as $t,
21 EnumNumber(i) => *i as $t,
22 _ => 0 as $t,
23 }
24 }
25 }
26 )*
27 };
28}
29
30impl_extract_nums!(u32, u64, i32, i64, f32, f64, u128, i128);
31impl Extract for u8 {
32 fn extract(v: &DataValue) -> u8 {
33 use DataValue::*;
34 match v {
35 U8(i) => *i,
36 _ => 0,
37 }
38 }
39}
40
41impl Extract for bool {
42 fn extract(v: &DataValue) -> bool {
43 match v {
44 DataValue::Bool(i) => *i,
45 DataValue::U8(i) => *i != 0,
46 DataValue::U32(i) => *i != 0,
47 DataValue::I32(i) => *i != 0,
48 DataValue::U64(i) => *i != 0,
49 DataValue::I64(i) => *i != 0,
50 DataValue::F32(i) => *i != 0.,
51 DataValue::F64(i) => *i != 0.,
52 _ => false,
53 }
54 }
55}
56
57impl Extract for String {
58 fn extract(v: &DataValue) -> String {
59 match v {
60 DataValue::String(i) => i.to_string(),
61 v => format!("{v}"),
62 }
63 }
64}
65
66impl<T> Extract for Vec<T>
67where
68 T: Extract,
69{
70 fn extract(v: &DataValue) -> Vec<T> {
71 use DataValue::*;
72 match v {
73 Vec(i) => i.iter().map(|x| T::extract(x)).collect(),
74 _ => vec![],
75 }
76 }
77}
78
79impl<V> Extract for std::collections::HashMap<smartstring::alias::String, V>
80where
81 V: Extract,
82{
83 fn extract(v: &DataValue) -> std::collections::HashMap<smartstring::alias::String, V> {
84 use DataValue::*;
85 match v {
86 Map(i) => i.iter().map(|(k, v)| (k.clone(), V::extract(v))).collect(),
87 _ => Default::default(),
88 }
89 }
90}
91
92#[cfg(test)]
93mod test {
94 use super::*;
95 use rstest::*;
96
97 #[rstest]
98 #[case(DataValue::U8(1), 1)]
99 #[case(DataValue::U32(1), 1)]
100 #[case(DataValue::I32(1), 1)]
101 #[case(DataValue::U64(1), 1)]
102 #[case(DataValue::I64(1), 1)]
103 #[case(DataValue::F32(1.0), 1)]
104 #[case(DataValue::F64(1.0), 1)]
105 #[case(DataValue::U128(1), 1)]
106 #[case(DataValue::I128(1), 1)]
107 #[case(DataValue::EnumNumber(1), 1)]
108 #[case(DataValue::Bool(true), 1)]
109 #[case(DataValue::Bool(false), 0)]
110 #[case(DataValue::String("1".into()), 0)]
111 fn test_extract_num(#[case] input: DataValue, #[case] expected: u32) {
112 assert_eq!(u32::extract(&input), expected);
113 }
114
115 #[rstest]
116 #[case(DataValue::U8(1), "1")]
117 #[case(DataValue::U32(1), "1")]
118 #[case(DataValue::I32(1), "1")]
119 #[case(DataValue::U64(1), "1")]
120 #[case(DataValue::I64(1), "1")]
121 #[case(DataValue::F32(1.1), "1.1")]
122 #[case(DataValue::F64(1.1), "1.1")]
123 #[case(DataValue::U128(1), "1")]
124 #[case(DataValue::I128(1), "1")]
125 #[case(DataValue::EnumNumber(1), "1")]
126 #[case(DataValue::Bool(true), "true")]
127 #[case(DataValue::Bool(false), "false")]
128 #[case(DataValue::String("1".into()), "1")]
129 fn test_extract_string(#[case] input: DataValue, #[case] expected: &str) {
130 assert_eq!(String::extract(&input), expected.to_string());
131 }
132 #[rstest]
133 #[case(DataValue::U8(1), 1)]
134 #[case(DataValue::U32(1), 1)]
135 #[case(DataValue::I32(1), 1)]
136 #[case(DataValue::U64(1), 1)]
137 #[case(DataValue::I64(1), 1)]
138 #[case(DataValue::F32(1.0), 1)]
139 #[case(DataValue::F64(1.0), 1)]
140 #[case(DataValue::U128(1), 1)]
141 #[case(DataValue::I128(1), 1)]
142 #[case(DataValue::EnumNumber(1), 1)]
143 #[case(DataValue::Bool(true), 1)]
144 #[case(DataValue::Bool(false), 0)]
145 #[case(DataValue::String("1".into()), 0)]
146 fn test_extract_u64(#[case] input: DataValue, #[case] expected: u64) {
147 assert_eq!(u64::extract(&input), expected);
148 }
149
150 #[rstest]
151 #[case(DataValue::U8(1), 1)]
152 #[case(DataValue::U32(1), 1)]
153 #[case(DataValue::I32(1), 1)]
154 #[case(DataValue::U64(1), 1)]
155 #[case(DataValue::I64(1), 1)]
156 #[case(DataValue::F32(1.0), 1)]
157 #[case(DataValue::F64(1.0), 1)]
158 #[case(DataValue::U128(1), 1)]
159 #[case(DataValue::I128(1), 1)]
160 #[case(DataValue::EnumNumber(1), 1)]
161 #[case(DataValue::Bool(true), 1)]
162 #[case(DataValue::Bool(false), 0)]
163 #[case(DataValue::String("1".into()), 0)]
164 fn test_extract_i32(#[case] input: DataValue, #[case] expected: i32) {
165 assert_eq!(i32::extract(&input), expected);
166 }
167
168 #[rstest]
169 #[case(DataValue::U8(1), 1)]
170 #[case(DataValue::U32(1), 1)]
171 #[case(DataValue::I32(1), 1)]
172 #[case(DataValue::U64(1), 1)]
173 #[case(DataValue::I64(1), 1)]
174 #[case(DataValue::F32(1.0), 1)]
175 #[case(DataValue::F64(1.0), 1)]
176 #[case(DataValue::U128(1), 1)]
177 #[case(DataValue::I128(1), 1)]
178 #[case(DataValue::EnumNumber(1), 1)]
179 #[case(DataValue::Bool(true), 1)]
180 #[case(DataValue::Bool(false), 0)]
181 #[case(DataValue::String("1".into()), 0)]
182 fn test_extract_i64(#[case] input: DataValue, #[case] expected: i64) {
183 assert_eq!(i64::extract(&input), expected);
184 }
185
186 #[rstest]
187 #[case(DataValue::U8(1), 1f64)]
188 #[case(DataValue::U32(1), 1f64)]
189 #[case(DataValue::I32(1), 1f64)]
190 #[case(DataValue::U64(1), 1f64)]
191 #[case(DataValue::I64(1), 1f64)]
192 #[case(DataValue::F32(1.0), 1f64)]
193 #[case(DataValue::F64(1.0), 1f64)]
194 #[case(DataValue::U128(1), 1f64)]
195 #[case(DataValue::I128(1), 1f64)]
196 #[case(DataValue::EnumNumber(1), 1f64)]
197 #[case(DataValue::Bool(true), 1f64)]
198 #[case(DataValue::Bool(false), 0f64)]
199 #[case(DataValue::String("1".into()), 0f64)]
200 fn test_extract_f64(#[case] input: DataValue, #[case] expected: f64) {
201 assert_eq!(f64::extract(&input), expected);
202 }
203
204 #[rstest]
205 #[case(DataValue::U8(1), 1f32)]
206 #[case(DataValue::U32(1), 1f32)]
207 #[case(DataValue::I32(1), 1f32)]
208 #[case(DataValue::U64(1), 1f32)]
209 #[case(DataValue::I64(1), 1f32)]
210 #[case(DataValue::F32(1.0), 1f32)]
211 #[case(DataValue::F64(1.0), 1f32)]
212 #[case(DataValue::U128(1), 1f32)]
213 #[case(DataValue::I128(1), 1f32)]
214 #[case(DataValue::EnumNumber(1), 1f32)]
215 #[case(DataValue::Bool(true), 1f32)]
216 #[case(DataValue::Bool(false), 0f32)]
217 #[case(DataValue::String("1".into()), 0f32)]
218 #[case(DataValue::Null, 0f32)]
219 fn test_extract_f32(#[case] input: DataValue, #[case] expected: f32) {
220 assert_eq!(f32::extract(&input), expected);
221 }
222
223 #[rstest]
224 #[case(DataValue::Vec(vec![1.into()]), vec![1])]
225 #[case(DataValue::Vec(vec![1.into(), 2.into()]), vec![1, 2])]
226 #[case(DataValue::Vec(vec![1.into(), 2.into(), 3.into()]), vec![1, 2, 3])]
227 fn test_extract_vec(#[case] input: DataValue, #[case] expected: Vec<u32>) {
228 assert_eq!(Vec::<u32>::extract(&input), expected);
229 }
230
231 #[rstest]
232 #[case(DataValue::Map(crate::stdhashmap!("a" => 1)), crate::stdhashmap!("a" => 1))]
233 #[case(DataValue::Map(crate::stdhashmap!("a" => 1, "b" => 2)), crate::stdhashmap!("a" => 1, "b" => 2))]
234 #[case(DataValue::Map(crate::stdhashmap!("a" => 1, "b" => 2, "c" => 3)), crate::stdhashmap!("a" => 1, "b" => 2, "c" => 3))]
235 fn test_extract_map(
236 #[case] input: DataValue,
237 #[case] expected: std::collections::HashMap<smartstring::alias::String, i32>,
238 ) {
239 assert_eq!(
240 std::collections::HashMap::<smartstring::alias::String, i32>::extract(&input),
241 expected
242 );
243 }
244}