mielin_cells/debug/
mod.rs1pub mod inspector;
10pub mod profiler;
11pub mod remote;
12pub mod tracer;
13
14pub use inspector::{InspectionQuery, InspectionResult, StateInspector};
15pub use profiler::{AllocationRecord, MemoryProfiler, MemorySnapshot, ProfilingReport};
16pub use remote::{DebugCommand, DebugSession, DebuggerConfig, RemoteDebugger};
17pub use tracer::{ExecutionTracer, TraceEvent, TraceFilter, TraceRecorder};
18
19use serde::{Deserialize, Serialize};
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct DebugContext {
24 pub agent_id: [u8; 16],
26 pub session_id: [u8; 16],
28 pub enabled: bool,
30 pub breakpoints: Vec<Breakpoint>,
32 pub watches: Vec<WatchExpression>,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct Breakpoint {
39 pub id: u64,
41 pub location: String,
43 pub condition: Option<String>,
45 pub hit_count: u64,
47 pub enabled: bool,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct WatchExpression {
54 pub id: u64,
56 pub expression: String,
58 pub last_value: Option<String>,
60}
61
62impl DebugContext {
63 pub fn new(agent_id: [u8; 16]) -> Self {
65 use rand::Rng;
66 let mut rng = rand::rng();
67 let mut session_id = [0u8; 16];
68 rng.fill(&mut session_id);
69
70 Self {
71 agent_id,
72 session_id,
73 enabled: false,
74 breakpoints: Vec::new(),
75 watches: Vec::new(),
76 }
77 }
78
79 pub fn enable(&mut self) {
81 self.enabled = true;
82 }
83
84 pub fn disable(&mut self) {
86 self.enabled = false;
87 }
88
89 pub fn add_breakpoint(&mut self, location: String, condition: Option<String>) -> u64 {
91 let id = self.breakpoints.len() as u64;
92 self.breakpoints.push(Breakpoint {
93 id,
94 location,
95 condition,
96 hit_count: 0,
97 enabled: true,
98 });
99 id
100 }
101
102 pub fn remove_breakpoint(&mut self, id: u64) -> bool {
104 if let Some(pos) = self.breakpoints.iter().position(|b| b.id == id) {
105 self.breakpoints.remove(pos);
106 true
107 } else {
108 false
109 }
110 }
111
112 pub fn add_watch(&mut self, expression: String) -> u64 {
114 let id = self.watches.len() as u64;
115 self.watches.push(WatchExpression {
116 id,
117 expression,
118 last_value: None,
119 });
120 id
121 }
122
123 pub fn remove_watch(&mut self, id: u64) -> bool {
125 if let Some(pos) = self.watches.iter().position(|w| w.id == id) {
126 self.watches.remove(pos);
127 true
128 } else {
129 false
130 }
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn test_debug_context_creation() {
140 let agent_id = [1u8; 16];
141 let context = DebugContext::new(agent_id);
142
143 assert_eq!(context.agent_id, agent_id);
144 assert!(!context.enabled);
145 assert!(context.breakpoints.is_empty());
146 assert!(context.watches.is_empty());
147 }
148
149 #[test]
150 fn test_debug_context_enable_disable() {
151 let agent_id = [1u8; 16];
152 let mut context = DebugContext::new(agent_id);
153
154 assert!(!context.enabled);
155 context.enable();
156 assert!(context.enabled);
157 context.disable();
158 assert!(!context.enabled);
159 }
160
161 #[test]
162 fn test_debug_context_breakpoints() {
163 let agent_id = [1u8; 16];
164 let mut context = DebugContext::new(agent_id);
165
166 let bp_id = context.add_breakpoint("main".to_string(), None);
167 assert_eq!(context.breakpoints.len(), 1);
168
169 let removed = context.remove_breakpoint(bp_id);
170 assert!(removed);
171 assert_eq!(context.breakpoints.len(), 0);
172 }
173
174 #[test]
175 fn test_debug_context_watches() {
176 let agent_id = [1u8; 16];
177 let mut context = DebugContext::new(agent_id);
178
179 let watch_id = context.add_watch("variable_x".to_string());
180 assert_eq!(context.watches.len(), 1);
181
182 let removed = context.remove_watch(watch_id);
183 assert!(removed);
184 assert_eq!(context.watches.len(), 0);
185 }
186}