debugger/common/
config.rs1use serde::Deserialize;
4use std::collections::HashMap;
5use std::path::PathBuf;
6
7use super::paths::config_path;
8use super::Result;
9
10#[derive(Debug, Deserialize, Default)]
12pub struct Config {
13 #[serde(default)]
15 pub adapters: HashMap<String, AdapterConfig>,
16
17 #[serde(default)]
19 pub defaults: Defaults,
20
21 #[serde(default)]
23 pub timeouts: Timeouts,
24
25 #[serde(default)]
27 pub daemon: DaemonConfig,
28
29 #[serde(default)]
31 pub output: OutputConfig,
32}
33
34#[derive(Debug, Deserialize, Clone, Default, PartialEq)]
36#[serde(rename_all = "lowercase")]
37pub enum TransportMode {
38 #[default]
40 Stdio,
41 Tcp,
43}
44
45#[derive(Debug, Deserialize, Clone, Default, PartialEq)]
47pub enum TcpSpawnStyle {
48 #[default]
50 #[serde(rename = "tcp-listen")]
51 TcpListen,
52 #[serde(rename = "tcp-port-arg")]
54 TcpPortArg,
55}
56
57#[derive(Debug, Deserialize, Clone)]
59pub struct AdapterConfig {
60 pub path: PathBuf,
62
63 #[serde(default)]
65 pub args: Vec<String>,
66
67 #[serde(default)]
69 pub transport: TransportMode,
70
71 #[serde(default)]
73 pub spawn_style: TcpSpawnStyle,
74}
75
76#[derive(Debug, Deserialize)]
78pub struct Defaults {
79 #[serde(default = "default_adapter")]
81 pub adapter: String,
82}
83
84impl Default for Defaults {
85 fn default() -> Self {
86 Self {
87 adapter: default_adapter(),
88 }
89 }
90}
91
92fn default_adapter() -> String {
93 "lldb-dap".to_string()
94}
95
96#[derive(Debug, Deserialize)]
98pub struct Timeouts {
99 #[serde(default = "default_dap_initialize")]
101 pub dap_initialize_secs: u64,
102
103 #[serde(default = "default_dap_request")]
105 pub dap_request_secs: u64,
106
107 #[serde(default = "default_await")]
109 pub await_default_secs: u64,
110}
111
112impl Default for Timeouts {
113 fn default() -> Self {
114 Self {
115 dap_initialize_secs: default_dap_initialize(),
116 dap_request_secs: default_dap_request(),
117 await_default_secs: default_await(),
118 }
119 }
120}
121
122fn default_dap_initialize() -> u64 {
123 10
124}
125fn default_dap_request() -> u64 {
126 30
127}
128fn default_await() -> u64 {
129 300
130}
131
132#[derive(Debug, Deserialize)]
134pub struct DaemonConfig {
135 #[serde(default = "default_idle_timeout")]
137 pub idle_timeout_minutes: u64,
138}
139
140impl Default for DaemonConfig {
141 fn default() -> Self {
142 Self {
143 idle_timeout_minutes: default_idle_timeout(),
144 }
145 }
146}
147
148fn default_idle_timeout() -> u64 {
149 30
150}
151
152#[derive(Debug, Deserialize)]
154pub struct OutputConfig {
155 #[serde(default = "default_max_events")]
157 pub max_events: usize,
158
159 #[serde(default = "default_max_bytes")]
161 pub max_bytes_mb: usize,
162}
163
164impl Default for OutputConfig {
165 fn default() -> Self {
166 Self {
167 max_events: default_max_events(),
168 max_bytes_mb: default_max_bytes(),
169 }
170 }
171}
172
173fn default_max_events() -> usize {
174 10_000
175}
176fn default_max_bytes() -> usize {
177 10
178}
179
180impl Config {
181 pub fn load() -> Result<Self> {
185 if let Some(path) = config_path() {
186 if path.exists() {
187 let content = std::fs::read_to_string(&path).map_err(|e| {
188 super::Error::FileRead {
189 path: path.display().to_string(),
190 error: e.to_string(),
191 }
192 })?;
193 return toml::from_str(&content)
194 .map_err(|e| super::Error::ConfigParse(e.to_string()));
195 }
196 }
197 Ok(Self::default())
198 }
199
200 pub fn get_adapter(&self, name: &str) -> Option<AdapterConfig> {
204 if let Some(config) = self.adapters.get(name) {
206 return Some(config.clone());
207 }
208
209 which::which(name).ok().map(|path| AdapterConfig {
211 path,
212 args: Vec::new(),
213 transport: TransportMode::default(),
214 spawn_style: TcpSpawnStyle::default(),
215 })
216 }
217}