1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct Source {
6 pub name: Option<String>,
7 pub path: Option<String>,
8 #[serde(rename = "sourceReference")]
9 pub source_reference: Option<i64>,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Breakpoint {
14 pub id: Option<i64>,
15 #[serde(default)]
16 pub verified: bool,
17 pub message: Option<String>,
18 pub source: Option<Source>,
19 pub line: Option<i64>,
20 pub column: Option<i64>,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct SourceBreakpoint {
25 pub line: i64,
26 pub column: Option<i64>,
27 pub condition: Option<String>,
28 #[serde(rename = "hitCondition")]
29 pub hit_condition: Option<String>,
30 #[serde(rename = "logMessage")]
31 pub log_message: Option<String>,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct StackFrame {
36 pub id: i64,
37 pub name: String,
38 pub source: Option<Source>,
39 pub line: i64,
40 pub column: i64,
41 #[serde(rename = "endLine")]
42 pub end_line: Option<i64>,
43 #[serde(rename = "endColumn")]
44 pub end_column: Option<i64>,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct Thread {
49 pub id: i64,
50 pub name: String,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct Variable {
55 pub name: String,
56 pub value: String,
57 #[serde(rename = "type")]
58 pub var_type: Option<String>,
59 #[serde(rename = "variablesReference")]
60 pub variables_reference: i64,
61 #[serde(rename = "namedVariables")]
62 pub named_variables: Option<i64>,
63 #[serde(rename = "indexedVariables")]
64 pub indexed_variables: Option<i64>,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct Scope {
69 pub name: String,
70 #[serde(rename = "variablesReference")]
71 pub variables_reference: i64,
72 pub expensive: bool,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(rename_all = "camelCase")]
77pub struct LaunchRequestArguments {
78 pub program: String,
79 pub args: Option<Vec<String>>,
80 pub cwd: Option<String>,
81 pub env: Option<HashMap<String, String>>,
82 pub stop_on_entry: Option<bool>,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
86pub enum DebugState {
87 Stopped,
88 Initialized,
89 Running,
90 Paused,
91 Terminated,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct DebugSession {
96 pub id: String,
97 pub name: String,
98 pub state: DebugState,
99 pub adapter_type: String,
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn test_debug_session_serialization() {
108 let session = DebugSession {
109 id: "session-1".to_string(),
110 name: "Debug Main".to_string(),
111 state: DebugState::Running,
112 adapter_type: "cppdbg".to_string(),
113 };
114
115 let json = serde_json::to_string(&session).expect("Failed to serialize DebugSession");
117
118 assert!(json.contains("session-1"));
120 assert!(json.contains("Debug Main"));
121 assert!(json.contains("Running"));
122 assert!(json.contains("cppdbg"));
123
124 let deserialized: DebugSession =
126 serde_json::from_str(&json).expect("Failed to deserialize DebugSession");
127 assert_eq!(deserialized.id, session.id);
128 assert_eq!(deserialized.name, session.name);
129 assert_eq!(deserialized.state, session.state);
130 assert_eq!(deserialized.adapter_type, session.adapter_type);
131
132 for state in [
134 DebugState::Stopped,
135 DebugState::Initialized,
136 DebugState::Running,
137 DebugState::Paused,
138 DebugState::Terminated,
139 ] {
140 let s = DebugSession {
141 id: "test".to_string(),
142 name: "test".to_string(),
143 state: state.clone(),
144 adapter_type: "test-adapter".to_string(),
145 };
146 let json = serde_json::to_string(&s).unwrap();
147 let roundtrip: DebugSession = serde_json::from_str(&json).unwrap();
148 assert_eq!(roundtrip.state, state);
149 }
150 }
151
152 #[test]
153 fn test_breakpoint_serialization() {
154 let bp = Breakpoint {
156 id: Some(42),
157 verified: true,
158 message: Some("Breakpoint set".to_string()),
159 source: Some(Source {
160 name: Some("main.rs".to_string()),
161 path: Some("/src/main.rs".to_string()),
162 source_reference: None,
163 }),
164 line: Some(10),
165 column: Some(5),
166 };
167
168 let json = serde_json::to_string(&bp).expect("Failed to serialize Breakpoint");
169 let roundtrip: Breakpoint = serde_json::from_str(&json).expect("Failed to deserialize Breakpoint");
170 assert_eq!(roundtrip.id, bp.id);
171 assert_eq!(roundtrip.verified, bp.verified);
172 assert_eq!(roundtrip.message, bp.message);
173 assert_eq!(roundtrip.line, bp.line);
174 assert_eq!(roundtrip.column, bp.column);
175
176 let sbp = SourceBreakpoint {
178 line: 25,
179 column: Some(8),
180 condition: Some("x > 0".to_string()),
181 hit_condition: Some("5".to_string()),
182 log_message: Some("Hit breakpoint at line 25".to_string()),
183 };
184
185 let json = serde_json::to_string(&sbp).expect("Failed to serialize SourceBreakpoint");
186 let roundtrip: SourceBreakpoint =
187 serde_json::from_str(&json).expect("Failed to deserialize SourceBreakpoint");
188 assert_eq!(roundtrip.line, sbp.line);
189 assert_eq!(roundtrip.column, sbp.column);
190 assert_eq!(roundtrip.condition, sbp.condition);
191 assert_eq!(roundtrip.hit_condition, sbp.hit_condition);
192 assert_eq!(roundtrip.log_message, sbp.log_message);
193
194 let minimal = SourceBreakpoint {
196 line: 1,
197 column: None,
198 condition: None,
199 hit_condition: None,
200 log_message: None,
201 };
202 let json = serde_json::to_string(&minimal).unwrap();
203 let roundtrip: SourceBreakpoint = serde_json::from_str(&json).unwrap();
204 assert_eq!(roundtrip.line, 1);
205 assert!(roundtrip.column.is_none());
206 }
207}