ghostscope_ui/components/ebpf_panel/output/
streaming_parser_bridge.rs

1//! Simplified bridge for streaming trace event parsing
2//!
3//! This module handles the integration of StreamingTraceParser with the UI crate,
4//! returning ParsedTraceEvent directly for UI processing.
5
6use ghostscope_protocol::{ParsedTraceEvent, StreamingTraceParser, TraceContext};
7use tracing::debug;
8
9/// Bridge for streaming trace event parsing in UI context
10pub struct StreamingParserBridge {
11    parser: StreamingTraceParser,
12}
13
14impl StreamingParserBridge {
15    /// Create a new streaming parser bridge
16    pub fn new() -> Self {
17        Self {
18            parser: StreamingTraceParser::new(),
19        }
20    }
21
22    /// Process incoming ringbuf segment and return complete ParsedTraceEvent if ready
23    ///
24    /// This method uses StreamingTraceParser to reconstruct complete trace events
25    /// and returns them directly for UI processing.
26    pub fn process_ringbuf_segment(
27        &mut self,
28        segment_data: &[u8],
29        trace_context: &TraceContext,
30    ) -> Result<Option<ParsedTraceEvent>, String> {
31        // Use StreamingTraceParser to process the segment
32        let parsed_event = self.parser.process_segment(segment_data, trace_context)?;
33
34        if let Some(trace_event) = parsed_event {
35            debug!(
36                "Completed trace event: trace_id={}, {} instructions",
37                trace_event.trace_id,
38                trace_event.instructions.len()
39            );
40
41            Ok(Some(trace_event))
42        } else {
43            // Segment processed but event not yet complete
44            Ok(None)
45        }
46    }
47
48    /// Reset parser state (useful for error recovery)
49    pub fn reset(&mut self) {
50        self.parser.reset();
51    }
52
53    /// Get current parse state for debugging
54    pub fn get_parse_state(&self) -> &ghostscope_protocol::ParseState {
55        self.parser.get_state()
56    }
57}
58
59impl Default for StreamingParserBridge {
60    fn default() -> Self {
61        Self::new()
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use ghostscope_protocol::TraceContext;
69
70    #[test]
71    fn test_streaming_parser_bridge() {
72        let mut bridge = StreamingParserBridge::new();
73        let trace_context = TraceContext::new();
74
75        // Create test segment data with valid TraceEventHeader
76        use ghostscope_protocol::{consts, TraceEventHeader};
77        let test_header = TraceEventHeader {
78            magic: consts::MAGIC,
79        };
80
81        // Convert header to bytes
82        let header_bytes = unsafe {
83            std::slice::from_raw_parts(
84                &test_header as *const _ as *const u8,
85                std::mem::size_of::<TraceEventHeader>(),
86            )
87        };
88
89        // Process valid header segment
90        let result = bridge.process_ringbuf_segment(header_bytes, &trace_context);
91
92        // Should succeed with valid header but return None (incomplete event)
93        assert!(result.is_ok());
94        assert!(result.unwrap().is_none());
95    }
96}