sparkles_parser/
tracing_decoder.rs

1use 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    /// id, dif_tm_len
30    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                // Not enough bytes
90                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        // Try parse as many events as possible
108        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}