1#[derive(Copy, Clone, PartialEq, Debug)]
2pub enum DataType {
3 U8,
4 I8,
5 U16,
6 I16,
7 U32,
8 I32,
9 U64,
10 I64,
11 Str,
12 Struct,
13}
14
15#[derive(Debug, PartialEq, Clone)]
16pub enum ErrorKind {
17 NotFound,
18 InvalidType,
19}
20
21#[derive(Debug, PartialEq)]
22pub struct Event {
23 klass_id: u32,
24 values: std::collections::HashMap<String, Value>,
25}
26
27#[derive(Debug)]
28pub struct ValueError {
29 kind: ErrorKind,
30 field: String,
31}
32
33impl ValueError {
34 pub fn new(field: &str, kind: ErrorKind) -> ValueError {
35 ValueError {
36 kind,
37 field: field.to_string(),
38 }
39 }
40
41 pub fn kind(&self) -> ErrorKind {
42 self.kind.clone()
43 }
44}
45
46impl std::error::Error for ValueError {}
47
48impl std::fmt::Display for ValueError {
49 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
50 write!(f, "Cannot get value {}: {:?}>", self.field, self.kind)
51 }
52}
53
54#[derive(Debug, PartialEq)]
57pub enum Value {
58 U8(u8),
59 I8(i8),
60 U16(u16),
61 I16(i16),
62 U32(u32),
63 I32(i32),
64 U64(u64),
65 I64(i64),
66 Str(String),
67 Struct(Event),
68}
69
70impl std::fmt::Display for Value {
71 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
72 match self {
73 Value::U8(v) => write!(f, "{}", v),
74 Value::I8(v) => write!(f, "{}", v),
75 Value::U16(v) => write!(f, "{}", v),
76 Value::I16(v) => write!(f, "{}", v),
77 Value::U32(v) => write!(f, "{}", v),
78 Value::I32(v) => write!(f, "{}", v),
79 Value::U64(v) => write!(f, "{}", v),
80 Value::I64(v) => write!(f, "{}", v),
81 Value::Str(v) => write!(f, "\"{}\"", v),
82 Value::Struct(v) => write!(f, "<Event {}>", v.get_klass_id()),
83 }
84 }
85}
86
87macro_rules! make_field_getter {
88 ($function_name: ident, $data_type: ident, $type: ty) => (
89 pub fn $function_name(&self, name: &str) -> Result<$type, ValueError> {
90 match self.values.get(name) {
91 Some(value) => {
92 if let Value::$data_type(data) = value {
93 Ok(*data)
94 } else {
95 Err(ValueError::new(name, ErrorKind::InvalidType))
96 }
97 },
98 None => Err(ValueError::new(name, ErrorKind::NotFound))
99 }
100 }
101 )
102}
103
104macro_rules! make_field_getter_ref {
105 ($function_name: ident, $data_type: ident, $type: ty) => (
106 pub fn $function_name(&self, name: &str) -> Result<$type, ValueError> {
107 match self.values.get(name) {
108 Some(value) => {
109 if let Value::$data_type(data) = value {
110 Ok(data)
111 } else {
112 Err(ValueError::new(name, ErrorKind::InvalidType))
113 }
114 },
115 None => Err(ValueError::new(name, ErrorKind::NotFound))
116 }
117 }
118 )
119}
120
121impl Event {
122 pub fn new(klass_id: u32, values: std::collections::HashMap<String, Value>) -> Event {
123 Event { klass_id, values }
124 }
125
126 make_field_getter!(get_value_u8, U8, u8);
127 make_field_getter!(get_value_i8, I8, i8);
128 make_field_getter!(get_value_u16, U16, u16);
129 make_field_getter!(get_value_i16, I16, i16);
130 make_field_getter!(get_value_u32, U32, u32);
131 make_field_getter!(get_value_i32, I32, i32);
132 make_field_getter!(get_value_u64, U64, u64);
133 make_field_getter!(get_value_i64, I64, i64);
134 make_field_getter_ref!(get_value_string, Str, &String);
135 make_field_getter_ref!(get_value_struct, Struct, &Event);
136
137 pub fn get_raw_value(&self, name: &str) -> Option<&Value> {
138 self.values.get(name)
139 }
140
141 pub fn get_all_values(&self) -> &std::collections::HashMap<String, Value> {
142 &self.values
143 }
144
145 pub fn get_klass_id(&self) -> u32 {
146 self.klass_id
147 }
148
149 pub fn flat_event(self) -> Event {
150 let mut new_values = std::collections::HashMap::<String, Value>::new();
151 let klass_id = self.get_klass_id();
152 self.flat_event_internal(&mut new_values);
153
154 Event::new(klass_id, new_values)
155 }
156
157 fn flat_event_internal(mut self, new_values: &mut std::collections::HashMap<String, Value>) {
158 let base_value = self.values.remove("base");
159
160 for (name, value) in self.values {
161 new_values.insert(name, value);
162 }
163
164 if let Some(base_value) = base_value {
165 if let Value::Struct(event) = base_value {
166 event.flat_event_internal(new_values);
167 } else {
168 new_values.insert("base".to_string(), base_value);
169 }
170 }
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177 use std::collections::HashMap;
178
179 #[test]
180 fn getting_klass_id_should_return_correct_value() {
181 let klass_id = 5;
182 let event = Event::new(klass_id, HashMap::<String, Value>::new());
183 assert_eq!(klass_id, event.get_klass_id());
184 }
185
186 #[test]
187 fn getting_valid_type_should_not_fail() {
188 let u32_value = 492;
189 let mut values = HashMap::<String, Value>::new();
190 values.insert("v1".to_string(), Value::U32(u32_value));
191 let event = Event::new(1, values);
192
193 assert_eq!(
194 event.get_value_u32("v1").expect("value v1 doesn't exist"),
195 u32_value
196 );
197 }
198
199 #[test]
200 fn getting_non_existing_value_should_fail() {
201 let event = Event::new(1, HashMap::<String, Value>::new());
202
203 assert_eq!(
204 event.get_value_u32("non-existing").unwrap_err().kind(),
205 ErrorKind::NotFound
206 );
207 }
208
209 #[test]
210 fn getting_non_existing_string_value_should_fail() {
211 let event = Event::new(1, HashMap::<String, Value>::new());
212
213 assert_eq!(
214 event.get_value_string("non-existing").unwrap_err().kind(),
215 ErrorKind::NotFound
216 );
217 }
218
219 #[test]
220 fn getting_invalid_type_should_fail() {
221 let mut values = HashMap::<String, Value>::new();
222 values.insert("v1".to_string(), Value::U32(2));
223 let event = Event::new(1, values);
224
225 assert_eq!(
226 event.get_value_string("v1").unwrap_err().kind(),
227 ErrorKind::InvalidType
228 );
229 }
230
231 #[test]
232 fn getting_invalid_integer_type_should_fail() {
233 let mut values = HashMap::<String, Value>::new();
234 values.insert("v1".to_string(), Value::U8(2));
235 let event = Event::new(1, values);
236
237 assert_eq!(
238 event.get_value_u32("v1").unwrap_err().kind(),
239 ErrorKind::InvalidType
240 );
241 }
242
243 #[test]
244 fn flatten_event_should_collapse_all_base_struct_events() {
245 let mut super_base_values = HashMap::<String, Value>::new();
246 super_base_values.insert("timestamp".to_string(), Value::U64(999));
247 super_base_values.insert("xxx".to_string(), Value::U64(876));
248
249 let mut base_values = HashMap::<String, Value>::new();
250 base_values.insert(
251 "base".to_string(),
252 Value::Struct(Event::new(1, super_base_values)),
253 );
254 base_values.insert("timestamp".to_string(), Value::U64(123));
255 base_values.insert("id".to_string(), Value::U64(456));
256
257 let mut values = HashMap::<String, Value>::new();
258 values.insert(
259 "base".to_string(),
260 Value::Struct(Event::new(1, base_values)),
261 );
262 values.insert("name".to_string(), Value::Str("some_name".to_string()));
263 let event = Event::new(3, values);
264
265 let event = event.flat_event();
266
267 assert_eq!(4, event.values.len());
268 assert_eq!(3, event.get_klass_id());
269 assert_eq!(event.get_value_u64("timestamp").unwrap(), 999);
270 assert_eq!(event.get_value_u64("id").unwrap(), 456);
271 assert_eq!(event.get_value_u64("xxx").unwrap(), 876);
272 assert_eq!(event.get_value_string("name").unwrap(), "some_name");
273 }
274
275 #[test]
276 fn flatten_event_should_not_collapse_non_event_fields() {
277 let mut values = HashMap::<String, Value>::new();
278 values.insert("base".to_string(), Value::U64(2));
279 values.insert("name".to_string(), Value::Str("some_name".to_string()));
280 let event = Event::new(3, values);
281
282 let event = event.flat_event();
283
284 assert_eq!(2, event.values.len());
285 assert_eq!(event.get_value_u64("base").unwrap(), 2);
286 assert_eq!(event.get_value_string("name").unwrap(), "some_name");
287 }
288}