1use crate::basevalue::BaseValue;
2use crate::field::{FieldValue, MatchModifier, Modifier};
3use crate::wildcard::{match_tokenized, tokenize};
4use std::collections::HashMap;
5use std::hash::Hash;
6use std::net::IpAddr;
7use std::str::FromStr;
8
9#[cfg(feature = "serde_json")]
10#[derive(Debug, serde::Deserialize)]
11struct EventProxy {
12 #[serde(flatten)]
13 value: serde_json::Value,
14}
15
16#[derive(Debug, PartialEq)]
17pub enum EventValue {
18 Value(BaseValue),
19 Sequence(Vec<EventValue>),
20 Map(HashMap<String, EventValue>),
21}
22
23#[cfg(feature = "serde_json")]
24impl TryFrom<serde_json::Value> for EventValue {
25 type Error = crate::error::JSONError;
26
27 fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
28 match value {
29 serde_json::Value::Null
30 | serde_json::Value::Bool(_)
31 | serde_json::Value::Number(_)
32 | serde_json::Value::String(_) => Ok(Self::Value(BaseValue::try_from(value)?)),
33 serde_json::Value::Array(a) => {
34 let mut result = Vec::with_capacity(a.len());
35 for item in a {
36 result.push(Self::try_from(item)?);
37 }
38 Ok(Self::Sequence(result))
39 }
40 serde_json::Value::Object(data) => {
41 let mut result = HashMap::with_capacity(data.len());
42 for (key, value) in data {
43 result.insert(key, Self::try_from(value)?);
44 }
45 Ok(Self::Map(result))
46 }
47 }
48 }
49}
50
51impl EventValue {
52 pub fn value_to_string(&self) -> String {
54 match self {
55 Self::Value(v) => v.value_to_string(),
56 Self::Sequence(v) => {
57 let mut result = "[".to_string();
58 result.push_str(
59 v.iter()
60 .map(|v| v.value_to_string())
61 .collect::<Vec<String>>()
62 .join(", ")
63 .as_str(),
64 );
65 result.push(']');
66 result
67 }
68 Self::Map(m) => {
69 let mut result = "{".to_string();
70 result.push_str(
71 m.iter()
72 .map(|(k, v)| format!("{}: {}", k, v.value_to_string()))
73 .collect::<Vec<String>>()
74 .join(", ")
75 .as_str(),
76 );
77 result.push('}');
78 result
79 }
80 }
81 }
82
83 pub(crate) fn contains_keyword(&self, s: &str) -> bool {
84 match self {
85 Self::Value(v) => {
86 let tokens = tokenize(s, true);
89 match_tokenized(&tokens, v.value_to_string().as_str(), true)
90 }
91 Self::Sequence(seq) => seq.iter().any(|v| v.contains_keyword(s)),
92 Self::Map(m) => m.values().any(|v| v.contains_keyword(s)),
93 }
94 }
95
96 pub(crate) fn matches(&self, field_value: &FieldValue, modifier: &Modifier) -> bool {
97 match (&self, field_value) {
98 (Self::Value(target), FieldValue::Base(value)) => match modifier.match_modifier {
99 Some(MatchModifier::Contains) => match (target, value) {
101 (BaseValue::String(target), BaseValue::String(value)) => {
102 if modifier.cased {
103 target.contains(value)
104 } else {
105 target.to_lowercase().contains(&value.to_lowercase())
106 }
107 }
108 _ => false,
109 },
110 Some(MatchModifier::StartsWith) => match (target, value) {
111 (BaseValue::String(target), BaseValue::String(value)) => {
112 if modifier.cased {
113 target.starts_with(value)
114 } else {
115 target.to_lowercase().starts_with(&value.to_lowercase())
116 }
117 }
118 _ => false,
119 },
120 Some(MatchModifier::EndsWith) => match (target, value) {
121 (BaseValue::String(target), BaseValue::String(value)) => {
122 if modifier.cased {
123 target.ends_with(value)
124 } else {
125 target.to_lowercase().ends_with(&value.to_lowercase())
126 }
127 }
128 _ => false,
129 },
130
131 Some(MatchModifier::Gt) => target > value,
132 Some(MatchModifier::Gte) => target >= value,
133 Some(MatchModifier::Lt) => target < value,
134 Some(MatchModifier::Lte) => target <= value,
135
136 Some(MatchModifier::Re) | Some(MatchModifier::Cidr) => false,
138
139 None => value == target,
141 },
142 (Self::Value(v), FieldValue::WildcardPattern(w)) => {
143 if let BaseValue::String(s) = v {
144 match_tokenized(w, s, !modifier.cased)
145 } else {
146 match_tokenized(w, v.value_to_string().as_str(), !modifier.cased)
147 }
148 }
149
150 (Self::Value(v), FieldValue::Regex(r)) => r.is_match(&v.value_to_string()),
151 (Self::Value(v), FieldValue::Cidr(c)) => {
152 if let BaseValue::String(s) = v {
153 match IpAddr::from_str(s) {
154 Ok(ip) => c.contains(&ip),
155 Err(_) => false,
156 }
157 } else {
158 false
159 }
160 }
161
162 (Self::Sequence(_), _) => false,
165 (Self::Map(_), _) => false,
166 }
167 }
168}
169
170impl<T> From<T> for EventValue
171where
172 T: Into<BaseValue>,
173{
174 fn from(value: T) -> Self {
175 Self::Value(value.into())
176 }
177}
178
179#[derive(Debug, Default)]
185#[cfg_attr(feature = "serde_json", derive(serde::Deserialize))]
186#[cfg_attr(feature = "serde_json", serde(try_from = "EventProxy"))]
187pub struct Event {
188 inner: HashMap<String, EventValue>,
189}
190
191#[cfg(feature = "serde_json")]
192impl TryFrom<EventProxy> for Event {
193 type Error = crate::error::JSONError;
194
195 fn try_from(other: EventProxy) -> Result<Self, Self::Error> {
196 Self::try_from(other.value)
197 }
198}
199
200impl<T, S, const N: usize> From<[(S, T); N]> for Event
201where
202 S: Into<String> + Hash + Eq,
203 T: Into<EventValue>,
204{
205 fn from(values: [(S, T); N]) -> Self {
206 let mut data = HashMap::with_capacity(N);
207 for (k, v) in values {
208 data.insert(k.into(), v.into());
209 }
210 Self { inner: data }
211 }
212}
213
214impl Event {
215 pub fn new() -> Self {
217 Self::default()
218 }
219
220 pub fn insert<T, S>(&mut self, key: S, value: T)
233 where
234 S: Into<String> + Hash + Eq,
235 T: Into<EventValue>,
236 {
237 self.inner.insert(key.into(), value.into());
238 }
239
240 pub fn iter(&self) -> impl Iterator<Item = (&String, &EventValue)> {
242 self.inner.iter()
243 }
244
245 pub fn get(&self, key: &str) -> Option<&EventValue> {
247 if let Some(ev) = self.inner.get(key) {
248 return Some(ev);
249 }
250
251 let mut nested_key = key;
252 let mut current = &self.inner;
253 while let Some((head, tail)) = nested_key.split_once('.') {
254 if let Some(EventValue::Map(map)) = current.get(head) {
255 if let Some(value) = map.get(tail) {
256 return Some(value);
257 }
258 current = map;
259 nested_key = tail;
260 } else {
261 return None;
262 }
263 }
264 None
265 }
266
267 pub fn values(&self) -> impl Iterator<Item = &EventValue> {
268 self.inner.values()
269 }
270}
271
272#[cfg(feature = "serde_json")]
273impl TryFrom<serde_json::Value> for Event {
274 type Error = crate::error::JSONError;
275
276 fn try_from(data: serde_json::Value) -> Result<Self, Self::Error> {
277 let mut result = Self::default();
278 match data {
279 serde_json::Value::Object(data) => {
280 for (key, value) in data {
281 result.insert(key, EventValue::try_from(value)?);
282 }
283 }
284 _ => return Err(Self::Error::InvalidEvent()),
285 }
286 Ok(result)
287 }
288}
289
290#[cfg(feature = "serde_json")]
291#[cfg(test)]
292mod tests {
293 use super::*;
294 use crate::wildcard::tokenize;
295 use serde_json::json;
296
297 #[test]
298 fn test_event_value_to_string() {
299 let event_value = EventValue::Value(BaseValue::String("test".to_string()));
300 assert_eq!(event_value.value_to_string(), "test");
301
302 let event_value = EventValue::Sequence(vec![
303 EventValue::Value(BaseValue::String("test".to_string())),
304 EventValue::Value(BaseValue::Int(42)),
305 ]);
306
307 assert_eq!(event_value.value_to_string(), "[test, 42]");
308
309 let event_value = EventValue::Map({
310 let mut map = HashMap::new();
311 map.insert(
312 "key".to_string(),
313 EventValue::Value(BaseValue::String("test".to_string())),
314 );
315 map.insert("number".to_string(), EventValue::Value(BaseValue::Int(42)));
316 map
317 });
318
319 assert!(
320 event_value.value_to_string() == "{key: test, number: 42}"
321 || event_value.value_to_string() == "{number: 42, key: test}"
322 );
323 }
324
325 #[test]
326 fn test_matches() {
327 let mut modifier = Modifier::default();
328
329 assert!(EventValue::from("zsh").matches(&FieldValue::from("zsh"), &modifier));
330 assert!(!EventValue::from("zsh").matches(&FieldValue::from("bash"), &modifier));
331
332 modifier.match_modifier = Some(MatchModifier::StartsWith);
333
334 assert!(EventValue::from("zsh").matches(&FieldValue::from("z"), &modifier));
335 assert!(!EventValue::from("zsh").matches(&FieldValue::from("sd"), &modifier));
336
337 modifier.match_modifier = Some(MatchModifier::EndsWith);
338 assert!(EventValue::from("zsh").matches(&FieldValue::from("sh"), &modifier));
339 assert!(!EventValue::from("zsh").matches(&FieldValue::from("sd"), &modifier));
340
341 modifier.match_modifier = Some(MatchModifier::Contains);
342 assert!(EventValue::from("zsh").matches(&FieldValue::from("s"), &modifier));
343 assert!(!EventValue::from("zsh").matches(&FieldValue::from("d"), &modifier));
344 }
345
346 #[test]
347 fn test_load_from_json() {
348 let event: Event = json!({
349 "name": "John Doe",
350 "age": 43,
351 "address": {
352 "city": "New York",
353 "state": "NY"
354 }
355 })
356 .try_into()
357 .unwrap();
358
359 assert_eq!(event.inner["name"], EventValue::from("John Doe"));
360 assert_eq!(event.inner["age"], EventValue::from(43));
361 assert_eq!(
362 event.inner["address"],
363 EventValue::Map({
364 let mut map = HashMap::new();
365 map.insert("city".to_string(), EventValue::from("New York"));
366 map.insert("state".to_string(), EventValue::from("NY"));
367 map
368 })
369 );
370 }
371
372 #[test]
373 fn test_wildcard_matches() {
374 let modifier = Modifier::default();
375 let wildcard = FieldValue::WildcardPattern(tokenize("4?", false));
376
377 assert!(EventValue::from("42").matches(&wildcard, &modifier));
378 assert!(EventValue::from(43).matches(&wildcard, &modifier));
379 assert!(EventValue::from(43u32).matches(&wildcard, &modifier));
380 assert!(!EventValue::from(53).matches(&wildcard, &modifier));
381 assert!(!EventValue::from(433).matches(&wildcard, &modifier));
382 assert!(!EventValue::from(None).matches(&wildcard, &modifier));
383
384 let wildcard = FieldValue::WildcardPattern(tokenize("f*", false));
385 assert!(EventValue::from(false).matches(&wildcard, &modifier));
386 assert!(!EventValue::from(true).matches(&wildcard, &modifier));
387 assert!(!EventValue::from(None).matches(&wildcard, &modifier));
388 }
389
390 #[test]
391 fn test_iter() {
392 let event = Event::from([("name", 2)]);
393 let mut event_iter = event.iter();
394 assert_eq!(
395 event_iter.next(),
396 Some((&"name".to_string(), &EventValue::from(2)))
397 );
398 assert_eq!(event_iter.next(), None);
399 }
400}