on master help sign in
dap: Significantly simplify code using the Request trait
184abdcBlaž Hrastnik
helix-dap/examples/dap-dlv.rs+3−3
@@ -1,4 +1,4 @@
1−use helix_dap::{Client, Event, OutputEventBody, Result, SourceBreakpoint, StoppedEventBody};
1+use helix_dap::{events, Client, Event, Result, SourceBreakpoint};
2use serde::{Deserialize, Serialize};
2use serde::{Deserialize, Serialize};
3use serde_json::from_value;
3use serde_json::from_value;
4use tokio::sync::mpsc::Receiver;
4use tokio::sync::mpsc::Receiver;
@@ -12,7 +12,7 @@ struct LaunchArguments {
12
12
13async fn output(mut output_event: Receiver<Event>) {
13async fn output(mut output_event: Receiver<Event>) {
14 loop {
14 loop {
15− let body: OutputEventBody =
15+ let body: events::Output =
16 from_value(output_event.recv().await.unwrap().body.unwrap()).unwrap();
16 from_value(output_event.recv().await.unwrap().body.unwrap()).unwrap();
17 println!(
17 println!(
18 "> [{}] {}",
18 "> [{}] {}",
@@ -77,7 +77,7 @@ pub async fn main() -> Result<()> {
77
77
78 println!("configurationDone: {:?}", client.configuration_done().await);
78 println!("configurationDone: {:?}", client.configuration_done().await);
79
79
80− let stop: StoppedEventBody =
80+ let stop: events::Stopped =
81 from_value(stopped_event.recv().await.unwrap().body.unwrap()).unwrap();
81 from_value(stopped_event.recv().await.unwrap().body.unwrap()).unwrap();
82 println!("stopped: {:?}", stop);
82 println!("stopped: {:?}", stop);
83
83
helix-dap/examples/dap-lldb.rs+3−3
@@ -1,4 +1,4 @@
1−use helix_dap::{Client, Event, OutputEventBody, Result, SourceBreakpoint, StoppedEventBody};
1+use helix_dap::{events, Client, Event, Result, SourceBreakpoint};
2use serde::{Deserialize, Serialize};
2use serde::{Deserialize, Serialize};
3use serde_json::from_value;
3use serde_json::from_value;
4use tokio::sync::mpsc::Receiver;
4use tokio::sync::mpsc::Receiver;
@@ -12,7 +12,7 @@ struct LaunchArguments {
12
12
13async fn output(mut output_event: Receiver<Event>) {
13async fn output(mut output_event: Receiver<Event>) {
14 loop {
14 loop {
15− let body: OutputEventBody =
15+ let body: events::Output =
16 from_value(output_event.recv().await.unwrap().body.unwrap()).unwrap();
16 from_value(output_event.recv().await.unwrap().body.unwrap()).unwrap();
17 println!(
17 println!(
18 "> [{}] {}",
18 "> [{}] {}",
@@ -77,7 +77,7 @@ pub async fn main() -> Result<()> {
77
77
78 println!("configurationDone: {:?}", client.configuration_done().await);
78 println!("configurationDone: {:?}", client.configuration_done().await);
79
79
80− let stop: StoppedEventBody =
80+ let stop: events::Stopped =
81 from_value(stopped_event.recv().await.unwrap().body.unwrap()).unwrap();
81 from_value(stopped_event.recv().await.unwrap().body.unwrap()).unwrap();
82 println!("stopped: {:?}", stop);
82 println!("stopped: {:?}", stop);
83
83
helix-dap/src/client.rs+31−56
@@ -1,11 +1,9 @@
1use crate::{
1use crate::{
2− transport::{Event, Payload, Request, Response, Transport},
2+ transport::{Event, Payload, Request, Transport},
3 types::*,
3 types::*,
4 Result,
4 Result,
5};
5};
6pub use log::{error, info};
6pub use log::{error, info};
7−use serde::Serialize;
8−use serde_json::{from_value, to_value, Value};
9use std::{
7use std::{
10 collections::HashMap,
8 collections::HashMap,
11 net::{IpAddr, Ipv4Addr},
9 net::{IpAddr, Ipv4Addr},
@@ -184,13 +182,18 @@ impl Client {
184 self.request_counter.fetch_add(1, Ordering::Relaxed)
182 self.request_counter.fetch_add(1, Ordering::Relaxed)
185 }
183 }
186
184
187− async fn request(&self, command: String, arguments: Option<Value>) -> Result<Response> {
185+ async fn request<R: crate::types::Request>(
186+ &self,
187+ arguments: R::Arguments,
188+ ) -> Result<R::Result> {
188 let (callback_rx, mut callback_tx) = channel(1);
189 let (callback_rx, mut callback_tx) = channel(1);
189
190
191+ let arguments = Some(serde_json::to_value(arguments)?);
192+
190 let req = Request {
193 let req = Request {
191 back_ch: Some(callback_rx),
194 back_ch: Some(callback_rx),
192 seq: self.next_request_id(),
195 seq: self.next_request_id(),
193− command,
196+ command: R::COMMAND.to_string(),
194 arguments,
197 arguments,
195 };
198 };
196
199
@@ -198,7 +201,9 @@ impl Client {
198 .send(req)
201 .send(req)
199 .expect("Failed to send request to debugger");
202 .expect("Failed to send request to debugger");
200
203
201− Ok(callback_tx.recv().await.unwrap()?)
204+ let response = callback_tx.recv().await.unwrap()?;
205+ let response = serde_json::from_value(response.body.unwrap_or_default())?;
206+ Ok(response)
202 }
207 }
203
208
204 pub fn capabilities(&self) -> &DebuggerCapabilities {
209 pub fn capabilities(&self) -> &DebuggerCapabilities {
@@ -224,33 +229,30 @@ impl Client {
224 supports_invalidated_event: Some(false),
229 supports_invalidated_event: Some(false),
225 };
230 };
226
231
227− let response = self
232+ let response = self.request::<requests::Initialize>(args).await?;
228− .request("initialize".to_owned(), to_value(args).ok())
229− .await?;
230− self.capabilities = from_value(response.body.unwrap()).ok();
233+ self.capabilities = Some(response);
231
234
232 Ok(())
235 Ok(())
233 }
236 }
234
237
235 pub async fn disconnect(&mut self) -> Result<()> {
238 pub async fn disconnect(&mut self) -> Result<()> {
236− self.request("disconnect".to_owned(), None).await?;
239+ self.request::<requests::Disconnect>(()).await
237− Ok(())
238 }
240 }
239
241
240− pub async fn launch(&mut self, args: impl Serialize) -> Result<()> {
242+ pub async fn launch(&mut self, args: serde_json::Value) -> Result<()> {
241 let mut initialized = self.listen_for_event("initialized".to_owned()).await;
243 let mut initialized = self.listen_for_event("initialized".to_owned()).await;
242
244
243− let res = self.request("launch".to_owned(), to_value(args).ok());
245+ let res = self.request::<requests::Launch>(args);
244 let ev = initialized.recv();
246 let ev = initialized.recv();
245 join!(res, ev).0?;
247 join!(res, ev).0?;
246
248
247 Ok(())
249 Ok(())
248 }
250 }
249
251
250− pub async fn attach(&mut self, args: impl Serialize) -> Result<()> {
252+ pub async fn attach(&mut self, args: serde_json::Value) -> Result<()> {
251 let mut initialized = self.listen_for_event("initialized".to_owned()).await;
253 let mut initialized = self.listen_for_event("initialized".to_owned()).await;
252
254
253− let res = self.request("attach".to_owned(), to_value(args).ok());
255+ let res = self.request::<requests::Attach>(args);
254 let ev = initialized.recv();
256 let ev = initialized.recv();
255 join!(res, ev).0?;
257 join!(res, ev).0?;
256
258
@@ -277,29 +279,20 @@ impl Client {
277 source_modified: Some(false),
279 source_modified: Some(false),
278 };
280 };
279
281
280− let response = self
282+ let response = self.request::<requests::SetBreakpoints>(args).await?;
281− .request("setBreakpoints".to_owned(), to_value(args).ok())
282− .await?;
283− let body: Option<requests::SetBreakpointsResponse> = from_value(response.body.unwrap()).ok();
284
283
285− Ok(body.map(|b| b.breakpoints).unwrap())
284+ Ok(response.breakpoints)
286 }
285 }
287
286
288 pub async fn configuration_done(&mut self) -> Result<()> {
287 pub async fn configuration_done(&mut self) -> Result<()> {
289− self.request("configurationDone".to_owned(), None).await?;
288+ self.request::<requests::ConfigurationDone>(()).await
290− Ok(())
291 }
289 }
292
290
293 pub async fn continue_thread(&mut self, thread_id: usize) -> Result<Option<bool>> {
291 pub async fn continue_thread(&mut self, thread_id: usize) -> Result<Option<bool>> {
294 let args = requests::ContinueArguments { thread_id };
292 let args = requests::ContinueArguments { thread_id };
295
293
296− let response = self
294+ let response = self.request::<requests::Continue>(args).await?;
297− .request("continue".to_owned(), to_value(args).ok())
298− .await?;
299−
300− let body: Option<requests::ContinueResponse> = from_value(response.body.unwrap()).ok();
301−
302− Ok(body.map(|b| b.all_threads_continued).unwrap())
295+ Ok(response.all_threads_continued)
303 }
296 }
304
297
305 pub async fn stack_trace(
298 pub async fn stack_trace(
@@ -313,33 +306,20 @@ impl Client {
313 format: None,
306 format: None,
314 };
307 };
315
308
316− let response = self
309+ let response = self.request::<requests::StackTrace>(args).await?;
317− .request("stackTrace".to_owned(), to_value(args).ok())
318− .await?;
319−
320− let body: requests::StackTraceResponse = from_value(response.body.unwrap()).unwrap();
321−
322− Ok((body.stack_frames, body.total_frames))
310+ Ok((response.stack_frames, response.total_frames))
323 }
311 }
324
312
325 pub async fn threads(&mut self) -> Result<Vec<Thread>> {
313 pub async fn threads(&mut self) -> Result<Vec<Thread>> {
326− let response = self.request("threads".to_owned(), None).await?;
314+ let response = self.request::<requests::Threads>(()).await?;
327−
328− let body: requests::ThreadsResponse = from_value(response.body.unwrap()).unwrap();
329−
330− Ok(body.threads)
315+ Ok(response.threads)
331 }
316 }
332
317
333 pub async fn scopes(&mut self, frame_id: usize) -> Result<Vec<Scope>> {
318 pub async fn scopes(&mut self, frame_id: usize) -> Result<Vec<Scope>> {
334 let args = requests::ScopesArguments { frame_id };
319 let args = requests::ScopesArguments { frame_id };
335
320
336− let response = self
321+ let response = self.request::<requests::Scopes>(args).await?;
337− .request("scopes".to_owned(), to_value(args).ok())
338− .await?;
339−
340− let body: requests::ScopesResponse = from_value(response.body.unwrap()).unwrap();
341−
342− Ok(body.scopes)
322+ Ok(response.scopes)
343 }
323 }
344
324
345 pub async fn variables(&mut self, variables_reference: usize) -> Result<Vec<Variable>> {
325 pub async fn variables(&mut self, variables_reference: usize) -> Result<Vec<Variable>> {
@@ -351,12 +331,7 @@ impl Client {
351 format: None,
331 format: None,
352 };
332 };
353
333
354− let response = self
334+ let response = self.request::<requests::Variables>(args).await?;
355− .request("variables".to_owned(), to_value(args).ok())
356− .await?;
357−
358− let body: requests::VariablesResponse = from_value(response.body.unwrap()).unwrap();
359−
360− Ok(body.variables)
335+ Ok(response.variables)
361 }
336 }
362}
337}
helix-dap/src/types.rs+45
@@ -229,6 +229,51 @@ pub mod requests {
229 pub supports_invalidated_event: Option<bool>,
229 pub supports_invalidated_event: Option<bool>,
230 }
230 }
231
231
232+ #[derive(Debug)]
233+ pub enum Initialize {}
234+
235+ impl Request for Initialize {
236+ type Arguments = InitializeArguments;
237+ type Result = DebuggerCapabilities;
238+ const COMMAND: &'static str = "initialize";
239+ }
240+
241+ #[derive(Debug)]
242+ pub enum Launch {}
243+
244+ impl Request for Launch {
245+ type Arguments = Value;
246+ type Result = Value;
247+ const COMMAND: &'static str = "launch";
248+ }
249+
250+ #[derive(Debug)]
251+ pub enum Attach {}
252+
253+ impl Request for Attach {
254+ type Arguments = Value;
255+ type Result = Value;
256+ const COMMAND: &'static str = "attach";
257+ }
258+
259+ #[derive(Debug)]
260+ pub enum Disconnect {}
261+
262+ impl Request for Disconnect {
263+ type Arguments = ();
264+ type Result = ();
265+ const COMMAND: &'static str = "disconnect";
266+ }
267+
268+ #[derive(Debug)]
269+ pub enum ConfigurationDone {}
270+
271+ impl Request for ConfigurationDone {
272+ type Arguments = ();
273+ type Result = ();
274+ const COMMAND: &'static str = "configurationDone";
275+ }
276+
232 #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
277 #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
233 #[serde(rename_all = "camelCase")]
278 #[serde(rename_all = "camelCase")]
234 pub struct SetBreakpointsArguments {
279 pub struct SetBreakpointsArguments {