1use std::collections::HashMap;
2use std::convert::{TryFrom, TryInto};
3use std::fmt;
4
5use super::functions;
6use super::QueryError;
7use dw_models::Event;
8use dw_transform::classify::{RegexRule, Rule};
9
10use serde::{Serialize, Serializer};
11use serde_json::value::Value;
12use serde_json::Number;
13
14#[derive(Clone, Serialize)]
17#[serde(untagged)]
18pub enum DataType {
19 None(),
20 Bool(bool),
21 Number(f64),
22 String(String),
23 Event(Event),
24 List(Vec<DataType>),
25 Dict(HashMap<String, DataType>),
26 #[serde(serialize_with = "serialize_function")]
27 Function(String, functions::QueryFn),
28}
29
30#[allow(clippy::trivially_copy_pass_by_ref)]
31fn serialize_function<S>(
32 _element: &str,
33 _fun: &functions::QueryFn,
34 _serializer: S,
35) -> Result<S::Ok, S::Error>
36where
37 S: Serializer,
38{
39 panic!("Query function was unevaluated and was attempted to be serialized, panic!");
40 }
42
43impl fmt::Debug for DataType {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 match self {
49 DataType::None() => write!(f, "None()"),
50 DataType::Bool(b) => write!(f, "Bool({})", b),
51 DataType::Number(n) => write!(f, "Number({})", n),
52 DataType::String(s) => write!(f, "String({})", s),
53 DataType::Event(e) => write!(f, "Event({:?})", e),
54 DataType::List(l) => write!(f, "List({:?})", l),
55 DataType::Dict(d) => write!(f, "Dict({:?})", d),
56 DataType::Function(name, _fun) => write!(f, "Function({})", name),
57 }
58 }
59}
60
61impl DataType {
64 pub fn query_eq(&self, other: &DataType) -> Result<bool, QueryError> {
65 match (self, other) {
66 (DataType::None(), DataType::None()) => Ok(false),
68 (DataType::Bool(b1), DataType::Bool(b2)) => Ok(b1 == b2),
69 (DataType::Number(n1), DataType::Number(n2)) => Ok(n1 == n2),
70 (DataType::String(s1), DataType::String(s2)) => Ok(s1 == s2),
71 (DataType::Event(e1), DataType::Event(e2)) => Ok(e1 == e2),
72 (DataType::List(l1), DataType::List(l2)) => Ok(l1 == l2),
73 (DataType::Dict(d1), DataType::Dict(d2)) => Ok(d1 == d2),
74 _ => Err(QueryError::InvalidType(format!(
76 "Cannot compare values of different types {:?} and {:?}",
77 self, other
78 ))),
79 }
80 }
81}
82
83impl PartialEq for DataType {
85 fn eq(&self, other: &DataType) -> bool {
86 match (self, other) {
87 (DataType::None(), DataType::None()) => true,
88 (DataType::Bool(b1), DataType::Bool(b2)) => b1 == b2,
90 (DataType::Number(n1), DataType::Number(n2)) => n1 == n2,
91 (DataType::String(s1), DataType::String(s2)) => s1 == s2,
92 (DataType::Event(e1), DataType::Event(e2)) => e1 == e2,
93 (DataType::List(l1), DataType::List(l2)) => l1 == l2,
94 (DataType::Dict(d1), DataType::Dict(d2)) => d1 == d2,
95 _ => false,
97 }
98 }
99}
100
101impl TryFrom<&DataType> for Vec<DataType> {
102 type Error = QueryError;
103 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
104 match value {
105 DataType::List(ref s) => Ok(s.clone()),
106 ref invalid_type => Err(QueryError::InvalidFunctionParameters(format!(
107 "Expected function parameter of type List, got {:?}",
108 invalid_type
109 ))),
110 }
111 }
112}
113
114impl TryFrom<&DataType> for String {
115 type Error = QueryError;
116 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
117 match value {
118 DataType::String(s) => Ok(s.clone()),
119 ref invalid_type => Err(QueryError::InvalidFunctionParameters(format!(
120 "Expected function parameter of type String, list contains {:?}",
121 invalid_type
122 ))),
123 }
124 }
125}
126
127impl TryFrom<&DataType> for Vec<String> {
128 type Error = QueryError;
129 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
130 let mut tagged_strings: Vec<DataType> = value.try_into()?;
131 let mut strings = Vec::new();
132 for string in tagged_strings.drain(..) {
133 let s: String = (&string).try_into()?;
134 strings.push(s);
135 }
136 Ok(strings)
137 }
138}
139
140impl TryFrom<&DataType> for Vec<Event> {
141 type Error = QueryError;
142 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
143 let mut tagged_events: Vec<DataType> = value.try_into()?;
144 let mut events = Vec::new();
145 for event in tagged_events.drain(..) {
146 match event {
147 DataType::Event(e) => events.push(e.clone()),
148 ref invalid_type => {
149 return Err(QueryError::InvalidFunctionParameters(format!(
150 "Expected function parameter of type List of Events, list contains {:?}",
151 invalid_type
152 )))
153 }
154 }
155 }
156 Ok(events)
157 }
158}
159
160impl TryFrom<&DataType> for Vec<(String, Rule)> {
161 type Error = QueryError;
162 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
163 let mut tagged_lists: Vec<DataType> = value.try_into()?;
164 let mut lists: Vec<(String, Rule)> = Vec::new();
165 for list in tagged_lists.drain(..) {
166 match list {
167 DataType::List(ref l) => {
168 let tag: String = match l.get(0) {
169 Some(tag) => tag.try_into()?,
170 None => return Err(QueryError::InvalidFunctionParameters(
171 format!("Expected function parameter of type list of (tag, rule) tuples, list contains {:?}", l)))
172 };
173 let rule: Rule = match l.get(1) {
174 Some(rule) => rule.try_into()?,
175 None => return Err(QueryError::InvalidFunctionParameters(
176 format!("Expected function parameter of type list of (tag, rule) tuples, list contains {:?}", l)))
177 };
178 lists.push((tag, rule));
179 }
180 ref invalid_type => {
181 return Err(QueryError::InvalidFunctionParameters(format!(
182 "Expected function parameter of type list of (tag, rule) tuples, got {:?}",
183 invalid_type
184 )))
185 }
186 }
187 }
188 Ok(lists)
189 }
190}
191
192impl TryFrom<&DataType> for Vec<(Vec<String>, Rule)> {
193 type Error = QueryError;
194 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
195 let mut tagged_lists: Vec<DataType> = value.try_into()?;
196 let mut lists: Vec<(Vec<String>, Rule)> = Vec::new();
197 for list in tagged_lists.drain(..) {
198 match list {
199 DataType::List(ref l) => {
200 let category: Vec<String> = match l.get(0) {
201 Some(category) => category.try_into()?,
202 None => return Err(QueryError::InvalidFunctionParameters(
203 format!("Expected function parameter of type list of (category, rule) tuples, list contains {:?}", l)))
204 };
205 let rule: Rule = match l.get(1) {
206 Some(rule) => rule.try_into()?,
207 None => return Err(QueryError::InvalidFunctionParameters(
208 format!("Expected function parameter of type list of (category, rule) tuples, list contains {:?}", l)))
209 };
210 lists.push((category, rule));
211 }
212 ref invalid_type => {
213 return Err(QueryError::InvalidFunctionParameters(format!(
214 "Expected function parameter of type list of (category, rule) tuples, got {:?}",
215 invalid_type
216 )))
217 }
218 }
219 }
220 Ok(lists)
221 }
222}
223
224impl TryFrom<&DataType> for f64 {
225 type Error = QueryError;
226 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
227 match value {
228 DataType::Number(f) => Ok(*f),
229 ref invalid_type => Err(QueryError::InvalidFunctionParameters(format!(
230 "Expected function parameter of type Number, got {:?}",
231 invalid_type
232 ))),
233 }
234 }
235}
236
237impl TryFrom<&DataType> for usize {
238 type Error = QueryError;
239 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
240 let f: f64 = value.try_into()?;
241 Ok(f as usize)
242 }
243}
244
245impl TryFrom<&DataType> for Value {
246 type Error = QueryError;
247 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
248 match value {
249 DataType::None() => Ok(Value::Null),
250 DataType::Bool(b) => Ok(Value::Bool(*b)),
251 DataType::Number(n) => Ok(Value::Number(Number::from_f64(*n).unwrap())),
252 DataType::String(s) => Ok(Value::String(s.to_string())),
253 DataType::List(_l) => {
254 let mut tagged_values: Vec<DataType> = value.try_into()?;
255 let mut values: Vec<Value> = Vec::new();
256 for value in tagged_values.drain(..) {
257 values.push((&value).try_into()?);
258 }
259 Ok(Value::Array(values))
260 }
261 ref invalid_type => Err(QueryError::InvalidFunctionParameters(format!(
262 "Query2 support for parsing values is limited, does not support parsing {:?}",
263 invalid_type
264 ))),
265 }
266 }
267}
268
269impl TryFrom<&DataType> for Vec<Value> {
270 type Error = QueryError;
271 fn try_from(value: &DataType) -> Result<Self, Self::Error> {
272 let mut tagged_values: Vec<DataType> = value.try_into()?;
273 let mut values: Vec<Value> = Vec::new();
274 for value in tagged_values.drain(..) {
275 values.push((&value).try_into()?);
276 }
277 Ok(values)
278 }
279}
280
281impl TryFrom<&DataType> for Rule {
282 type Error = QueryError;
283
284 fn try_from(data: &DataType) -> Result<Self, Self::Error> {
285 let obj = match data {
286 DataType::Dict(dict) => dict,
287 _ => {
288 return Err(QueryError::InvalidFunctionParameters(format!(
289 "Expected rule dict, got {:?}",
290 data
291 )))
292 }
293 };
294 let rtype_val = match obj.get("type") {
295 Some(rtype) => rtype,
296 None => {
297 return Err(QueryError::InvalidFunctionParameters(
298 "rule does not have a type".to_string(),
299 ))
300 }
301 };
302 let rtype = match rtype_val {
303 DataType::String(s) => s,
304 _ => {
305 return Err(QueryError::InvalidFunctionParameters(
306 "rule type is not a string".to_string(),
307 ))
308 }
309 };
310 if rtype == "none" {
311 Ok(Self::None)
312 } else if rtype == "regex" {
313 let regex_val = match obj.get("regex") {
314 Some(regex_val) => regex_val,
315 None => {
316 return Err(QueryError::InvalidFunctionParameters(
317 "regex rule is missing the 'regex' field".to_string(),
318 ))
319 }
320 };
321 let regex_str = match regex_val {
322 DataType::String(s) => s,
323 _ => {
324 return Err(QueryError::InvalidFunctionParameters(
325 "the regex field of the regex rule is not a string".to_string(),
326 ))
327 }
328 };
329 let ignore_case_val = match obj.get("ignore_case") {
330 Some(case_val) => case_val,
331 None => &DataType::Bool(false),
332 };
333 let ignore_case = match ignore_case_val {
334 DataType::Bool(b) => b,
335 _ => {
336 return Err(QueryError::InvalidFunctionParameters(
337 "the ignore_case field of the regex rule is not a bool".to_string(),
338 ))
339 }
340 };
341 let regex_rule = match RegexRule::new(regex_str, *ignore_case) {
342 Ok(regex_rule) => regex_rule,
343 Err(err) => {
344 return Err(QueryError::RegexCompileError(format!(
345 "Failed to compile regex string '{}': '{:?}",
346 regex_str, err
347 )))
348 }
349 };
350 Ok(Self::Regex(regex_rule))
351 } else {
352 Err(QueryError::InvalidFunctionParameters(format!(
353 "Unknown rule type '{}'",
354 rtype
355 )))
356 }
357 }
358}