rsigma_eval/event/
mapped.rs1use std::borrow::Cow;
17use std::collections::HashMap;
18
19use serde_json::Value;
20
21use super::{Event, EventValue};
22
23pub struct MappedEvent<'a, E: Event + ?Sized> {
26 inner: &'a E,
27 mapping: &'a HashMap<String, Vec<String>>,
31}
32
33impl<'a, E: Event + ?Sized> MappedEvent<'a, E> {
34 pub fn new(inner: &'a E, mapping: &'a HashMap<String, Vec<String>>) -> Self {
37 Self { inner, mapping }
38 }
39}
40
41impl<E: Event + ?Sized> Event for MappedEvent<'_, E> {
42 fn get_field(&self, path: &str) -> Option<EventValue<'_>> {
43 if let Some(targets) = self.mapping.get(path) {
44 for target in targets {
45 if let Some(value) = self.inner.get_field(target) {
46 return Some(value);
47 }
48 }
49 return self.inner.get_field(path);
52 }
53 self.inner.get_field(path)
54 }
55
56 fn any_string_value(&self, pred: &dyn Fn(&str) -> bool) -> bool {
57 self.inner.any_string_value(pred)
58 }
59
60 fn all_string_values(&self) -> Vec<Cow<'_, str>> {
61 self.inner.all_string_values()
62 }
63
64 fn visit_string_values(&self, visit: &mut dyn FnMut(&str)) {
65 self.inner.visit_string_values(visit)
66 }
67
68 fn to_json(&self) -> Value {
69 self.inner.to_json()
70 }
71
72 fn field_keys(&self) -> Vec<Cow<'_, str>> {
73 self.inner.field_keys()
74 }
75
76 fn top_level_keys(&self) -> Option<Vec<Cow<'_, str>>> {
77 self.inner.top_level_keys()
78 }
79
80 fn visit_top_level_keys(&self, visit: &mut dyn FnMut(&str)) -> bool {
81 self.inner.visit_top_level_keys(visit)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::event::JsonEvent;
89 use serde_json::json;
90
91 fn map(pairs: &[(&str, &[&str])]) -> HashMap<String, Vec<String>> {
92 pairs
93 .iter()
94 .map(|(k, vs)| {
95 (
96 (*k).to_string(),
97 vs.iter().map(|s| (*s).to_string()).collect(),
98 )
99 })
100 .collect()
101 }
102
103 #[test]
104 fn remaps_field_to_schema_name() {
105 let v = json!({"user": {"name": "alice"}});
106 let inner = JsonEvent::borrow(&v);
107 let m = map(&[("User", &["user.name"])]);
108 let mapped = MappedEvent::new(&inner, &m);
109 assert_eq!(
110 mapped
111 .get_field("User")
112 .and_then(|x| x.as_str().map(|s| s.to_string())),
113 Some("alice".to_string())
114 );
115 }
116
117 #[test]
118 fn falls_back_to_original_name_when_unmapped() {
119 let v = json!({"User": "bob"});
120 let inner = JsonEvent::borrow(&v);
121 let m = HashMap::new();
123 let mapped = MappedEvent::new(&inner, &m);
124 assert_eq!(
125 mapped
126 .get_field("User")
127 .and_then(|x| x.as_str().map(|s| s.to_string())),
128 Some("bob".to_string())
129 );
130 }
131
132 #[test]
133 fn one_to_many_picks_first_present() {
134 let v = json!({"source": {"user": {"name": "carol"}}});
135 let inner = JsonEvent::borrow(&v);
136 let m = map(&[("User", &["user.name", "source.user.name"])]);
137 let mapped = MappedEvent::new(&inner, &m);
138 assert_eq!(
139 mapped
140 .get_field("User")
141 .and_then(|x| x.as_str().map(|s| s.to_string())),
142 Some("carol".to_string())
143 );
144 }
145}