dap_command.rs

   1use std::sync::Arc;
   2
   3use anyhow::{Context as _, Ok, Result};
   4use base64::Engine;
   5use dap::{
   6    Capabilities, ContinueArguments, ExceptionFilterOptions, InitializeRequestArguments,
   7    InitializeRequestArgumentsPathFormat, NextArguments, SetVariableResponse, SourceBreakpoint,
   8    StepInArguments, StepOutArguments, SteppingGranularity, ValueFormat, Variable,
   9    VariablesArgumentsFilter,
  10    client::SessionId,
  11    proto_conversions::ProtoConversion,
  12    requests::{Continue, Next},
  13};
  14use rpc::proto;
  15use serde_json::Value;
  16use util::ResultExt;
  17
  18pub trait LocalDapCommand: 'static + Send + Sync + std::fmt::Debug {
  19    type Response: 'static + Send + std::fmt::Debug;
  20    type DapRequest: 'static + Send + dap::requests::Request;
  21    /// Is this request idempotent? Is it safe to cache the response for as long as the execution environment is unchanged?
  22    const CACHEABLE: bool = false;
  23
  24    fn is_supported(_capabilities: &Capabilities) -> bool {
  25        true
  26    }
  27
  28    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments;
  29
  30    fn response_from_dap(
  31        &self,
  32        message: <Self::DapRequest as dap::requests::Request>::Response,
  33    ) -> Result<Self::Response>;
  34}
  35
  36pub trait DapCommand: LocalDapCommand {
  37    type ProtoRequest: 'static + Send;
  38    type ProtoResponse: 'static + Send;
  39
  40    #[allow(dead_code)]
  41    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId;
  42
  43    #[allow(dead_code)]
  44    fn from_proto(request: &Self::ProtoRequest) -> Self;
  45
  46    #[allow(unused)]
  47    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest;
  48
  49    #[allow(dead_code)]
  50    fn response_to_proto(
  51        debug_client_id: SessionId,
  52        message: Self::Response,
  53    ) -> Self::ProtoResponse;
  54
  55    #[allow(unused)]
  56    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response>;
  57}
  58
  59impl<T: LocalDapCommand> LocalDapCommand for Arc<T> {
  60    type Response = T::Response;
  61    type DapRequest = T::DapRequest;
  62
  63    fn is_supported(capabilities: &Capabilities) -> bool {
  64        T::is_supported(capabilities)
  65    }
  66
  67    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
  68        T::to_dap(self)
  69    }
  70
  71    fn response_from_dap(
  72        &self,
  73        message: <Self::DapRequest as dap::requests::Request>::Response,
  74    ) -> Result<Self::Response> {
  75        T::response_from_dap(self, message)
  76    }
  77}
  78
  79impl<T: DapCommand> DapCommand for Arc<T> {
  80    type ProtoRequest = T::ProtoRequest;
  81    type ProtoResponse = T::ProtoResponse;
  82
  83    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
  84        T::client_id_from_proto(request)
  85    }
  86
  87    fn from_proto(request: &Self::ProtoRequest) -> Self {
  88        Arc::new(T::from_proto(request))
  89    }
  90
  91    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
  92        T::to_proto(self, debug_client_id, upstream_project_id)
  93    }
  94
  95    fn response_to_proto(
  96        debug_client_id: SessionId,
  97        message: Self::Response,
  98    ) -> Self::ProtoResponse {
  99        T::response_to_proto(debug_client_id, message)
 100    }
 101
 102    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
 103        T::response_from_proto(self, message)
 104    }
 105}
 106
 107#[derive(Debug, Hash, PartialEq, Eq)]
 108pub struct StepCommand {
 109    pub thread_id: u64,
 110    pub granularity: Option<SteppingGranularity>,
 111    pub single_thread: Option<bool>,
 112}
 113
 114impl StepCommand {
 115    fn from_proto(message: proto::DapNextRequest) -> Self {
 116        const LINE: i32 = proto::SteppingGranularity::Line as i32;
 117        const INSTRUCTION: i32 = proto::SteppingGranularity::Instruction as i32;
 118
 119        let granularity = message.granularity.map(|granularity| match granularity {
 120            LINE => SteppingGranularity::Line,
 121            INSTRUCTION => SteppingGranularity::Instruction,
 122            _ => SteppingGranularity::Statement,
 123        });
 124
 125        Self {
 126            thread_id: message.thread_id,
 127            granularity,
 128            single_thread: message.single_thread,
 129        }
 130    }
 131}
 132
 133#[derive(Debug, Hash, PartialEq, Eq)]
 134pub(crate) struct NextCommand {
 135    pub inner: StepCommand,
 136}
 137
 138impl LocalDapCommand for NextCommand {
 139    type Response = <Next as dap::requests::Request>::Response;
 140    type DapRequest = Next;
 141
 142    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 143        NextArguments {
 144            thread_id: self.inner.thread_id,
 145            single_thread: self.inner.single_thread,
 146            granularity: self.inner.granularity,
 147        }
 148    }
 149    fn response_from_dap(
 150        &self,
 151        _message: <Self::DapRequest as dap::requests::Request>::Response,
 152    ) -> Result<Self::Response> {
 153        Ok(())
 154    }
 155}
 156
 157impl DapCommand for NextCommand {
 158    type ProtoRequest = proto::DapNextRequest;
 159    type ProtoResponse = proto::Ack;
 160
 161    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 162        SessionId::from_proto(request.client_id)
 163    }
 164
 165    fn from_proto(request: &Self::ProtoRequest) -> Self {
 166        Self {
 167            inner: StepCommand::from_proto(request.clone()),
 168        }
 169    }
 170
 171    fn response_to_proto(
 172        _debug_client_id: SessionId,
 173        _message: Self::Response,
 174    ) -> Self::ProtoResponse {
 175        proto::Ack {}
 176    }
 177
 178    fn to_proto(
 179        &self,
 180        debug_client_id: SessionId,
 181        upstream_project_id: u64,
 182    ) -> proto::DapNextRequest {
 183        proto::DapNextRequest {
 184            project_id: upstream_project_id,
 185            client_id: debug_client_id.to_proto(),
 186            thread_id: self.inner.thread_id,
 187            single_thread: self.inner.single_thread,
 188            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
 189        }
 190    }
 191
 192    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 193        Ok(())
 194    }
 195}
 196
 197#[derive(Debug, Hash, PartialEq, Eq)]
 198pub(crate) struct StepInCommand {
 199    pub inner: StepCommand,
 200}
 201
 202impl LocalDapCommand for StepInCommand {
 203    type Response = <dap::requests::StepIn as dap::requests::Request>::Response;
 204    type DapRequest = dap::requests::StepIn;
 205
 206    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 207        StepInArguments {
 208            thread_id: self.inner.thread_id,
 209            single_thread: self.inner.single_thread,
 210            target_id: None,
 211            granularity: self.inner.granularity,
 212        }
 213    }
 214
 215    fn response_from_dap(
 216        &self,
 217        _message: <Self::DapRequest as dap::requests::Request>::Response,
 218    ) -> Result<Self::Response> {
 219        Ok(())
 220    }
 221}
 222
 223impl DapCommand for StepInCommand {
 224    type ProtoRequest = proto::DapStepInRequest;
 225    type ProtoResponse = proto::Ack;
 226
 227    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 228        SessionId::from_proto(request.client_id)
 229    }
 230
 231    fn from_proto(request: &Self::ProtoRequest) -> Self {
 232        Self {
 233            inner: StepCommand::from_proto(proto::DapNextRequest {
 234                project_id: request.project_id,
 235                client_id: request.client_id,
 236                thread_id: request.thread_id,
 237                single_thread: request.single_thread,
 238                granularity: request.granularity,
 239            }),
 240        }
 241    }
 242
 243    fn response_to_proto(
 244        _debug_client_id: SessionId,
 245        _message: Self::Response,
 246    ) -> Self::ProtoResponse {
 247        proto::Ack {}
 248    }
 249
 250    fn to_proto(
 251        &self,
 252        debug_client_id: SessionId,
 253        upstream_project_id: u64,
 254    ) -> proto::DapStepInRequest {
 255        proto::DapStepInRequest {
 256            project_id: upstream_project_id,
 257            client_id: debug_client_id.to_proto(),
 258            thread_id: self.inner.thread_id,
 259            single_thread: self.inner.single_thread,
 260            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
 261            target_id: None,
 262        }
 263    }
 264
 265    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 266        Ok(())
 267    }
 268}
 269
 270#[derive(Debug, Hash, PartialEq, Eq)]
 271pub(crate) struct StepOutCommand {
 272    pub inner: StepCommand,
 273}
 274
 275impl LocalDapCommand for StepOutCommand {
 276    type Response = <dap::requests::StepOut as dap::requests::Request>::Response;
 277    type DapRequest = dap::requests::StepOut;
 278
 279    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 280        StepOutArguments {
 281            thread_id: self.inner.thread_id,
 282            single_thread: self.inner.single_thread,
 283            granularity: self.inner.granularity,
 284        }
 285    }
 286
 287    fn response_from_dap(
 288        &self,
 289        _message: <Self::DapRequest as dap::requests::Request>::Response,
 290    ) -> Result<Self::Response> {
 291        Ok(())
 292    }
 293}
 294
 295impl DapCommand for StepOutCommand {
 296    type ProtoRequest = proto::DapStepOutRequest;
 297    type ProtoResponse = proto::Ack;
 298
 299    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 300        SessionId::from_proto(request.client_id)
 301    }
 302
 303    fn from_proto(request: &Self::ProtoRequest) -> Self {
 304        Self {
 305            inner: StepCommand::from_proto(proto::DapNextRequest {
 306                project_id: request.project_id,
 307                client_id: request.client_id,
 308                thread_id: request.thread_id,
 309                single_thread: request.single_thread,
 310                granularity: request.granularity,
 311            }),
 312        }
 313    }
 314
 315    fn response_to_proto(
 316        _debug_client_id: SessionId,
 317        _message: Self::Response,
 318    ) -> Self::ProtoResponse {
 319        proto::Ack {}
 320    }
 321
 322    fn to_proto(
 323        &self,
 324        debug_client_id: SessionId,
 325        upstream_project_id: u64,
 326    ) -> proto::DapStepOutRequest {
 327        proto::DapStepOutRequest {
 328            project_id: upstream_project_id,
 329            client_id: debug_client_id.to_proto(),
 330            thread_id: self.inner.thread_id,
 331            single_thread: self.inner.single_thread,
 332            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
 333        }
 334    }
 335
 336    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 337        Ok(())
 338    }
 339}
 340
 341#[derive(Debug, Hash, PartialEq, Eq)]
 342pub(crate) struct StepBackCommand {
 343    pub inner: StepCommand,
 344}
 345impl LocalDapCommand for StepBackCommand {
 346    type Response = <dap::requests::StepBack as dap::requests::Request>::Response;
 347    type DapRequest = dap::requests::StepBack;
 348
 349    fn is_supported(capabilities: &Capabilities) -> bool {
 350        capabilities.supports_step_back.unwrap_or_default()
 351    }
 352
 353    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 354        dap::StepBackArguments {
 355            thread_id: self.inner.thread_id,
 356            single_thread: self.inner.single_thread,
 357            granularity: self.inner.granularity,
 358        }
 359    }
 360
 361    fn response_from_dap(
 362        &self,
 363        _message: <Self::DapRequest as dap::requests::Request>::Response,
 364    ) -> Result<Self::Response> {
 365        Ok(())
 366    }
 367}
 368
 369impl DapCommand for StepBackCommand {
 370    type ProtoRequest = proto::DapStepBackRequest;
 371    type ProtoResponse = proto::Ack;
 372
 373    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 374        SessionId::from_proto(request.client_id)
 375    }
 376
 377    fn from_proto(request: &Self::ProtoRequest) -> Self {
 378        Self {
 379            inner: StepCommand::from_proto(proto::DapNextRequest {
 380                project_id: request.project_id,
 381                client_id: request.client_id,
 382                thread_id: request.thread_id,
 383                single_thread: request.single_thread,
 384                granularity: request.granularity,
 385            }),
 386        }
 387    }
 388
 389    fn response_to_proto(
 390        _debug_client_id: SessionId,
 391        _message: Self::Response,
 392    ) -> Self::ProtoResponse {
 393        proto::Ack {}
 394    }
 395
 396    fn to_proto(
 397        &self,
 398        debug_client_id: SessionId,
 399        upstream_project_id: u64,
 400    ) -> proto::DapStepBackRequest {
 401        proto::DapStepBackRequest {
 402            project_id: upstream_project_id,
 403            client_id: debug_client_id.to_proto(),
 404            thread_id: self.inner.thread_id,
 405            single_thread: self.inner.single_thread,
 406            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
 407        }
 408    }
 409
 410    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 411        Ok(())
 412    }
 413}
 414
 415#[derive(Debug, Hash, PartialEq, Eq)]
 416pub(crate) struct ContinueCommand {
 417    pub args: ContinueArguments,
 418}
 419
 420impl LocalDapCommand for ContinueCommand {
 421    type Response = <Continue as dap::requests::Request>::Response;
 422    type DapRequest = Continue;
 423
 424    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 425        self.args.clone()
 426    }
 427
 428    fn response_from_dap(
 429        &self,
 430        message: <Self::DapRequest as dap::requests::Request>::Response,
 431    ) -> Result<Self::Response> {
 432        Ok(message)
 433    }
 434}
 435
 436impl DapCommand for ContinueCommand {
 437    type ProtoRequest = proto::DapContinueRequest;
 438    type ProtoResponse = proto::DapContinueResponse;
 439
 440    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 441        SessionId::from_proto(request.client_id)
 442    }
 443
 444    fn to_proto(
 445        &self,
 446        debug_client_id: SessionId,
 447        upstream_project_id: u64,
 448    ) -> proto::DapContinueRequest {
 449        proto::DapContinueRequest {
 450            project_id: upstream_project_id,
 451            client_id: debug_client_id.to_proto(),
 452            thread_id: self.args.thread_id,
 453            single_thread: self.args.single_thread,
 454        }
 455    }
 456
 457    fn from_proto(request: &Self::ProtoRequest) -> Self {
 458        Self {
 459            args: ContinueArguments {
 460                thread_id: request.thread_id,
 461                single_thread: request.single_thread,
 462            },
 463        }
 464    }
 465
 466    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
 467        Ok(Self::Response {
 468            all_threads_continued: message.all_threads_continued,
 469        })
 470    }
 471
 472    fn response_to_proto(
 473        debug_client_id: SessionId,
 474        message: Self::Response,
 475    ) -> Self::ProtoResponse {
 476        proto::DapContinueResponse {
 477            client_id: debug_client_id.to_proto(),
 478            all_threads_continued: message.all_threads_continued,
 479        }
 480    }
 481}
 482
 483#[derive(Debug, Hash, PartialEq, Eq)]
 484pub(crate) struct PauseCommand {
 485    pub thread_id: u64,
 486}
 487
 488impl LocalDapCommand for PauseCommand {
 489    type Response = <dap::requests::Pause as dap::requests::Request>::Response;
 490    type DapRequest = dap::requests::Pause;
 491    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 492        dap::PauseArguments {
 493            thread_id: self.thread_id,
 494        }
 495    }
 496
 497    fn response_from_dap(
 498        &self,
 499        _message: <Self::DapRequest as dap::requests::Request>::Response,
 500    ) -> Result<Self::Response> {
 501        Ok(())
 502    }
 503}
 504
 505impl DapCommand for PauseCommand {
 506    type ProtoRequest = proto::DapPauseRequest;
 507    type ProtoResponse = proto::Ack;
 508
 509    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 510        SessionId::from_proto(request.client_id)
 511    }
 512
 513    fn from_proto(request: &Self::ProtoRequest) -> Self {
 514        Self {
 515            thread_id: request.thread_id,
 516        }
 517    }
 518
 519    fn to_proto(
 520        &self,
 521        debug_client_id: SessionId,
 522        upstream_project_id: u64,
 523    ) -> proto::DapPauseRequest {
 524        proto::DapPauseRequest {
 525            project_id: upstream_project_id,
 526            client_id: debug_client_id.to_proto(),
 527            thread_id: self.thread_id,
 528        }
 529    }
 530
 531    fn response_to_proto(
 532        _debug_client_id: SessionId,
 533        _message: Self::Response,
 534    ) -> Self::ProtoResponse {
 535        proto::Ack {}
 536    }
 537
 538    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 539        Ok(())
 540    }
 541}
 542
 543#[derive(Debug, Hash, PartialEq, Eq)]
 544pub(crate) struct DisconnectCommand {
 545    pub restart: Option<bool>,
 546    pub terminate_debuggee: Option<bool>,
 547    pub suspend_debuggee: Option<bool>,
 548}
 549
 550impl LocalDapCommand for DisconnectCommand {
 551    type Response = <dap::requests::Disconnect as dap::requests::Request>::Response;
 552    type DapRequest = dap::requests::Disconnect;
 553
 554    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 555        dap::DisconnectArguments {
 556            restart: self.restart,
 557            terminate_debuggee: self.terminate_debuggee,
 558            suspend_debuggee: self.suspend_debuggee,
 559        }
 560    }
 561
 562    fn response_from_dap(
 563        &self,
 564        _message: <Self::DapRequest as dap::requests::Request>::Response,
 565    ) -> Result<Self::Response> {
 566        Ok(())
 567    }
 568}
 569
 570impl DapCommand for DisconnectCommand {
 571    type ProtoRequest = proto::DapDisconnectRequest;
 572    type ProtoResponse = proto::Ack;
 573
 574    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 575        SessionId::from_proto(request.client_id)
 576    }
 577
 578    fn from_proto(request: &Self::ProtoRequest) -> Self {
 579        Self {
 580            restart: request.restart,
 581            terminate_debuggee: request.terminate_debuggee,
 582            suspend_debuggee: request.suspend_debuggee,
 583        }
 584    }
 585
 586    fn to_proto(
 587        &self,
 588        debug_client_id: SessionId,
 589        upstream_project_id: u64,
 590    ) -> proto::DapDisconnectRequest {
 591        proto::DapDisconnectRequest {
 592            project_id: upstream_project_id,
 593            client_id: debug_client_id.to_proto(),
 594            restart: self.restart,
 595            terminate_debuggee: self.terminate_debuggee,
 596            suspend_debuggee: self.suspend_debuggee,
 597        }
 598    }
 599
 600    fn response_to_proto(
 601        _debug_client_id: SessionId,
 602        _message: Self::Response,
 603    ) -> Self::ProtoResponse {
 604        proto::Ack {}
 605    }
 606
 607    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 608        Ok(())
 609    }
 610}
 611
 612#[derive(Debug, Hash, PartialEq, Eq)]
 613pub(crate) struct TerminateThreadsCommand {
 614    pub thread_ids: Option<Vec<u64>>,
 615}
 616
 617impl LocalDapCommand for TerminateThreadsCommand {
 618    type Response = <dap::requests::TerminateThreads as dap::requests::Request>::Response;
 619    type DapRequest = dap::requests::TerminateThreads;
 620
 621    fn is_supported(capabilities: &Capabilities) -> bool {
 622        capabilities
 623            .supports_terminate_threads_request
 624            .unwrap_or_default()
 625    }
 626
 627    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 628        dap::TerminateThreadsArguments {
 629            thread_ids: self.thread_ids.clone(),
 630        }
 631    }
 632
 633    fn response_from_dap(
 634        &self,
 635        _message: <Self::DapRequest as dap::requests::Request>::Response,
 636    ) -> Result<Self::Response> {
 637        Ok(())
 638    }
 639}
 640
 641impl DapCommand for TerminateThreadsCommand {
 642    type ProtoRequest = proto::DapTerminateThreadsRequest;
 643    type ProtoResponse = proto::Ack;
 644
 645    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 646        SessionId::from_proto(request.client_id)
 647    }
 648
 649    fn from_proto(request: &Self::ProtoRequest) -> Self {
 650        let thread_ids = if request.thread_ids.is_empty() {
 651            None
 652        } else {
 653            Some(request.thread_ids.clone())
 654        };
 655
 656        Self { thread_ids }
 657    }
 658
 659    fn to_proto(
 660        &self,
 661        debug_client_id: SessionId,
 662        upstream_project_id: u64,
 663    ) -> proto::DapTerminateThreadsRequest {
 664        proto::DapTerminateThreadsRequest {
 665            project_id: upstream_project_id,
 666            client_id: debug_client_id.to_proto(),
 667            thread_ids: self.thread_ids.clone().unwrap_or_default(),
 668        }
 669    }
 670
 671    fn response_to_proto(
 672        _debug_client_id: SessionId,
 673        _message: Self::Response,
 674    ) -> Self::ProtoResponse {
 675        proto::Ack {}
 676    }
 677
 678    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 679        Ok(())
 680    }
 681}
 682
 683#[derive(Debug, Hash, PartialEq, Eq)]
 684pub(crate) struct TerminateCommand {
 685    pub restart: Option<bool>,
 686}
 687
 688impl LocalDapCommand for TerminateCommand {
 689    type Response = <dap::requests::Terminate as dap::requests::Request>::Response;
 690    type DapRequest = dap::requests::Terminate;
 691
 692    fn is_supported(capabilities: &Capabilities) -> bool {
 693        capabilities.supports_terminate_request.unwrap_or_default()
 694    }
 695    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 696        dap::TerminateArguments {
 697            restart: self.restart,
 698        }
 699    }
 700
 701    fn response_from_dap(
 702        &self,
 703        _message: <Self::DapRequest as dap::requests::Request>::Response,
 704    ) -> Result<Self::Response> {
 705        Ok(())
 706    }
 707}
 708
 709impl DapCommand for TerminateCommand {
 710    type ProtoRequest = proto::DapTerminateRequest;
 711    type ProtoResponse = proto::Ack;
 712
 713    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 714        SessionId::from_proto(request.client_id)
 715    }
 716
 717    fn from_proto(request: &Self::ProtoRequest) -> Self {
 718        Self {
 719            restart: request.restart,
 720        }
 721    }
 722
 723    fn to_proto(
 724        &self,
 725        debug_client_id: SessionId,
 726        upstream_project_id: u64,
 727    ) -> proto::DapTerminateRequest {
 728        proto::DapTerminateRequest {
 729            project_id: upstream_project_id,
 730            client_id: debug_client_id.to_proto(),
 731            restart: self.restart,
 732        }
 733    }
 734
 735    fn response_to_proto(
 736        _debug_client_id: SessionId,
 737        _message: Self::Response,
 738    ) -> Self::ProtoResponse {
 739        proto::Ack {}
 740    }
 741
 742    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 743        Ok(())
 744    }
 745}
 746
 747#[derive(Debug, Hash, PartialEq, Eq)]
 748pub(crate) struct RestartCommand {
 749    pub raw: serde_json::Value,
 750}
 751
 752impl LocalDapCommand for RestartCommand {
 753    type Response = <dap::requests::Restart as dap::requests::Request>::Response;
 754    type DapRequest = dap::requests::Restart;
 755
 756    fn is_supported(capabilities: &Capabilities) -> bool {
 757        capabilities.supports_restart_request.unwrap_or_default()
 758    }
 759
 760    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 761        dap::RestartArguments {
 762            raw: self.raw.clone(),
 763        }
 764    }
 765
 766    fn response_from_dap(
 767        &self,
 768        _message: <Self::DapRequest as dap::requests::Request>::Response,
 769    ) -> Result<Self::Response> {
 770        Ok(())
 771    }
 772}
 773
 774impl DapCommand for RestartCommand {
 775    type ProtoRequest = proto::DapRestartRequest;
 776    type ProtoResponse = proto::Ack;
 777
 778    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 779        SessionId::from_proto(request.client_id)
 780    }
 781
 782    fn from_proto(request: &Self::ProtoRequest) -> Self {
 783        Self {
 784            raw: serde_json::from_slice(&request.raw_args)
 785                .log_err()
 786                .unwrap_or(serde_json::Value::Null),
 787        }
 788    }
 789
 790    fn to_proto(
 791        &self,
 792        debug_client_id: SessionId,
 793        upstream_project_id: u64,
 794    ) -> proto::DapRestartRequest {
 795        let raw_args = serde_json::to_vec(&self.raw).log_err().unwrap_or_default();
 796
 797        proto::DapRestartRequest {
 798            project_id: upstream_project_id,
 799            client_id: debug_client_id.to_proto(),
 800            raw_args,
 801        }
 802    }
 803
 804    fn response_to_proto(
 805        _debug_client_id: SessionId,
 806        _message: Self::Response,
 807    ) -> Self::ProtoResponse {
 808        proto::Ack {}
 809    }
 810
 811    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 812        Ok(())
 813    }
 814}
 815
 816#[derive(Debug, Hash, PartialEq, Eq)]
 817pub struct VariablesCommand {
 818    pub variables_reference: u64,
 819    pub filter: Option<VariablesArgumentsFilter>,
 820    pub start: Option<u64>,
 821    pub count: Option<u64>,
 822    pub format: Option<ValueFormat>,
 823}
 824
 825impl LocalDapCommand for VariablesCommand {
 826    type Response = Vec<Variable>;
 827    type DapRequest = dap::requests::Variables;
 828    const CACHEABLE: bool = true;
 829
 830    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 831        dap::VariablesArguments {
 832            variables_reference: self.variables_reference,
 833            filter: self.filter,
 834            start: self.start,
 835            count: self.count,
 836            format: self.format.clone(),
 837        }
 838    }
 839
 840    fn response_from_dap(
 841        &self,
 842        message: <Self::DapRequest as dap::requests::Request>::Response,
 843    ) -> Result<Self::Response> {
 844        Ok(message.variables)
 845    }
 846}
 847
 848impl DapCommand for VariablesCommand {
 849    type ProtoRequest = proto::VariablesRequest;
 850    type ProtoResponse = proto::DapVariables;
 851
 852    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 853        SessionId::from_proto(request.client_id)
 854    }
 855
 856    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
 857        proto::VariablesRequest {
 858            project_id: upstream_project_id,
 859            client_id: debug_client_id.to_proto(),
 860            variables_reference: self.variables_reference,
 861            filter: None,
 862            start: self.start,
 863            count: self.count,
 864            format: None,
 865        }
 866    }
 867
 868    fn from_proto(request: &Self::ProtoRequest) -> Self {
 869        Self {
 870            variables_reference: request.variables_reference,
 871            filter: None,
 872            start: request.start,
 873            count: request.count,
 874            format: None,
 875        }
 876    }
 877
 878    fn response_to_proto(
 879        debug_client_id: SessionId,
 880        message: Self::Response,
 881    ) -> Self::ProtoResponse {
 882        proto::DapVariables {
 883            client_id: debug_client_id.to_proto(),
 884            variables: message.to_proto(),
 885        }
 886    }
 887
 888    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
 889        Ok(Vec::from_proto(message.variables))
 890    }
 891}
 892
 893#[derive(Debug, Hash, PartialEq, Eq)]
 894pub(crate) struct SetVariableValueCommand {
 895    pub name: String,
 896    pub value: String,
 897    pub variables_reference: u64,
 898}
 899impl LocalDapCommand for SetVariableValueCommand {
 900    type Response = SetVariableResponse;
 901    type DapRequest = dap::requests::SetVariable;
 902    fn is_supported(capabilities: &Capabilities) -> bool {
 903        capabilities.supports_set_variable.unwrap_or_default()
 904    }
 905    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 906        dap::SetVariableArguments {
 907            format: None,
 908            name: self.name.clone(),
 909            value: self.value.clone(),
 910            variables_reference: self.variables_reference,
 911        }
 912    }
 913    fn response_from_dap(
 914        &self,
 915        message: <Self::DapRequest as dap::requests::Request>::Response,
 916    ) -> Result<Self::Response> {
 917        Ok(message)
 918    }
 919}
 920
 921impl DapCommand for SetVariableValueCommand {
 922    type ProtoRequest = proto::DapSetVariableValueRequest;
 923    type ProtoResponse = proto::DapSetVariableValueResponse;
 924
 925    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 926        SessionId::from_proto(request.client_id)
 927    }
 928
 929    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
 930        proto::DapSetVariableValueRequest {
 931            project_id: upstream_project_id,
 932            client_id: debug_client_id.to_proto(),
 933            variables_reference: self.variables_reference,
 934            value: self.value.clone(),
 935            name: self.name.clone(),
 936        }
 937    }
 938
 939    fn from_proto(request: &Self::ProtoRequest) -> Self {
 940        Self {
 941            variables_reference: request.variables_reference,
 942            name: request.name.clone(),
 943            value: request.value.clone(),
 944        }
 945    }
 946
 947    fn response_to_proto(
 948        debug_client_id: SessionId,
 949        message: Self::Response,
 950    ) -> Self::ProtoResponse {
 951        proto::DapSetVariableValueResponse {
 952            client_id: debug_client_id.to_proto(),
 953            value: message.value,
 954            variable_type: message.type_,
 955            named_variables: message.named_variables,
 956            variables_reference: message.variables_reference,
 957            indexed_variables: message.indexed_variables,
 958            memory_reference: message.memory_reference,
 959        }
 960    }
 961
 962    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
 963        Ok(SetVariableResponse {
 964            value: message.value,
 965            type_: message.variable_type,
 966            variables_reference: message.variables_reference,
 967            named_variables: message.named_variables,
 968            indexed_variables: message.indexed_variables,
 969            memory_reference: message.memory_reference,
 970            value_location_reference: None, // TODO
 971        })
 972    }
 973}
 974
 975#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 976pub(crate) struct RestartStackFrameCommand {
 977    pub stack_frame_id: u64,
 978}
 979
 980impl LocalDapCommand for RestartStackFrameCommand {
 981    type Response = <dap::requests::RestartFrame as dap::requests::Request>::Response;
 982    type DapRequest = dap::requests::RestartFrame;
 983
 984    fn is_supported(capabilities: &Capabilities) -> bool {
 985        capabilities.supports_restart_frame.unwrap_or_default()
 986    }
 987
 988    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 989        dap::RestartFrameArguments {
 990            frame_id: self.stack_frame_id,
 991        }
 992    }
 993
 994    fn response_from_dap(
 995        &self,
 996        _message: <Self::DapRequest as dap::requests::Request>::Response,
 997    ) -> Result<Self::Response> {
 998        Ok(())
 999    }
1000}
1001
1002impl DapCommand for RestartStackFrameCommand {
1003    type ProtoRequest = proto::DapRestartStackFrameRequest;
1004    type ProtoResponse = proto::Ack;
1005
1006    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1007        SessionId::from_proto(request.client_id)
1008    }
1009
1010    fn from_proto(request: &Self::ProtoRequest) -> Self {
1011        Self {
1012            stack_frame_id: request.stack_frame_id,
1013        }
1014    }
1015
1016    fn to_proto(
1017        &self,
1018        debug_client_id: SessionId,
1019        upstream_project_id: u64,
1020    ) -> proto::DapRestartStackFrameRequest {
1021        proto::DapRestartStackFrameRequest {
1022            project_id: upstream_project_id,
1023            client_id: debug_client_id.to_proto(),
1024            stack_frame_id: self.stack_frame_id,
1025        }
1026    }
1027
1028    fn response_to_proto(
1029        _debug_client_id: SessionId,
1030        _message: Self::Response,
1031    ) -> Self::ProtoResponse {
1032        proto::Ack {}
1033    }
1034
1035    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
1036        Ok(())
1037    }
1038}
1039
1040#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1041pub(crate) struct ModulesCommand;
1042
1043impl LocalDapCommand for ModulesCommand {
1044    type Response = Vec<dap::Module>;
1045    type DapRequest = dap::requests::Modules;
1046    const CACHEABLE: bool = true;
1047
1048    fn is_supported(capabilities: &Capabilities) -> bool {
1049        capabilities.supports_modules_request.unwrap_or_default()
1050    }
1051
1052    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1053        dap::ModulesArguments {
1054            start_module: None,
1055            module_count: None,
1056        }
1057    }
1058
1059    fn response_from_dap(
1060        &self,
1061        message: <Self::DapRequest as dap::requests::Request>::Response,
1062    ) -> Result<Self::Response> {
1063        Ok(message.modules)
1064    }
1065}
1066
1067impl DapCommand for ModulesCommand {
1068    type ProtoRequest = proto::DapModulesRequest;
1069    type ProtoResponse = proto::DapModulesResponse;
1070
1071    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1072        SessionId::from_proto(request.client_id)
1073    }
1074
1075    fn from_proto(_request: &Self::ProtoRequest) -> Self {
1076        Self {}
1077    }
1078
1079    fn to_proto(
1080        &self,
1081        debug_client_id: SessionId,
1082        upstream_project_id: u64,
1083    ) -> proto::DapModulesRequest {
1084        proto::DapModulesRequest {
1085            project_id: upstream_project_id,
1086            client_id: debug_client_id.to_proto(),
1087        }
1088    }
1089
1090    fn response_to_proto(
1091        debug_client_id: SessionId,
1092        message: Self::Response,
1093    ) -> Self::ProtoResponse {
1094        proto::DapModulesResponse {
1095            modules: message
1096                .into_iter()
1097                .map(|module| module.to_proto())
1098                .collect(),
1099            client_id: debug_client_id.to_proto(),
1100        }
1101    }
1102
1103    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1104        Ok(message
1105            .modules
1106            .into_iter()
1107            .filter_map(|module| dap::Module::from_proto(module).ok())
1108            .collect())
1109    }
1110}
1111
1112#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1113pub(crate) struct LoadedSourcesCommand;
1114
1115impl LocalDapCommand for LoadedSourcesCommand {
1116    type Response = Vec<dap::Source>;
1117    type DapRequest = dap::requests::LoadedSources;
1118    const CACHEABLE: bool = true;
1119
1120    fn is_supported(capabilities: &Capabilities) -> bool {
1121        capabilities
1122            .supports_loaded_sources_request
1123            .unwrap_or_default()
1124    }
1125    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1126        dap::LoadedSourcesArguments {}
1127    }
1128
1129    fn response_from_dap(
1130        &self,
1131        message: <Self::DapRequest as dap::requests::Request>::Response,
1132    ) -> Result<Self::Response> {
1133        Ok(message.sources)
1134    }
1135}
1136
1137impl DapCommand for LoadedSourcesCommand {
1138    type ProtoRequest = proto::DapLoadedSourcesRequest;
1139    type ProtoResponse = proto::DapLoadedSourcesResponse;
1140
1141    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1142        SessionId::from_proto(request.client_id)
1143    }
1144
1145    fn from_proto(_request: &Self::ProtoRequest) -> Self {
1146        Self {}
1147    }
1148
1149    fn to_proto(
1150        &self,
1151        debug_client_id: SessionId,
1152        upstream_project_id: u64,
1153    ) -> proto::DapLoadedSourcesRequest {
1154        proto::DapLoadedSourcesRequest {
1155            project_id: upstream_project_id,
1156            client_id: debug_client_id.to_proto(),
1157        }
1158    }
1159
1160    fn response_to_proto(
1161        debug_client_id: SessionId,
1162        message: Self::Response,
1163    ) -> Self::ProtoResponse {
1164        proto::DapLoadedSourcesResponse {
1165            sources: message
1166                .into_iter()
1167                .map(|source| source.to_proto())
1168                .collect(),
1169            client_id: debug_client_id.to_proto(),
1170        }
1171    }
1172
1173    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1174        Ok(message
1175            .sources
1176            .into_iter()
1177            .map(dap::Source::from_proto)
1178            .collect())
1179    }
1180}
1181
1182#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1183pub(crate) struct StackTraceCommand {
1184    pub thread_id: u64,
1185    pub start_frame: Option<u64>,
1186    pub levels: Option<u64>,
1187}
1188
1189impl LocalDapCommand for StackTraceCommand {
1190    type Response = Vec<dap::StackFrame>;
1191    type DapRequest = dap::requests::StackTrace;
1192    const CACHEABLE: bool = true;
1193
1194    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1195        dap::StackTraceArguments {
1196            thread_id: self.thread_id,
1197            start_frame: self.start_frame,
1198            levels: self.levels,
1199            format: None,
1200        }
1201    }
1202
1203    fn response_from_dap(
1204        &self,
1205        message: <Self::DapRequest as dap::requests::Request>::Response,
1206    ) -> Result<Self::Response> {
1207        Ok(message.stack_frames)
1208    }
1209}
1210
1211impl DapCommand for StackTraceCommand {
1212    type ProtoRequest = proto::DapStackTraceRequest;
1213    type ProtoResponse = proto::DapStackTraceResponse;
1214
1215    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1216        proto::DapStackTraceRequest {
1217            project_id: upstream_project_id,
1218            client_id: debug_client_id.to_proto(),
1219            thread_id: self.thread_id,
1220            start_frame: self.start_frame,
1221            stack_trace_levels: self.levels,
1222        }
1223    }
1224
1225    fn from_proto(request: &Self::ProtoRequest) -> Self {
1226        Self {
1227            thread_id: request.thread_id,
1228            start_frame: request.start_frame,
1229            levels: request.stack_trace_levels,
1230        }
1231    }
1232
1233    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1234        SessionId::from_proto(request.client_id)
1235    }
1236
1237    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1238        Ok(message
1239            .frames
1240            .into_iter()
1241            .map(dap::StackFrame::from_proto)
1242            .collect())
1243    }
1244
1245    fn response_to_proto(
1246        _debug_client_id: SessionId,
1247        message: Self::Response,
1248    ) -> Self::ProtoResponse {
1249        proto::DapStackTraceResponse {
1250            frames: message.to_proto(),
1251        }
1252    }
1253}
1254
1255#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1256pub(crate) struct ScopesCommand {
1257    pub stack_frame_id: u64,
1258}
1259
1260impl LocalDapCommand for ScopesCommand {
1261    type Response = Vec<dap::Scope>;
1262    type DapRequest = dap::requests::Scopes;
1263    const CACHEABLE: bool = true;
1264
1265    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1266        dap::ScopesArguments {
1267            frame_id: self.stack_frame_id,
1268        }
1269    }
1270
1271    fn response_from_dap(
1272        &self,
1273        message: <Self::DapRequest as dap::requests::Request>::Response,
1274    ) -> Result<Self::Response> {
1275        Ok(message.scopes)
1276    }
1277}
1278
1279impl DapCommand for ScopesCommand {
1280    type ProtoRequest = proto::DapScopesRequest;
1281    type ProtoResponse = proto::DapScopesResponse;
1282
1283    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1284        proto::DapScopesRequest {
1285            project_id: upstream_project_id,
1286            client_id: debug_client_id.to_proto(),
1287            stack_frame_id: self.stack_frame_id,
1288        }
1289    }
1290
1291    fn from_proto(request: &Self::ProtoRequest) -> Self {
1292        Self {
1293            stack_frame_id: request.stack_frame_id,
1294        }
1295    }
1296
1297    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1298        SessionId::from_proto(request.client_id)
1299    }
1300
1301    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1302        Ok(Vec::from_proto(message.scopes))
1303    }
1304
1305    fn response_to_proto(
1306        _debug_client_id: SessionId,
1307        message: Self::Response,
1308    ) -> Self::ProtoResponse {
1309        proto::DapScopesResponse {
1310            scopes: message.to_proto(),
1311        }
1312    }
1313}
1314
1315impl LocalDapCommand for super::session::CompletionsQuery {
1316    type Response = dap::CompletionsResponse;
1317    type DapRequest = dap::requests::Completions;
1318    const CACHEABLE: bool = true;
1319
1320    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1321        dap::CompletionsArguments {
1322            text: self.query.clone(),
1323            frame_id: self.frame_id,
1324            column: self.column,
1325            line: None,
1326        }
1327    }
1328
1329    fn response_from_dap(
1330        &self,
1331        message: <Self::DapRequest as dap::requests::Request>::Response,
1332    ) -> Result<Self::Response> {
1333        Ok(message)
1334    }
1335
1336    fn is_supported(capabilities: &Capabilities) -> bool {
1337        capabilities
1338            .supports_completions_request
1339            .unwrap_or_default()
1340    }
1341}
1342
1343impl DapCommand for super::session::CompletionsQuery {
1344    type ProtoRequest = proto::DapCompletionRequest;
1345    type ProtoResponse = proto::DapCompletionResponse;
1346
1347    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1348        proto::DapCompletionRequest {
1349            client_id: debug_client_id.to_proto(),
1350            project_id: upstream_project_id,
1351            frame_id: self.frame_id,
1352            query: self.query.clone(),
1353            column: self.column,
1354            line: self.line,
1355        }
1356    }
1357
1358    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1359        SessionId::from_proto(request.client_id)
1360    }
1361
1362    fn from_proto(request: &Self::ProtoRequest) -> Self {
1363        Self {
1364            query: request.query.clone(),
1365            frame_id: request.frame_id,
1366            column: request.column,
1367            line: request.line,
1368        }
1369    }
1370
1371    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1372        Ok(dap::CompletionsResponse {
1373            targets: Vec::from_proto(message.completions),
1374        })
1375    }
1376
1377    fn response_to_proto(
1378        _debug_client_id: SessionId,
1379        message: Self::Response,
1380    ) -> Self::ProtoResponse {
1381        proto::DapCompletionResponse {
1382            client_id: _debug_client_id.to_proto(),
1383            completions: message.targets.to_proto(),
1384        }
1385    }
1386}
1387
1388#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1389pub(crate) struct EvaluateCommand {
1390    pub expression: String,
1391    pub frame_id: Option<u64>,
1392    pub context: Option<dap::EvaluateArgumentsContext>,
1393    pub source: Option<dap::Source>,
1394}
1395
1396impl LocalDapCommand for EvaluateCommand {
1397    type Response = dap::EvaluateResponse;
1398    type DapRequest = dap::requests::Evaluate;
1399    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1400        dap::EvaluateArguments {
1401            expression: self.expression.clone(),
1402            frame_id: self.frame_id,
1403            context: self.context.clone(),
1404            source: self.source.clone(),
1405            line: None,
1406            column: None,
1407            format: None,
1408        }
1409    }
1410
1411    fn response_from_dap(
1412        &self,
1413        message: <Self::DapRequest as dap::requests::Request>::Response,
1414    ) -> Result<Self::Response> {
1415        Ok(message)
1416    }
1417}
1418impl DapCommand for EvaluateCommand {
1419    type ProtoRequest = proto::DapEvaluateRequest;
1420    type ProtoResponse = proto::DapEvaluateResponse;
1421
1422    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1423        proto::DapEvaluateRequest {
1424            client_id: debug_client_id.to_proto(),
1425            project_id: upstream_project_id,
1426            expression: self.expression.clone(),
1427            frame_id: self.frame_id,
1428            context: self
1429                .context
1430                .clone()
1431                .map(|context| context.to_proto().into()),
1432        }
1433    }
1434
1435    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1436        SessionId::from_proto(request.client_id)
1437    }
1438
1439    fn from_proto(request: &Self::ProtoRequest) -> Self {
1440        Self {
1441            expression: request.expression.clone(),
1442            frame_id: request.frame_id,
1443            context: Some(dap::EvaluateArgumentsContext::from_proto(request.context())),
1444            source: None,
1445        }
1446    }
1447
1448    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1449        Ok(dap::EvaluateResponse {
1450            result: message.result.clone(),
1451            type_: message.evaluate_type.clone(),
1452            presentation_hint: None,
1453            variables_reference: message.variable_reference,
1454            named_variables: message.named_variables,
1455            indexed_variables: message.indexed_variables,
1456            memory_reference: message.memory_reference.clone(),
1457            value_location_reference: None, //TODO
1458        })
1459    }
1460
1461    fn response_to_proto(
1462        _debug_client_id: SessionId,
1463        message: Self::Response,
1464    ) -> Self::ProtoResponse {
1465        proto::DapEvaluateResponse {
1466            result: message.result,
1467            evaluate_type: message.type_,
1468            variable_reference: message.variables_reference,
1469            named_variables: message.named_variables,
1470            indexed_variables: message.indexed_variables,
1471            memory_reference: message.memory_reference,
1472        }
1473    }
1474}
1475
1476#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1477pub(crate) struct ThreadsCommand;
1478
1479impl LocalDapCommand for ThreadsCommand {
1480    type Response = Vec<dap::Thread>;
1481    type DapRequest = dap::requests::Threads;
1482    const CACHEABLE: bool = true;
1483
1484    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1485        dap::ThreadsArgument {}
1486    }
1487
1488    fn response_from_dap(
1489        &self,
1490        message: <Self::DapRequest as dap::requests::Request>::Response,
1491    ) -> Result<Self::Response> {
1492        Ok(message.threads)
1493    }
1494}
1495
1496impl DapCommand for ThreadsCommand {
1497    type ProtoRequest = proto::DapThreadsRequest;
1498    type ProtoResponse = proto::DapThreadsResponse;
1499
1500    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1501        proto::DapThreadsRequest {
1502            project_id: upstream_project_id,
1503            client_id: debug_client_id.to_proto(),
1504        }
1505    }
1506
1507    fn from_proto(_request: &Self::ProtoRequest) -> Self {
1508        Self {}
1509    }
1510
1511    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1512        SessionId::from_proto(request.client_id)
1513    }
1514
1515    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1516        Ok(Vec::from_proto(message.threads))
1517    }
1518
1519    fn response_to_proto(
1520        _debug_client_id: SessionId,
1521        message: Self::Response,
1522    ) -> Self::ProtoResponse {
1523        proto::DapThreadsResponse {
1524            threads: message.to_proto(),
1525        }
1526    }
1527}
1528
1529#[derive(Clone, Debug, Hash, PartialEq)]
1530pub(super) struct Initialize {
1531    pub(super) adapter_id: String,
1532}
1533
1534fn dap_client_capabilities(adapter_id: String) -> InitializeRequestArguments {
1535    InitializeRequestArguments {
1536        client_id: Some("zed".to_owned()),
1537        client_name: Some("Zed".to_owned()),
1538        adapter_id,
1539        locale: Some("en-US".to_owned()),
1540        path_format: Some(InitializeRequestArgumentsPathFormat::Path),
1541        supports_variable_type: Some(true),
1542        supports_variable_paging: Some(false),
1543        supports_run_in_terminal_request: Some(true),
1544        supports_memory_references: Some(true),
1545        supports_progress_reporting: Some(false),
1546        supports_invalidated_event: Some(false),
1547        lines_start_at1: Some(true),
1548        columns_start_at1: Some(true),
1549        supports_memory_event: Some(false),
1550        supports_args_can_be_interpreted_by_shell: Some(false),
1551        supports_start_debugging_request: Some(true),
1552        supports_ansistyling: Some(true),
1553    }
1554}
1555
1556impl LocalDapCommand for Initialize {
1557    type Response = Capabilities;
1558    type DapRequest = dap::requests::Initialize;
1559
1560    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1561        dap_client_capabilities(self.adapter_id.clone())
1562    }
1563
1564    fn response_from_dap(
1565        &self,
1566        message: <Self::DapRequest as dap::requests::Request>::Response,
1567    ) -> Result<Self::Response> {
1568        Ok(message)
1569    }
1570}
1571
1572#[derive(Clone, Debug, Hash, PartialEq)]
1573pub(super) struct ConfigurationDone {}
1574
1575impl LocalDapCommand for ConfigurationDone {
1576    type Response = ();
1577    type DapRequest = dap::requests::ConfigurationDone;
1578
1579    fn is_supported(capabilities: &Capabilities) -> bool {
1580        capabilities
1581            .supports_configuration_done_request
1582            .unwrap_or_default()
1583    }
1584
1585    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1586        dap::ConfigurationDoneArguments {}
1587    }
1588
1589    fn response_from_dap(
1590        &self,
1591        message: <Self::DapRequest as dap::requests::Request>::Response,
1592    ) -> Result<Self::Response> {
1593        Ok(message)
1594    }
1595}
1596
1597#[derive(Clone, Debug, Hash, PartialEq)]
1598pub(super) struct Launch {
1599    pub(super) raw: Value,
1600}
1601
1602impl LocalDapCommand for Launch {
1603    type Response = ();
1604    type DapRequest = dap::requests::Launch;
1605
1606    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1607        dap::LaunchRequestArguments {
1608            raw: self.raw.clone(),
1609        }
1610    }
1611
1612    fn response_from_dap(
1613        &self,
1614        message: <Self::DapRequest as dap::requests::Request>::Response,
1615    ) -> Result<Self::Response> {
1616        Ok(message)
1617    }
1618}
1619
1620#[derive(Clone, Debug, Hash, PartialEq)]
1621pub(super) struct Attach {
1622    pub(super) raw: Value,
1623}
1624
1625impl LocalDapCommand for Attach {
1626    type Response = ();
1627    type DapRequest = dap::requests::Attach;
1628
1629    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1630        dap::AttachRequestArguments {
1631            raw: self.raw.clone(),
1632        }
1633    }
1634
1635    fn response_from_dap(
1636        &self,
1637        message: <Self::DapRequest as dap::requests::Request>::Response,
1638    ) -> Result<Self::Response> {
1639        Ok(message)
1640    }
1641}
1642
1643#[derive(Clone, Debug, Hash, PartialEq)]
1644pub(super) struct SetBreakpoints {
1645    pub(super) source: dap::Source,
1646    pub(super) breakpoints: Vec<SourceBreakpoint>,
1647    pub(super) source_modified: Option<bool>,
1648}
1649
1650impl LocalDapCommand for SetBreakpoints {
1651    type Response = Vec<dap::Breakpoint>;
1652    type DapRequest = dap::requests::SetBreakpoints;
1653
1654    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1655        dap::SetBreakpointsArguments {
1656            lines: None,
1657            source_modified: self.source_modified,
1658            source: self.source.clone(),
1659            breakpoints: Some(self.breakpoints.clone()),
1660        }
1661    }
1662
1663    fn response_from_dap(
1664        &self,
1665        message: <Self::DapRequest as dap::requests::Request>::Response,
1666    ) -> Result<Self::Response> {
1667        Ok(message.breakpoints)
1668    }
1669}
1670#[derive(Clone, Debug, Hash, PartialEq)]
1671pub(super) enum SetExceptionBreakpoints {
1672    Plain {
1673        filters: Vec<String>,
1674    },
1675    WithOptions {
1676        filters: Vec<ExceptionFilterOptions>,
1677    },
1678}
1679
1680impl LocalDapCommand for SetExceptionBreakpoints {
1681    type Response = Vec<dap::Breakpoint>;
1682    type DapRequest = dap::requests::SetExceptionBreakpoints;
1683
1684    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1685        match self {
1686            SetExceptionBreakpoints::Plain { filters } => dap::SetExceptionBreakpointsArguments {
1687                filters: filters.clone(),
1688                exception_options: None,
1689                filter_options: None,
1690            },
1691            SetExceptionBreakpoints::WithOptions { filters } => {
1692                dap::SetExceptionBreakpointsArguments {
1693                    filters: vec![],
1694                    filter_options: Some(filters.clone()),
1695                    exception_options: None,
1696                }
1697            }
1698        }
1699    }
1700
1701    fn response_from_dap(
1702        &self,
1703        message: <Self::DapRequest as dap::requests::Request>::Response,
1704    ) -> Result<Self::Response> {
1705        Ok(message.breakpoints.unwrap_or_default())
1706    }
1707}
1708
1709#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1710pub(super) struct LocationsCommand {
1711    pub(super) reference: u64,
1712}
1713
1714impl LocalDapCommand for LocationsCommand {
1715    type Response = dap::LocationsResponse;
1716    type DapRequest = dap::requests::Locations;
1717    const CACHEABLE: bool = true;
1718
1719    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1720        dap::LocationsArguments {
1721            location_reference: self.reference,
1722        }
1723    }
1724
1725    fn response_from_dap(
1726        &self,
1727        message: <Self::DapRequest as dap::requests::Request>::Response,
1728    ) -> Result<Self::Response> {
1729        Ok(message)
1730    }
1731}
1732
1733impl DapCommand for LocationsCommand {
1734    type ProtoRequest = proto::DapLocationsRequest;
1735    type ProtoResponse = proto::DapLocationsResponse;
1736
1737    fn client_id_from_proto(message: &Self::ProtoRequest) -> SessionId {
1738        SessionId::from_proto(message.session_id)
1739    }
1740
1741    fn from_proto(message: &Self::ProtoRequest) -> Self {
1742        Self {
1743            reference: message.location_reference,
1744        }
1745    }
1746
1747    fn to_proto(&self, session_id: SessionId, project_id: u64) -> Self::ProtoRequest {
1748        proto::DapLocationsRequest {
1749            project_id,
1750            session_id: session_id.to_proto(),
1751            location_reference: self.reference,
1752        }
1753    }
1754
1755    fn response_to_proto(_: SessionId, response: Self::Response) -> Self::ProtoResponse {
1756        proto::DapLocationsResponse {
1757            source: Some(response.source.to_proto()),
1758            line: response.line,
1759            column: response.column,
1760            end_line: response.end_line,
1761            end_column: response.end_column,
1762        }
1763    }
1764
1765    fn response_from_proto(&self, response: Self::ProtoResponse) -> Result<Self::Response> {
1766        Ok(dap::LocationsResponse {
1767            source: response
1768                .source
1769                .map(<dap::Source as ProtoConversion>::from_proto)
1770                .context("Missing `source` field in Locations proto")?,
1771            line: response.line,
1772            column: response.column,
1773            end_line: response.end_line,
1774            end_column: response.end_column,
1775        })
1776    }
1777}
1778
1779#[derive(Debug, Hash, PartialEq, Eq)]
1780pub(crate) struct ReadMemory {
1781    pub(crate) memory_reference: String,
1782    pub(crate) offset: Option<u64>,
1783    pub(crate) count: u64,
1784}
1785
1786#[derive(Clone, Debug, PartialEq)]
1787pub(crate) struct ReadMemoryResponse {
1788    pub(super) address: Arc<str>,
1789    pub(super) unreadable_bytes: Option<u64>,
1790    pub(super) content: Arc<[u8]>,
1791}
1792
1793impl LocalDapCommand for ReadMemory {
1794    type Response = ReadMemoryResponse;
1795    type DapRequest = dap::requests::ReadMemory;
1796    const CACHEABLE: bool = true;
1797
1798    fn is_supported(capabilities: &Capabilities) -> bool {
1799        capabilities
1800            .supports_read_memory_request
1801            .unwrap_or_default()
1802    }
1803    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1804        dap::ReadMemoryArguments {
1805            memory_reference: self.memory_reference.clone(),
1806            offset: self.offset,
1807            count: self.count,
1808        }
1809    }
1810
1811    fn response_from_dap(
1812        &self,
1813        message: <Self::DapRequest as dap::requests::Request>::Response,
1814    ) -> Result<Self::Response> {
1815        let data = if let Some(data) = message.data {
1816            base64::engine::general_purpose::STANDARD
1817                .decode(data)
1818                .log_err()
1819                .context("parsing base64 data from DAP's ReadMemory response")?
1820        } else {
1821            vec![]
1822        };
1823
1824        Ok(ReadMemoryResponse {
1825            address: message.address.into(),
1826            content: data.into(),
1827            unreadable_bytes: message.unreadable_bytes,
1828        })
1829    }
1830}
1831
1832impl LocalDapCommand for dap::DataBreakpointInfoArguments {
1833    type Response = dap::DataBreakpointInfoResponse;
1834    type DapRequest = dap::requests::DataBreakpointInfo;
1835    const CACHEABLE: bool = true;
1836    fn is_supported(capabilities: &Capabilities) -> bool {
1837        capabilities.supports_data_breakpoints.unwrap_or_default()
1838    }
1839    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1840        self.clone()
1841    }
1842
1843    fn response_from_dap(
1844        &self,
1845        message: <Self::DapRequest as dap::requests::Request>::Response,
1846    ) -> Result<Self::Response> {
1847        Ok(message)
1848    }
1849}
1850
1851impl LocalDapCommand for dap::WriteMemoryArguments {
1852    type Response = dap::WriteMemoryResponse;
1853    type DapRequest = dap::requests::WriteMemory;
1854    fn is_supported(capabilities: &Capabilities) -> bool {
1855        capabilities
1856            .supports_write_memory_request
1857            .unwrap_or_default()
1858    }
1859    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1860        self.clone()
1861    }
1862
1863    fn response_from_dap(
1864        &self,
1865        message: <Self::DapRequest as dap::requests::Request>::Response,
1866    ) -> Result<Self::Response> {
1867        Ok(message)
1868    }
1869}