1use crate::{
2 config::{
3 EnumerationFieldTypeMappingSequence, FeaturesUnsignedIntegerFieldType, FieldType,
4 NativeByteOrder, PreferredDisplayBase, PrimitiveFieldType, StructureMemberFieldType,
5 UnsignedIntegerFieldType,
6 },
7 error::Error,
8 types::{EventId, FieldValue, PrimitiveFieldValue},
9};
10use byteordered::{byteorder::ReadBytesExt, ByteOrdered, Endianness};
11use fxhash::FxHashMap;
12use internment::Intern;
13use uuid::Uuid;
14
15#[derive(Debug)]
16pub struct PacketHeaderParser {
17 pub magic: Option<UIntParser>,
18 pub uuid: Option<UuidParser>,
19 pub stream_id: UIntParser,
20 pub alignment: Size,
21 pub wire_size_hint: AlignedCursor,
22}
23
24impl PacketHeaderParser {
25 pub fn new(
26 magic: Option<UIntParser>,
27 uuid: Option<UuidParser>,
28 stream_id: UIntParser,
29 alignment: Size,
30 ) -> Self {
31 let mut wire_size_hint = AlignedCursor::default();
32
33 wire_size_hint.align_to(alignment);
35
36 if let Some(f) = magic.as_ref() {
38 wire_size_hint.aligned_increment(f.desc());
39 }
40 if uuid.is_some() {
41 wire_size_hint.align_to(Size::Bits8);
43 wire_size_hint.increment(Size::Bits64);
44 wire_size_hint.increment(Size::Bits64);
45 }
46 wire_size_hint.aligned_increment(stream_id.desc());
47
48 Self {
49 magic,
50 uuid,
51 stream_id,
52 alignment,
53 wire_size_hint,
54 }
55 }
56}
57
58#[derive(Debug)]
59pub struct PacketContextParserArgs {
60 pub packet_size: UIntParser,
61 pub content_size: UIntParser,
62 pub beginning_timestamp: Option<UIntParser>,
63 pub end_timestamp: Option<UIntParser>,
64 pub events_discarded: Option<UIntParser>,
65 pub sequence_number: Option<UIntParser>,
66 pub extra_members: Vec<EventPayloadMemberParser>,
67 pub alignment: Size,
68}
69
70#[derive(Debug)]
71pub struct PacketContextParser {
72 pub packet_size: UIntParser,
73 pub content_size: UIntParser,
74 pub beginning_timestamp: Option<UIntParser>,
75 pub end_timestamp: Option<UIntParser>,
76 pub events_discarded: Option<UIntParser>,
77 pub sequence_number: Option<UIntParser>,
78 pub extra_members: Vec<EventPayloadMemberParser>,
79 pub alignment: Size,
80 pub wire_size_hint: AlignedCursor,
81}
82
83impl PacketContextParser {
84 pub fn new(args: PacketContextParserArgs, packet_header_cursor: &AlignedCursor) -> Self {
85 let mut wire_size_hint = *packet_header_cursor;
86
87 wire_size_hint.align_to(args.alignment);
89
90 wire_size_hint.aligned_increment(args.packet_size.desc());
92 wire_size_hint.aligned_increment(args.content_size.desc());
93 if let Some(f) = args.beginning_timestamp.as_ref() {
94 wire_size_hint.aligned_increment(f.desc());
95 }
96 if let Some(f) = args.end_timestamp.as_ref() {
97 wire_size_hint.aligned_increment(f.desc());
98 }
99 if let Some(f) = args.events_discarded.as_ref() {
100 wire_size_hint.aligned_increment(f.desc());
101 }
102 if let Some(f) = args.sequence_number.as_ref() {
103 wire_size_hint.aligned_increment(f.desc());
104 }
105
106 for extra_member in args.extra_members.iter() {
108 wire_size_hint.aligned_increment(extra_member.value.desc());
109 }
110
111 Self {
112 packet_size: args.packet_size,
113 content_size: args.content_size,
114 beginning_timestamp: args.beginning_timestamp,
115 end_timestamp: args.end_timestamp,
116 events_discarded: args.events_discarded,
117 sequence_number: args.sequence_number,
118 extra_members: args.extra_members,
119 alignment: args.alignment,
120 wire_size_hint,
121 }
122 }
123}
124
125#[derive(Debug)]
126pub struct StreamParser {
127 pub stream_name: Intern<String>,
128 pub packet_context: PacketContextParser,
129 pub event_header: EventHeaderParser,
130 pub common_context: Option<EventPayloadParser>,
131 pub events: FxHashMap<EventId, EventParser>,
132}
133
134#[derive(Debug)]
135pub struct EventHeaderParser {
136 pub event_id: UIntParser,
137 pub timestamp: UIntParser,
138 pub alignment: Size,
139}
140
141#[derive(Debug)]
142pub struct EventParser {
143 pub event_name: Intern<String>,
144 pub log_level: Option<i32>,
145 pub specific_context: Option<EventPayloadParser>,
146 pub payload: Option<EventPayloadParser>,
147}
148
149#[derive(Debug)]
150pub struct EventPayloadParser {
151 pub alignment: Size,
152 pub members: Vec<EventPayloadMemberParser>,
153}
154
155#[derive(Debug)]
156pub struct EnumerationMappings(pub Vec<(Intern<String>, Vec<EnumerationFieldTypeMappingSequence>)>);
157
158impl EnumerationMappings {
159 pub(crate) fn from_struct_ft(ft: &StructureMemberFieldType) -> Option<Self> {
160 match ft {
161 StructureMemberFieldType::UnsignedEnumeration(t)
162 | StructureMemberFieldType::SignedEnumeration(t) => {
163 let mut mappings = Vec::new();
164 for (label, seq) in t.mappings.iter() {
165 mappings.push((Intern::new(label.clone()), seq.clone()));
166 }
167 Some(Self(mappings))
168 }
169 _ => None,
170 }
171 }
172
173 pub fn label(&self, v: i64) -> Option<Intern<String>> {
174 self.0
175 .iter()
176 .find_map(|(label, values)| values.iter().any(|s| s.contains(v)).then_some(*label))
177 }
178}
179
180#[derive(Debug)]
181pub struct EventPayloadMemberParser {
182 pub member_name: Intern<String>,
183 pub preferred_display_base: Option<PreferredDisplayBase>,
184 pub enum_mappings: Option<EnumerationMappings>,
185 pub value: FieldTypeParser,
186}
187
188impl EventPayloadMemberParser {
189 pub fn parse<T: ReadBytesExt>(&self, r: &mut StreamReader<T>) -> Result<FieldValue, Error> {
190 let val = match self.value.parse(r)? {
192 FieldValue::Primitive(PrimitiveFieldValue::UnsignedInteger(v, _)) => {
193 FieldValue::Primitive(PrimitiveFieldValue::UnsignedInteger(
194 v,
195 self.preferred_display_base.unwrap_or_default(),
196 ))
197 }
198 FieldValue::Primitive(PrimitiveFieldValue::SignedInteger(v, _)) => {
199 FieldValue::Primitive(PrimitiveFieldValue::SignedInteger(
200 v,
201 self.preferred_display_base.unwrap_or_default(),
202 ))
203 }
204 val => val,
205 };
206
207 if let Some(mappings) = &self.enum_mappings {
209 match val {
210 FieldValue::Primitive(PrimitiveFieldValue::UnsignedInteger(v, pdb)) => {
212 Ok(FieldValue::Primitive(PrimitiveFieldValue::Enumeration(
213 v as i64,
214 pdb,
215 mappings.label(v as i64),
216 )))
217 }
218 FieldValue::Primitive(PrimitiveFieldValue::SignedInteger(v, pdb)) => {
219 Ok(FieldValue::Primitive(PrimitiveFieldValue::Enumeration(
220 v,
221 pdb,
222 mappings.label(v),
223 )))
224 }
225 val => Ok(val),
226 }
227 } else {
228 Ok(val)
229 }
230 }
231}
232
233#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
234pub enum Size {
235 Bits8,
236 Bits16,
237 Bits32,
238 Bits64,
239}
240
241impl Size {
242 pub fn from_bits(bits: usize) -> Option<Self> {
243 Some(match bits {
244 8 => Self::Bits8,
245 16 => Self::Bits16,
246 32 => Self::Bits32,
247 64 => Self::Bits64,
248 _ => return None,
249 })
250 }
251
252 fn bits(&self) -> usize {
253 match self {
254 Self::Bits8 => 8,
255 Self::Bits16 => 16,
256 Self::Bits32 => 32,
257 Self::Bits64 => 64,
258 }
259 }
260}
261
262#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
263pub struct FieldDesc {
264 pub size: Size,
265 pub alignment: Size,
266}
267
268#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, thiserror::Error)]
269#[error("Unsupported field type (width {0}, alignment {1})")]
270pub struct FieldUnsupportedError(pub usize, pub usize);
271
272impl FieldDesc {
273 pub fn from_ft<T: FieldType>(ft: &T) -> Result<Self, FieldUnsupportedError> {
274 if let (Some(size), Some(alignment)) =
275 (Size::from_bits(ft.size()), Size::from_bits(ft.alignment()))
276 {
277 Ok(Self { size, alignment })
278 } else {
279 Err(FieldUnsupportedError(ft.size(), ft.alignment()))
280 }
281 }
282}
283
284#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
285pub struct UuidParser {}
286
287impl UuidParser {
288 pub fn from_bool_ft(uuid_field_type: bool) -> Option<Self> {
289 uuid_field_type.then_some(Self {})
290 }
291
292 pub fn parse<T: ReadBytesExt>(&self, r: &mut StreamReader<T>) -> Result<Uuid, Error> {
293 r.align_to(Size::Bits8)?;
294 let mut bytes = [0_u8; 16];
295 for b in bytes.iter_mut() {
296 *b = r.read_u8(Size::Bits8)?;
297 }
298 Ok(Uuid::from_bytes(bytes))
299 }
300}
301
302#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
303pub struct UIntParser(FieldDesc);
304
305impl UIntParser {
306 pub fn from_uint_ft(ft: &UnsignedIntegerFieldType) -> Result<Self, FieldUnsupportedError> {
307 Ok(Self(FieldDesc::from_ft(&ft.field_type)?))
308 }
309
310 pub fn from_opt_uint_ft(
311 ft: &FeaturesUnsignedIntegerFieldType,
312 ) -> Result<Option<Self>, FieldUnsupportedError> {
313 match ft {
314 FeaturesUnsignedIntegerFieldType::False(_) => Ok(None),
315 FeaturesUnsignedIntegerFieldType::UnsignedInteger(uint) => {
316 Ok(Some(Self::from_uint_ft(uint)?))
317 }
318 }
319 }
320
321 pub fn desc(&self) -> &FieldDesc {
322 &self.0
323 }
324
325 pub fn parse<T: ReadBytesExt>(&self, r: &mut StreamReader<T>) -> Result<u64, Error> {
326 Ok(match self.desc().size {
327 Size::Bits8 => r.read_u8(self.desc().alignment)?.into(),
328 Size::Bits16 => r.read_u16(self.desc().alignment)?.into(),
329 Size::Bits32 => r.read_u32(self.desc().alignment)?.into(),
330 Size::Bits64 => r.read_u64(self.desc().alignment)?,
331 })
332 }
333}
334
335#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
336pub enum PrimitiveFieldTypeParser {
337 UInt(FieldDesc),
338 Int(FieldDesc),
339 String(FieldDesc),
340 Real(FieldDesc),
341 UEnum(FieldDesc),
342 Enum(FieldDesc),
343}
344
345impl PrimitiveFieldTypeParser {
346 pub fn from_ft(ft: &PrimitiveFieldType) -> Result<Self, FieldUnsupportedError> {
347 let desc = FieldDesc::from_ft(ft)?;
348 Ok(match ft {
349 PrimitiveFieldType::UnsignedInteger(_) => Self::UInt(desc),
350 PrimitiveFieldType::SignedInteger(_) => Self::Int(desc),
351 PrimitiveFieldType::String => Self::String(desc),
352 PrimitiveFieldType::Real(_) => Self::Real(desc),
353 PrimitiveFieldType::UnsignedEnumeration(_) => Self::UEnum(desc),
354 PrimitiveFieldType::SignedEnumeration(_) => Self::Enum(desc),
355 })
356 }
357
358 pub fn desc(&self) -> &FieldDesc {
359 match self {
360 Self::UInt(t)
361 | Self::Int(t)
362 | Self::String(t)
363 | Self::Real(t)
364 | Self::UEnum(t)
365 | Self::Enum(t) => t,
366 }
367 }
368
369 pub fn parse<T: ReadBytesExt>(
370 &self,
371 r: &mut StreamReader<T>,
372 ) -> Result<PrimitiveFieldValue, Error> {
373 Ok(match self {
374 Self::UInt(desc) | Self::UEnum(desc) => match desc.size {
375 Size::Bits8 => r.read_u8(desc.alignment)?.into(),
376 Size::Bits16 => r.read_u16(desc.alignment)?.into(),
377 Size::Bits32 => r.read_u32(desc.alignment)?.into(),
378 Size::Bits64 => r.read_u64(desc.alignment)?.into(),
379 },
380 Self::Int(desc) | Self::Enum(desc) => match desc.size {
381 Size::Bits8 => r.read_i8(desc.alignment)?.into(),
382 Size::Bits16 => r.read_i16(desc.alignment)?.into(),
383 Size::Bits32 => r.read_i32(desc.alignment)?.into(),
384 Size::Bits64 => r.read_i64(desc.alignment)?.into(),
385 },
386 Self::String(_) => r.read_string()?.into(),
387 Self::Real(desc) => match desc.size {
388 Size::Bits32 => r.read_f32(desc.alignment)?.into(),
389 Size::Bits64 => r.read_f64(desc.alignment)?.into(),
390 _ => return Err(Error::InvalidFloatSize(desc.size.bits())),
391 },
392 })
393 }
394}
395
396#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
397pub enum FieldTypeParser {
398 Primitive(PrimitiveFieldTypeParser),
399 StaticArray(usize, PrimitiveFieldTypeParser),
400 DynamicArray(PrimitiveFieldTypeParser),
401}
402
403impl FieldTypeParser {
404 pub fn from_ft(ft: &StructureMemberFieldType) -> Result<Self, FieldUnsupportedError> {
405 let desc = FieldDesc::from_ft(ft)?;
406
407 Ok(match ft {
408 StructureMemberFieldType::UnsignedInteger(_) => {
409 Self::Primitive(PrimitiveFieldTypeParser::UInt(desc))
410 }
411 StructureMemberFieldType::SignedInteger(_) => {
412 Self::Primitive(PrimitiveFieldTypeParser::Int(desc))
413 }
414 StructureMemberFieldType::String => {
415 Self::Primitive(PrimitiveFieldTypeParser::String(desc))
416 }
417 StructureMemberFieldType::Real(_) => {
418 Self::Primitive(PrimitiveFieldTypeParser::Real(desc))
419 }
420 StructureMemberFieldType::UnsignedEnumeration(_) => {
421 Self::Primitive(PrimitiveFieldTypeParser::UEnum(desc))
422 }
423 StructureMemberFieldType::SignedEnumeration(_) => {
424 Self::Primitive(PrimitiveFieldTypeParser::Enum(desc))
425 }
426 StructureMemberFieldType::StaticArray(ft) => Self::StaticArray(
427 ft.length,
428 PrimitiveFieldTypeParser::from_ft(&ft.element_field_type)?,
429 ),
430 StructureMemberFieldType::DynamicArray(ft) => {
431 Self::DynamicArray(PrimitiveFieldTypeParser::from_ft(&ft.element_field_type)?)
432 }
433 })
434 }
435
436 pub fn desc(&self) -> &FieldDesc {
437 match self {
438 Self::Primitive(t) => t.desc(),
439 Self::StaticArray(_len, t) => t.desc(),
440 Self::DynamicArray(t) => t.desc(),
441 }
442 }
443
444 pub fn parse<T: ReadBytesExt>(&self, r: &mut StreamReader<T>) -> Result<FieldValue, Error> {
445 match self {
446 Self::Primitive(p) => Ok(p.parse(r)?.into()),
447 Self::StaticArray(len, p) => {
448 r.align_to(p.desc().alignment)?;
450
451 let mut arr = Vec::new();
453 for _ in 0..*len {
454 arr.push(p.parse(r)?);
455 }
456 Ok(FieldValue::Array(arr))
457 }
458 Self::DynamicArray(p) => {
459 let len = r.read_u32(Size::Bits8)?;
463
464 r.align_to(p.desc().alignment)?;
466
467 let mut arr = Vec::new();
469 for _ in 0..len {
470 arr.push(p.parse(r)?);
471 }
472 Ok(FieldValue::Array(arr))
473 }
474 }
475 }
476}
477
478#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
486pub struct AlignedCursor {
487 bit_index: usize,
488}
489
490impl AlignedCursor {
491 pub fn cursor_bits(&self) -> usize {
492 self.bit_index
493 }
494
495 pub fn cursor_bytes(&self) -> usize {
496 self.bit_index >> 3
497 }
498
499 pub fn align_to(&mut self, align: Size) -> usize {
501 let align_bits = align.bits();
502 debug_assert!(align_bits % 8 == 0);
503
504 let next_index = (self.bit_index + (align_bits - 1)) & (!align_bits + 1);
506 tracing::trace!(align = align_bits, index = self.bit_index, next_index,);
507 debug_assert!(next_index % 8 == 0);
508
509 let padding = next_index - self.bit_index;
511 self.bit_index += padding;
512 padding
513 }
514
515 pub fn aligned_increment(&mut self, desc: &FieldDesc) {
517 let _padding = self.align_to(desc.alignment);
518 self.increment(desc.size);
519 }
520
521 pub fn increment(&mut self, size: Size) {
523 self.bit_index += size.bits();
524 }
525}
526
527#[derive(Debug)]
528pub struct StreamReader<T> {
529 pub inner: ByteOrdered<T, Endianness>,
530 pub cursor: AlignedCursor,
531}
532
533impl<T> StreamReader<T>
534where
535 T: ReadBytesExt,
536{
537 pub fn new(byte_order: NativeByteOrder, r: T) -> Self {
538 Self::new_with_cursor(byte_order, AlignedCursor::default(), r)
539 }
540
541 pub fn new_with_cursor(byte_order: NativeByteOrder, cursor: AlignedCursor, r: T) -> Self {
542 Self {
543 inner: ByteOrdered::runtime(r, byte_order.into()),
544 cursor,
545 }
546 }
547
548 pub fn into_cursor(self) -> AlignedCursor {
549 let StreamReader { inner: _, cursor } = self;
550 cursor
551 }
552
553 pub fn cursor_bits(&self) -> usize {
554 self.cursor.cursor_bits()
555 }
556
557 pub fn align_to(&mut self, align: Size) -> Result<(), Error> {
558 let padding = self.cursor.align_to(align);
560 let padding_bytes = padding >> 3;
561 for _ in 0..padding_bytes {
562 let _ = self.inner.read_u8()?;
563 }
564 Ok(())
565 }
566
567 pub fn read_u8(&mut self, align: Size) -> Result<u8, Error> {
568 self.align_to(align)?;
569 let val = self.inner.read_u8()?;
570 self.cursor.increment(Size::Bits8);
571 Ok(val)
572 }
573
574 pub fn read_i8(&mut self, align: Size) -> Result<i8, Error> {
575 self.align_to(align)?;
576 let val = self.inner.read_i8()?;
577 self.cursor.increment(Size::Bits8);
578 Ok(val)
579 }
580
581 pub fn read_u16(&mut self, align: Size) -> Result<u16, Error> {
582 self.align_to(align)?;
583 let val = self.inner.read_u16()?;
584 self.cursor.increment(Size::Bits16);
585 Ok(val)
586 }
587
588 pub fn read_i16(&mut self, align: Size) -> Result<i16, Error> {
589 self.align_to(align)?;
590 let val = self.inner.read_i16()?;
591 self.cursor.increment(Size::Bits16);
592 Ok(val)
593 }
594
595 pub fn read_u32(&mut self, align: Size) -> Result<u32, Error> {
596 self.align_to(align)?;
597 let val = self.inner.read_u32()?;
598 self.cursor.increment(Size::Bits32);
599 Ok(val)
600 }
601
602 pub fn read_i32(&mut self, align: Size) -> Result<i32, Error> {
603 self.align_to(align)?;
604 let val = self.inner.read_i32()?;
605 self.cursor.increment(Size::Bits32);
606 Ok(val)
607 }
608
609 pub fn read_f32(&mut self, align: Size) -> Result<f32, Error> {
610 self.align_to(align)?;
611 let val = self.inner.read_f32()?;
612 self.cursor.increment(Size::Bits32);
613 Ok(val)
614 }
615
616 pub fn read_u64(&mut self, align: Size) -> Result<u64, Error> {
617 self.align_to(align)?;
618 let val = self.inner.read_u64()?;
619 self.cursor.increment(Size::Bits64);
620 Ok(val)
621 }
622
623 pub fn read_i64(&mut self, align: Size) -> Result<i64, Error> {
624 self.align_to(align)?;
625 let val = self.inner.read_i64()?;
626 self.cursor.increment(Size::Bits64);
627 Ok(val)
628 }
629
630 pub fn read_f64(&mut self, align: Size) -> Result<f64, Error> {
631 self.align_to(align)?;
632 let val = self.inner.read_f64()?;
633 self.cursor.increment(Size::Bits64);
634 Ok(val)
635 }
636
637 pub fn read_string(&mut self) -> Result<String, Error> {
638 let mut cstr = Vec::new();
639 self.align_to(Size::Bits8)?;
640 loop {
641 let b = self.inner.read_u8()?;
642 self.cursor.increment(Size::Bits8);
643 if b == 0 {
644 break;
645 }
646 cstr.push(b);
647 }
648 Ok(String::from_utf8_lossy(&cstr).to_string())
649 }
650}