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(crate) fn contains_keyword(&self, s: &str) -> bool {
53 match self {
54 Self::Value(v) => {
55 let tokens = tokenize(s, true);
58 match_tokenized(&tokens, v.value_to_string().as_str(), true)
59 }
60 Self::Sequence(seq) => seq.iter().any(|v| v.contains_keyword(s)),
61 Self::Map(m) => m.values().any(|v| v.contains_keyword(s)),
62 }
63 }
64
65 pub(crate) fn matches(&self, field_value: &FieldValue, modifier: &Modifier) -> bool {
66 match (&self, field_value) {
67 (Self::Value(target), FieldValue::Base(value)) => match modifier.match_modifier {
68 Some(MatchModifier::Contains) => match (target, value) {
70 (BaseValue::String(target), BaseValue::String(value)) => {
71 if modifier.cased {
72 target.contains(value)
73 } else {
74 target.to_lowercase().contains(&value.to_lowercase())
75 }
76 }
77 _ => false,
78 },
79 Some(MatchModifier::StartsWith) => match (target, value) {
80 (BaseValue::String(target), BaseValue::String(value)) => {
81 if modifier.cased {
82 target.starts_with(value)
83 } else {
84 target.to_lowercase().starts_with(&value.to_lowercase())
85 }
86 }
87 _ => false,
88 },
89 Some(MatchModifier::EndsWith) => match (target, value) {
90 (BaseValue::String(target), BaseValue::String(value)) => {
91 if modifier.cased {
92 target.ends_with(value)
93 } else {
94 target.to_lowercase().ends_with(&value.to_lowercase())
95 }
96 }
97 _ => false,
98 },
99
100 Some(MatchModifier::Gt) => target > value,
101 Some(MatchModifier::Gte) => target >= value,
102 Some(MatchModifier::Lt) => target < value,
103 Some(MatchModifier::Lte) => target <= value,
104
105 Some(MatchModifier::Re) | Some(MatchModifier::Cidr) => false,
107
108 None => value == target,
110 },
111 (Self::Value(v), FieldValue::WildcardPattern(w)) => {
112 if let BaseValue::String(s) = v {
113 match_tokenized(w, s, !modifier.cased)
114 } else {
115 match_tokenized(w, v.value_to_string().as_str(), !modifier.cased)
116 }
117 }
118
119 (Self::Value(v), FieldValue::Regex(r)) => r.is_match(&v.value_to_string()),
120 (Self::Value(v), FieldValue::Cidr(c)) => {
121 if let BaseValue::String(s) = v {
122 match IpAddr::from_str(s) {
123 Ok(ip) => c.contains(&ip),
124 Err(_) => false,
125 }
126 } else {
127 false
128 }
129 }
130
131 (Self::Sequence(_), _) => false,
134 (Self::Map(_), _) => false,
135 }
136 }
137}
138
139impl<T> From<T> for EventValue
140where
141 T: Into<BaseValue>,
142{
143 fn from(value: T) -> Self {
144 Self::Value(value.into())
145 }
146}
147
148#[derive(Debug, Default)]
154#[cfg_attr(feature = "serde_json", derive(serde::Deserialize))]
155#[cfg_attr(feature = "serde_json", serde(try_from = "EventProxy"))]
156pub struct Event {
157 inner: HashMap<String, EventValue>,
158}
159
160#[cfg(feature = "serde_json")]
161impl TryFrom<EventProxy> for Event {
162 type Error = crate::error::JSONError;
163
164 fn try_from(other: EventProxy) -> Result<Self, Self::Error> {
165 Self::try_from(other.value)
166 }
167}
168
169impl<T, S, const N: usize> From<[(S, T); N]> for Event
170where
171 S: Into<String> + Hash + Eq,
172 T: Into<EventValue>,
173{
174 fn from(values: [(S, T); N]) -> Self {
175 let mut data = HashMap::with_capacity(N);
176 for (k, v) in values {
177 data.insert(k.into(), v.into());
178 }
179 Self { inner: data }
180 }
181}
182
183impl Event {
184 pub fn new() -> Self {
186 Self::default()
187 }
188
189 pub fn insert<T, S>(&mut self, key: S, value: T)
202 where
203 S: Into<String> + Hash + Eq,
204 T: Into<EventValue>,
205 {
206 self.inner.insert(key.into(), value.into());
207 }
208
209 pub fn iter(&self) -> impl Iterator<Item = (&String, &EventValue)> {
211 self.inner.iter()
212 }
213
214 pub fn get(&self, key: &str) -> Option<&EventValue> {
216 if let Some(ev) = self.inner.get(key) {
217 return Some(ev);
218 }
219
220 let mut nested_key = key;
221 let mut current = &self.inner;
222 while let Some((head, tail)) = nested_key.split_once('.') {
223 if let Some(EventValue::Map(map)) = current.get(head) {
224 if let Some(value) = map.get(tail) {
225 return Some(value);
226 }
227 current = map;
228 nested_key = tail;
229 } else {
230 return None;
231 }
232 }
233 None
234 }
235
236 pub fn values(&self) -> impl Iterator<Item = &EventValue> {
237 self.inner.values()
238 }
239}
240
241#[cfg(feature = "serde_json")]
242impl TryFrom<serde_json::Value> for Event {
243 type Error = crate::error::JSONError;
244
245 fn try_from(data: serde_json::Value) -> Result<Self, Self::Error> {
246 let mut result = Self::default();
247 match data {
248 serde_json::Value::Object(data) => {
249 for (key, value) in data {
250 result.insert(key, EventValue::try_from(value)?);
251 }
252 }
253 _ => return Err(Self::Error::InvalidEvent()),
254 }
255 Ok(result)
256 }
257}
258
259#[cfg(feature = "serde_json")]
260#[cfg(test)]
261mod tests {
262 use super::*;
263 use crate::wildcard::tokenize;
264 use serde_json::json;
265
266 #[test]
267 fn test_matches() {
268 let mut modifier = Modifier::default();
269
270 assert!(EventValue::from("zsh").matches(&FieldValue::from("zsh"), &modifier));
271 assert!(!EventValue::from("zsh").matches(&FieldValue::from("bash"), &modifier));
272
273 modifier.match_modifier = Some(MatchModifier::StartsWith);
274
275 assert!(EventValue::from("zsh").matches(&FieldValue::from("z"), &modifier));
276 assert!(!EventValue::from("zsh").matches(&FieldValue::from("sd"), &modifier));
277
278 modifier.match_modifier = Some(MatchModifier::EndsWith);
279 assert!(EventValue::from("zsh").matches(&FieldValue::from("sh"), &modifier));
280 assert!(!EventValue::from("zsh").matches(&FieldValue::from("sd"), &modifier));
281
282 modifier.match_modifier = Some(MatchModifier::Contains);
283 assert!(EventValue::from("zsh").matches(&FieldValue::from("s"), &modifier));
284 assert!(!EventValue::from("zsh").matches(&FieldValue::from("d"), &modifier));
285 }
286
287 #[test]
288 fn test_load_from_json() {
289 let event: Event = json!({
290 "name": "John Doe",
291 "age": 43,
292 "address": {
293 "city": "New York",
294 "state": "NY"
295 }
296 })
297 .try_into()
298 .unwrap();
299
300 assert_eq!(event.inner["name"], EventValue::from("John Doe"));
301 assert_eq!(event.inner["age"], EventValue::from(43));
302 assert_eq!(
303 event.inner["address"],
304 EventValue::Map({
305 let mut map = HashMap::new();
306 map.insert("city".to_string(), EventValue::from("New York"));
307 map.insert("state".to_string(), EventValue::from("NY"));
308 map
309 })
310 );
311 }
312
313 #[test]
314 fn test_wildcard_matches() {
315 let modifier = Modifier::default();
316 let wildcard = FieldValue::WildcardPattern(tokenize("4?", false));
317
318 assert!(EventValue::from("42").matches(&wildcard, &modifier));
319 assert!(EventValue::from(43).matches(&wildcard, &modifier));
320 assert!(EventValue::from(43u32).matches(&wildcard, &modifier));
321 assert!(!EventValue::from(53).matches(&wildcard, &modifier));
322 assert!(!EventValue::from(433).matches(&wildcard, &modifier));
323 assert!(!EventValue::from(None).matches(&wildcard, &modifier));
324
325 let wildcard = FieldValue::WildcardPattern(tokenize("f*", false));
326 assert!(EventValue::from(false).matches(&wildcard, &modifier));
327 assert!(!EventValue::from(true).matches(&wildcard, &modifier));
328 assert!(!EventValue::from(None).matches(&wildcard, &modifier));
329 }
330
331 #[test]
332 fn test_iter() {
333 let event = Event::from([("name", 2)]);
334 let mut event_iter = event.iter();
335 assert_eq!(
336 event_iter.next(),
337 Some((&"name".to_string(), &EventValue::from(2)))
338 );
339 assert_eq!(event_iter.next(), None);
340 }
341}