1use anyhow::{Context, Result};
3use micromegas_transit::{
4 CustomReaderMap, InProcSerialize, LegacyDynString, UserDefinedType, advance_window,
5 parse_pod_instance, read_advance_string, read_consume_pod,
6 value::{Object, Value},
7};
8use std::{collections::HashMap, sync::Arc};
9
10use crate::property_set::PROPERTY_SET_DEP_TYPE_NAME;
11
12lazy_static::lazy_static! {
13 static ref TIME: Arc<String> = Arc::new("time".into());
14 static ref LEVEL: Arc<String> = Arc::new("level".into());
15 static ref TARGET: Arc<String> = Arc::new("target".into());
16 static ref MSG: Arc<String> = Arc::new("msg".into());
17 static ref DESC: Arc<String> = Arc::new("desc".into());
18 static ref PROPERTIES: Arc<String> = Arc::new("properties".into());
19}
20
21fn parse_log_string_event(
22 udt: &UserDefinedType,
23 _udts: &[UserDefinedType],
24 dependencies: &HashMap<u64, Value>,
25 mut object_window: &[u8],
26) -> Result<Value> {
27 let desc_id: u64 = read_consume_pod(&mut object_window);
28 let time: i64 = read_consume_pod(&mut object_window);
29 let msg = String::from_utf8(object_window.to_vec()).with_context(|| "parsing legacy string")?;
30 let desc = dependencies
31 .get(&desc_id)
32 .with_context(|| format!("desc member {desc_id} of LogStringEvent not found"))?;
33 let members = vec![
34 (TIME.clone(), Value::I64(time)),
35 (MSG.clone(), Value::String(Arc::new(msg))),
36 (DESC.clone(), desc.clone()),
37 ];
38 Ok(Value::Object(Arc::new(Object {
39 type_name: udt.name.clone(),
40 members,
41 })))
42}
43
44fn parse_log_string_event_v2(
45 udt: &UserDefinedType,
46 _udts: &[UserDefinedType],
47 dependencies: &HashMap<u64, Value>,
48 mut object_window: &[u8],
49) -> Result<Value> {
50 let desc_id: u64 = read_consume_pod(&mut object_window);
51 let time: i64 = read_consume_pod(&mut object_window);
52 let msg = read_advance_string(&mut object_window).with_context(|| "parsing string")?;
53 let desc: Value = dependencies
54 .get(&desc_id)
55 .with_context(|| format!("desc member {desc_id} of LogStringEvent not found"))?
56 .clone();
57 let members = vec![
58 (TIME.clone(), Value::I64(time)),
59 (MSG.clone(), Value::String(Arc::new(msg))),
60 (DESC.clone(), desc),
61 ];
62 Ok(Value::Object(Arc::new(Object {
63 type_name: udt.name.clone(),
64 members,
65 })))
66}
67
68fn parse_log_string_interop_event_v3(
69 udt: &UserDefinedType,
70 udts: &[UserDefinedType],
71 dependencies: &HashMap<u64, Value>,
72 mut object_window: &[u8],
73) -> Result<Value> {
74 let string_ref_metadata = udts
75 .iter()
76 .find(|t| *t.name == "StaticStringRef")
77 .with_context(
78 || "Can't parse log string interop event with no metadata for StaticStringRef",
79 )?;
80 let time: i64 = read_consume_pod(&mut object_window);
81 let level: u8 = read_consume_pod(&mut object_window);
82 let target = parse_pod_instance(
83 string_ref_metadata,
84 udts,
85 dependencies,
86 &object_window[0..string_ref_metadata.size],
87 )
88 .with_context(|| "parse_pod_instance")?;
89 object_window = advance_window(object_window, string_ref_metadata.size);
90 let msg = read_advance_string(&mut object_window)?;
91 let members = vec![
92 (TIME.clone(), Value::I64(time)),
93 (LEVEL.clone(), Value::U8(level)),
94 (TARGET.clone(), target),
95 (MSG.clone(), Value::String(Arc::new(msg))),
96 ];
97 Ok(Value::Object(Arc::new(Object {
98 type_name: udt.name.clone(),
99 members,
100 })))
101}
102
103fn parse_tagged_log_interop_event(
104 udt: &UserDefinedType,
105 udts: &[UserDefinedType],
106 dependencies: &HashMap<u64, Value>,
107 mut object_window: &[u8],
108) -> Result<Value> {
109 let string_ref_metadata = udts
110 .iter()
111 .find(|t| *t.name == "StaticStringRef")
112 .with_context(
113 || "Can't parse log string interop event with no metadata for StaticStringRef",
114 )?;
115 let time: i64 = read_consume_pod(&mut object_window);
116 let level: u8 = read_consume_pod(&mut object_window);
117 let target = parse_pod_instance(
118 string_ref_metadata,
119 udts,
120 dependencies,
121 &object_window[0..string_ref_metadata.size],
122 )
123 .with_context(|| "parse_pod_instance")?;
124 object_window = advance_window(object_window, string_ref_metadata.size);
125 let properties_id: u64 = read_consume_pod(&mut object_window);
126 let properties = dependencies
127 .get(&properties_id)
128 .with_context(|| "fetching properties in parse_tagged_log_interop_event")?
129 .clone();
130 let msg = read_advance_string(&mut object_window)?;
131 let members = vec![
132 (TIME.clone(), Value::I64(time)),
133 (LEVEL.clone(), Value::U8(level)),
134 (TARGET.clone(), target),
135 (PROPERTIES.clone(), properties),
136 (MSG.clone(), Value::String(Arc::new(msg))),
137 ];
138 Ok(Value::Object(Arc::new(Object {
139 type_name: udt.name.clone(),
140 members,
141 })))
142}
143
144fn parse_tagged_log_string(
145 udt: &UserDefinedType,
146 _udts: &[UserDefinedType],
147 dependencies: &HashMap<u64, Value>,
148 mut object_window: &[u8],
149) -> Result<Value> {
150 let desc_id: u64 = read_consume_pod(&mut object_window);
151 let desc = dependencies
152 .get(&desc_id)
153 .with_context(|| "fetching desc in parse_tagged_log_string")?
154 .clone();
155 let properties_id: u64 = read_consume_pod(&mut object_window);
156 let properties = dependencies
157 .get(&properties_id)
158 .with_context(|| "fetching property set in parse_tagged_log_string")?
159 .clone();
160 let time: i64 = read_consume_pod(&mut object_window);
161 let msg = read_advance_string(&mut object_window)?;
162
163 let members = vec![
164 (TIME.clone(), Value::I64(time)),
165 (DESC.clone(), desc),
166 (PROPERTIES.clone(), properties),
167 (MSG.clone(), Value::String(Arc::new(msg))),
168 ];
169 Ok(Value::Object(Arc::new(Object {
170 type_name: udt.name.clone(),
171 members,
172 })))
173}
174
175fn parse_log_string_interop_event(
176 udt: &UserDefinedType,
177 udts: &[UserDefinedType],
178 dependencies: &HashMap<u64, Value>,
179 mut object_window: &[u8],
180) -> Result<Value> {
181 let stringid_metadata = udts
182 .iter()
183 .find(|t| *t.name == "StringId")
184 .with_context(|| "Can't parse log string interop event with no metadata for StringId")?;
185 unsafe {
186 let time: i64 = read_consume_pod(&mut object_window);
187 let level: u32 = read_consume_pod(&mut object_window);
188 let target = parse_pod_instance(
189 stringid_metadata,
190 udts,
191 dependencies,
192 &object_window[0..stringid_metadata.size],
193 )
194 .with_context(|| "parse_pod_instance")?;
195 object_window = advance_window(object_window, stringid_metadata.size);
196 let msg = <LegacyDynString as InProcSerialize>::read_value(object_window);
197 let members = vec![
198 (TIME.clone(), Value::I64(time)),
199 (LEVEL.clone(), Value::U32(level)),
200 (TARGET.clone(), target),
201 (MSG.clone(), Value::String(Arc::new(msg.0))),
202 ];
203 Ok(Value::Object(Arc::new(Object {
204 type_name: udt.name.clone(),
205 members,
206 })))
207 }
208}
209
210fn parse_property_set(
211 _udt: &UserDefinedType,
212 udts: &[UserDefinedType],
213 dependencies: &HashMap<u64, Value>,
214 mut window: &[u8],
215) -> Result<Value> {
216 let property_layout = udts
217 .iter()
218 .find(|t| *t.name == "Property")
219 .with_context(|| "could not find Property layout")?;
220
221 let object_id: u64 = read_consume_pod(&mut window);
222 let nb_properties: u32 = read_consume_pod(&mut window);
223 let mut members = vec![];
224 for i in 0..nb_properties {
225 let property_size = property_layout.size;
226 let begin = i as usize * property_size;
227 let property_window = &window[begin..begin + property_size];
228 if let Value::Object(obj) =
229 parse_pod_instance(property_layout, udts, dependencies, property_window)?
230 {
231 members.push((
232 obj.get::<Arc<String>>("name")?,
233 Value::String(obj.get::<Arc<String>>("value")?),
234 ));
235 } else {
236 anyhow::bail!("invalid property in propertyset");
237 }
238 }
239
240 lazy_static! {
241 static ref PROPERTY_SET_TYPE_NAME: Arc<String> = Arc::new("property_set".into());
242 static ref ID: Arc<String> = Arc::new("id".into());
243 static ref VALUE: Arc<String> = Arc::new("value".into());
244 }
245
246 let set = Arc::new(Object {
247 type_name: PROPERTY_SET_TYPE_NAME.clone(),
248 members,
249 });
250 Ok(Value::Object(Arc::new(Object {
251 type_name: PROPERTY_SET_DEP_TYPE_NAME.clone(),
252 members: vec![
253 (ID.clone(), Value::U64(object_id)),
254 (VALUE.clone(), Value::Object(set)),
255 ],
256 })))
257}
258
259pub fn make_custom_readers() -> CustomReaderMap {
261 let mut custom_readers: CustomReaderMap = HashMap::new();
262 custom_readers.insert("LogStringEvent".into(), Arc::new(parse_log_string_event));
263 custom_readers.insert(
264 "LogStringEventV2".into(),
265 Arc::new(parse_log_string_event_v2),
266 );
267 custom_readers.insert(
268 "LogStringInteropEventV2".into(),
269 Arc::new(parse_log_string_interop_event),
270 );
271 custom_readers.insert(
272 "LogStringInteropEventV3".into(),
273 Arc::new(parse_log_string_interop_event_v3),
274 );
275 custom_readers.insert("TaggedLogString".into(), Arc::new(parse_tagged_log_string));
276 custom_readers.insert(
277 PROPERTY_SET_DEP_TYPE_NAME.to_string(),
278 Arc::new(parse_property_set),
279 );
280 custom_readers.insert(
281 "TaggedLogInteropEvent".into(),
282 Arc::new(parse_tagged_log_interop_event),
283 );
284 custom_readers
285}