1use std::collections::HashMap;
2
3#[cfg(feature = "python")]
4mod python;
5
6mod basic_operation;
7mod deserializer;
8mod extract;
9mod from;
10mod operators;
11mod utils;
12pub use smartstring::alias::String;
13
14#[derive(Debug, Clone, Default)]
17pub enum DataValue {
18 String(String),
19 Bytes(Vec<u8>),
20 U8(u8),
21 Bool(bool),
22 I32(i32),
23 U32(u32),
24 I64(i64),
25 U64(u64),
26 I128(i128),
27 U128(u128),
28 F32(f32),
29 F64(f64),
30 Map(HashMap<String, DataValue>),
31 Vec(Vec<DataValue>),
32 EnumNumber(i32),
33 #[default]
34 Null,
35}
36
37impl std::fmt::Display for DataValue {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 use DataValue::*;
40 match self {
41 Bool(i) => write!(f, "{}", i),
42 U32(i) => write!(f, "{}", i),
43 I32(i) => write!(f, "{}", i),
44 U8(i) => write!(f, "{}", i),
45 U64(i) => write!(f, "{}", i),
46 I64(i) => write!(f, "{}", i),
47 F32(i) => write!(f, "{}", i),
48 F64(i) => write!(f, "{}", i),
49 U128(i) => write!(f, "{}", i),
50 I128(i) => write!(f, "{}", i),
51 String(i) => write!(f, "{}", i),
52 Bytes(i) => write!(f, "{}", std::string::String::from_utf8_lossy(i)),
53 Null => write!(f, "null",),
54 Vec(i) => write!(f, "{:?}", i),
55 EnumNumber(i) => write!(f, "{:?}", i),
56 Map(i) => write!(f, "{:?}", i),
57 }
58 }
59}
60impl DataValue {
61 pub fn extract<T>(&self) -> T
62 where
63 T: Extract,
64 {
65 T::extract(self)
66 }
67
68 pub fn extract_bytes(&self) -> Vec<u8> {
69 match self {
70 DataValue::Bytes(i) => i.to_vec(),
71 _ => vec![],
72 }
73 }
74}
75
76pub trait Extract {
77 fn extract(v: &DataValue) -> Self;
78}
79
80impl DataValue {
81 pub fn contains(&self, other: &str) -> bool {
82 match self {
83 DataValue::Vec(v) => v.iter().any(|x| x.contains(other)),
84 DataValue::Map(v) => v.keys().any(|x| x.contains(other)),
85 DataValue::String(v) => v.contains(other),
86 _ => false,
87 }
88 }
89}
90
91pub fn convert<D: Extract>(data: &[DataValue]) -> Vec<D> {
92 let mut result = Vec::with_capacity(data.len());
93 for d in data {
94 result.push(D::extract(d));
95 }
96 result
97}
98
99#[macro_export]
100macro_rules! datavalue {
101
102 ($(vec![$($value:expr),*]),*) => {
104 $crate::datavalue!($([$($value),*]),*)
105 };
106
107 ($([$($value:expr),*]),*) => {
109 {
110 $(
111 let mut _vec = Vec::new();
112 $(
113 _vec.push($crate::DataValue::from($value));
114 )*
115 $crate::DataValue::Vec(_vec)
116 )*
117 }
118 };
119 ($($key:expr => $value:expr,)+) => { $crate::datavalue!($($key => $value),+) };
121 ($($key:expr => vec![$($value:expr),*]),*) => {
123 $crate::datavalue!($($key => [$($value),*]),*)
124 };
125 ($($key:expr => [$($value:expr),*]),*) => {
127 {
128 let mut _map = ::std::collections::HashMap::new();
129 $(
130 let mut _arr = Vec::new();
131 $(
132 _arr.push($value.into());
133 )*
134 _map.insert($key.into(), $crate::DataValue::Vec(_arr));
135 )*
136 $crate::DataValue::Map(_map)
137 }
138 };
139 ($($key:expr => $value:expr),*) => {
141 {
142 let mut _map = ::std::collections::HashMap::new();
143 $(
144 _map.insert($key.into(), $value.into());
145 )*
146 $crate::DataValue::Map(_map)
147 }
148 };
149 ($value:expr) => {
151 $crate::DataValue::from($value)
152 };
153}
154#[cfg(test)]
155mod test {
156 use std::fmt::Debug;
157
158 use super::*;
159 use rstest::*;
160
161 #[test]
162 fn from_json_object_to_datavalue() {
163 let value = DataValue::from(&serde_json::json!(12));
164 assert_eq!(value, DataValue::I64(12));
165
166 let value = DataValue::from(&serde_json::json!(12.0));
167 assert_eq!(value, DataValue::F64(12.0));
168
169 let value = DataValue::from(&serde_json::json!("12"));
170 assert_eq!(value, DataValue::String("12".into()));
171
172 let value = DataValue::from(&serde_json::json!(true));
173 assert_eq!(value, DataValue::Bool(true));
174
175 let value = DataValue::from(&serde_json::json!(false));
176 assert_eq!(value, DataValue::Bool(false));
177
178 let value = DataValue::from(&serde_json::json!(null));
179 assert_eq!(value, DataValue::Null);
180 }
181
182 #[test]
183 fn from_native_to_datavalue() {
184 let value = DataValue::from(12u32);
185 assert_eq!(value, DataValue::U32(12));
186
187 let value = DataValue::from(12.0f64);
188 assert_eq!(value, DataValue::F64(12.0));
189
190 let value = DataValue::from("12");
191 assert_eq!(value, DataValue::String("12".into()));
192
193 let value = DataValue::from(true);
194 assert_eq!(value, DataValue::Bool(true));
195
196 let value = DataValue::from(false);
197 assert_eq!(value, DataValue::Bool(false));
198
199 let value = DataValue::from(());
200 assert_eq!(value, DataValue::Null);
201 }
202
203 #[rstest]
204 #[case(DataValue::U32(12), 12u32)]
205 #[case(DataValue::I32(12), 12i32)]
206 #[case(DataValue::U8(12), 12u8)]
207 #[case(DataValue::U64(12), 12u64)]
208 #[case(DataValue::I64(12), 12i64)]
209 #[case(DataValue::F32(12.0), 12f32)]
210 #[case(DataValue::F64(12.0), 12f64)]
211 #[case(DataValue::U128(12), 12u128)]
212 #[case(DataValue::I128(12), 12i128)]
213 #[case(DataValue::String("12".into()), "12".to_string())]
214 #[case(DataValue::Bool(true), true)]
215 #[case(DataValue::Bool(false), false)]
216 fn as_data_value_test<T: PartialEq + std::fmt::Debug + Into<DataValue> + Extract>(
217 #[case] value: DataValue,
218 #[case] expected: T,
219 ) {
220 assert_eq!(value.extract::<T>(), expected);
221 assert_eq!(value, expected.into());
222 }
223
224 #[rstest]
225 #[case(DataValue::Bytes("12".as_bytes().to_vec()), "12".as_bytes().to_vec())]
226 fn as_data_value_test_bytes(#[case] value: DataValue, #[case] expected: Vec<u8>) {
227 assert_eq!(value.extract_bytes(), expected);
228 }
229
230 #[rstest]
231 #[case(DataValue::U32(12), DataValue::U32(12), true)]
232 #[case(DataValue::I32(12), DataValue::I32(12), true)]
233 #[case(DataValue::U8(12), DataValue::U8(12), true)]
234 #[case(DataValue::U64(12), DataValue::U64(12), true)]
235 #[case(DataValue::I64(12), DataValue::I64(12), true)]
236 #[case(DataValue::F32(12.0), DataValue::F32(12.0), true)]
237 #[case(DataValue::F64(12.0), DataValue::F64(12.0), true)]
238 #[case(DataValue::U128(12), DataValue::U128(12), true)]
239 #[case(DataValue::I128(12), DataValue::I128(12), true)]
240 #[case(DataValue::String("12".into()), DataValue::String("12".into()), true)]
241 #[case(DataValue::Bytes("12".as_bytes().to_vec()), DataValue::Bytes("12".as_bytes().to_vec()), true)]
242 #[case(DataValue::Bool(true), DataValue::Bool(true), true)]
243 #[case(DataValue::Bool(false), DataValue::Bool(false), true)]
244 fn eq_test(#[case] value: DataValue, #[case] other: DataValue, #[case] expected: bool) {
245 assert_eq!(value == other, expected);
246 print!("{} == {} = {}", value, other, expected);
247 }
248
249 #[rstest]
250 #[case(
251 crate::datavalue!(1u32),
252 DataValue::U32(1),
253 vec![1u32]
254 )]
255 #[case(
256 crate::datavalue!(vec![1u32, 2u32]),
257 DataValue::Vec(vec![DataValue::U32(1), DataValue::U32(2)]),
258 vec![vec![1u32, 2u32]]
259 )]
260 fn convert_test<T: Extract + PartialEq + Debug>(
261 #[case] value: DataValue,
262 #[case] expected: DataValue,
263 #[case] expected_native: Vec<T>,
264 ) {
265 assert_eq!(value, expected);
266 let converted: Vec<T> = convert::<T>(&[value]);
267 assert_eq!(converted, expected_native);
268 }
269}