sparkles_parser/
tracing_decoder.rs1use std::mem;
2use ringbuf::consumer::Consumer;
3use ringbuf::producer::Producer;
4use ringbuf::storage::Heap;
5use ringbuf::traits::Observer;
6use crate::{TracingEvent, TracingEventId, PARSER_BUF_SIZE};
7
8pub struct StreamFrameDecoder {
9 state: ParsingState,
10 buf: ringbuf::LocalRb<Heap<u8>>
11}
12
13impl Default for StreamFrameDecoder {
14 fn default() -> Self {
15 Self {
16 state: ParsingState::NewFrame,
17 buf: ringbuf::LocalRb::new(PARSER_BUF_SIZE)
18 }
19 }
20}
21
22#[derive(Copy,Clone, Default, Debug)]
23#[derive(PartialEq)]
24pub enum ParsingState {
25 #[default]
26 NewFrame,
27 DifTmLen(TracingEventId),
28
29 DifTm(TracingEventId, usize),
31
32 RangeOrdId(Option<TracingEventId>, usize),
33 RangeTm(Option<TracingEventId>, usize, u8)
34}
35
36impl StreamFrameDecoder {
37 pub fn try_decode_event(&mut self) -> Result<TracingEvent, bool> {
38 let available_bytes_len = self.buf.occupied_len();
39
40 let (ev, new_state) = match mem::take(&mut self.state) {
41 ParsingState::NewFrame if available_bytes_len >= 1 => {
42 let ev_id = self.buf.try_pop().unwrap();
43 (None, ParsingState::DifTmLen(ev_id))
44 }
45 ParsingState::DifTmLen(ev) if available_bytes_len >= 1 => {
46 let dif_tm_len = self.buf.try_pop().unwrap();
47
48 let is_range_event = dif_tm_len & 0b1000_0000 != 0;
49 let is_unnamed_range_end = dif_tm_len & 0b0100_0000 != 0;
50 let dif_tm_len = (dif_tm_len & 0b0000_1111) as usize;
51
52 if is_range_event {
53 if is_unnamed_range_end {
54 (None, ParsingState::RangeOrdId(None, dif_tm_len))
55 }
56 else {
57 (None, ParsingState::RangeOrdId(Some(ev), dif_tm_len))
58 }
59 }
60 else {
61 (None, ParsingState::DifTm(ev, dif_tm_len))
62 }
63 }
64 ParsingState::DifTm(ev, dif_tm_len) if available_bytes_len >= dif_tm_len => {
65 let mut buf = [0u8; 8];
66 self.buf.pop_slice(&mut buf[..dif_tm_len]);
67 let dif_tm = u64::from_le_bytes(buf);
68 (Some(TracingEvent::Instant(ev, dif_tm)), ParsingState::NewFrame)
69 }
70 ParsingState::RangeOrdId(ev, dif_tm_len) if available_bytes_len >= 1 => {
71 let ord_id = self.buf.try_pop().unwrap();
72
73 (None, ParsingState::RangeTm(ev, dif_tm_len, ord_id))
74 }
75 ParsingState::RangeTm(ev_id, dif_tm_len, ord_id) if available_bytes_len >= dif_tm_len => {
76 let mut buf = [0u8; 8];
77 self.buf.pop_slice(&mut buf[..dif_tm_len]);
78 let dif_tm = u64::from_le_bytes(buf);
79
80 let ev = if let Some(id) = ev_id {
81 Some(TracingEvent::RangePart(id, dif_tm, ord_id))
82 }
83 else {
84 Some(TracingEvent::UnnamedRangeEnd(dif_tm, ord_id))
85 };
86 (ev, ParsingState::NewFrame)
87 }
88 state => {
89 self.state = state;
91 return Err(true)
92 }
93 };
94
95 self.state = new_state;
96 if let Some(ev) = ev {
97 Ok(ev)
98 }
99 else {
100 Err(false)
101 }
102 }
103
104 pub fn decode_many(&mut self, bytes: &[u8]) -> Vec<TracingEvent> {
105 self.buf.push_slice(bytes);
106 let mut events = Vec::new();
107 loop {
109 match self.try_decode_event() {
110 Ok(ev) => {
111 events.push(ev);
112 }
113 Err(finish) => {
114 if finish {
115 return events;
116 }
117 }
118 }
119 }
120 }
121
122 pub fn ensure_buf_end(&mut self) {
123 assert!(self.buf.is_empty());
124 assert_eq!(self.state, ParsingState::NewFrame);
125 }
126}