aboutsummaryrefslogtreecommitdiff
path: root/helix-dap/src/client.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-dap/src/client.rs')
-rw-r--r--helix-dap/src/client.rs108
1 files changed, 60 insertions, 48 deletions
diff --git a/helix-dap/src/client.rs b/helix-dap/src/client.rs
index 03e58757..f648b248 100644
--- a/helix-dap/src/client.rs
+++ b/helix-dap/src/client.rs
@@ -2,15 +2,22 @@ use crate::{
transport::{Event, Payload, Request, Response, Transport},
Result,
};
+use log::{error, info};
use serde::{Deserialize, Serialize};
use serde_json::{from_value, to_value, Value};
-use std::process::Stdio;
-use std::sync::atomic::{AtomicU64, Ordering};
+use std::sync::{
+ atomic::{AtomicU64, Ordering},
+ Arc,
+};
+use std::{collections::HashMap, process::Stdio};
use tokio::{
io::{AsyncBufRead, AsyncWrite, BufReader, BufWriter},
net::TcpStream,
process::{Child, Command},
- sync::mpsc::{channel, UnboundedReceiver, UnboundedSender},
+ sync::{
+ mpsc::{channel, Receiver, Sender, UnboundedReceiver, UnboundedSender},
+ Mutex,
+ },
};
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
@@ -252,9 +259,9 @@ pub struct Client {
id: usize,
_process: Option<Child>,
server_tx: UnboundedSender<Request>,
- server_rx: UnboundedReceiver<Payload>,
request_counter: AtomicU64,
capabilities: Option<DebuggerCapabilities>,
+ awaited_events: Arc<Mutex<HashMap<String, Sender<Event>>>>,
}
impl Client {
@@ -270,14 +277,52 @@ impl Client {
id,
_process: process,
server_tx,
- server_rx,
request_counter: AtomicU64::new(0),
capabilities: None,
+ awaited_events: Arc::new(Mutex::new(HashMap::default())),
};
+ tokio::spawn(Self::recv(Arc::clone(&client.awaited_events), server_rx));
+
Ok(client)
}
+ async fn recv(
+ awaited_events: Arc<Mutex<HashMap<String, Sender<Event>>>>,
+ mut server_rx: UnboundedReceiver<Payload>,
+ ) {
+ while let Some(msg) = server_rx.recv().await {
+ match msg {
+ Payload::Event(ev) => {
+ let name = ev.event.clone();
+ let tx = awaited_events.lock().await.remove(&name);
+
+ match tx {
+ Some(tx) => match tx.send(ev).await {
+ Ok(_) => (),
+ Err(_) => error!(
+ "Tried sending event into a closed channel (name={:?})",
+ name
+ ),
+ },
+ None => {
+ info!("unhandled event");
+ // client_tx.send(Payload::Event(ev)).expect("Failed to send");
+ }
+ }
+ }
+ Payload::Response(_) => unreachable!(),
+ Payload::Request(_) => todo!(),
+ }
+ }
+ }
+
+ pub async fn listen_for_event(&self, name: String) -> Receiver<Event> {
+ let (rx, tx) = channel(1);
+ self.awaited_events.lock().await.insert(name.clone(), rx);
+ tx
+ }
+
pub async fn tcp(addr: std::net::SocketAddr, id: usize) -> Result<Self> {
let stream = TcpStream::connect(addr).await?;
let (rx, tx) = stream.into_split();
@@ -373,45 +418,25 @@ impl Client {
}
pub async fn launch(&mut self, args: impl Serialize) -> Result<()> {
+ let mut initialized = self.listen_for_event("initialized".to_owned()).await;
+
self.request("launch".to_owned(), to_value(args).ok())
.await?;
- match self
- .server_rx
- .recv()
- .await
- .expect("Expected initialized event")
- {
- Payload::Event(Event { event, .. }) => {
- if event == *"initialized" {
- Ok(())
- } else {
- unreachable!()
- }
- }
- _ => unreachable!(),
- }
+ initialized.recv().await;
+
+ Ok(())
}
pub async fn attach(&mut self, args: impl Serialize) -> Result<()> {
+ let mut initialized = self.listen_for_event("initialized".to_owned()).await;
+
self.request("attach".to_owned(), to_value(args).ok())
.await?;
- match self
- .server_rx
- .recv()
- .await
- .expect("Expected initialized event")
- {
- Payload::Event(Event { event, .. }) => {
- if event == *"initialized" {
- Ok(())
- } else {
- unreachable!()
- }
- }
- _ => unreachable!(),
- }
+ initialized.recv().await;
+
+ Ok(())
}
pub async fn set_breakpoints(
@@ -447,19 +472,6 @@ impl Client {
Ok(())
}
- pub async fn wait_for_stopped(&mut self) -> Result<()> {
- match self.server_rx.recv().await.expect("Expected stopped event") {
- Payload::Event(Event { event, .. }) => {
- if event == *"stopped" {
- Ok(())
- } else {
- unreachable!()
- }
- }
- _ => unreachable!(),
- }
- }
-
pub async fn continue_thread(&mut self, thread_id: usize) -> Result<Option<bool>> {
let args = ContinueArguments { thread_id };