use serde::Deserialize;
use std::collections::HashMap;
use std::path::PathBuf;
use super::paths::config_path;
use super::Result;
#[derive(Debug, Deserialize, Default)]
pub struct Config {
#[serde(default)]
pub adapters: HashMap<String, AdapterConfig>,
#[serde(default)]
pub defaults: Defaults,
#[serde(default)]
pub timeouts: Timeouts,
#[serde(default)]
pub daemon: DaemonConfig,
#[serde(default)]
pub output: OutputConfig,
}
#[derive(Debug, Deserialize, Clone, Default, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum TransportMode {
#[default]
Stdio,
Tcp,
}
#[derive(Debug, Deserialize, Clone, Default, PartialEq)]
pub enum TcpSpawnStyle {
#[default]
#[serde(rename = "tcp-listen")]
TcpListen,
#[serde(rename = "tcp-port-arg")]
TcpPortArg,
}
#[derive(Debug, Deserialize, Clone)]
pub struct AdapterConfig {
pub path: PathBuf,
#[serde(default)]
pub args: Vec<String>,
#[serde(default)]
pub transport: TransportMode,
#[serde(default)]
pub spawn_style: TcpSpawnStyle,
}
#[derive(Debug, Deserialize)]
pub struct Defaults {
#[serde(default = "default_adapter")]
pub adapter: String,
}
impl Default for Defaults {
fn default() -> Self {
Self {
adapter: default_adapter(),
}
}
}
fn default_adapter() -> String {
"lldb-dap".to_string()
}
#[derive(Debug, Deserialize)]
pub struct Timeouts {
#[serde(default = "default_dap_initialize")]
pub dap_initialize_secs: u64,
#[serde(default = "default_dap_request")]
pub dap_request_secs: u64,
#[serde(default = "default_await")]
pub await_default_secs: u64,
}
impl Default for Timeouts {
fn default() -> Self {
Self {
dap_initialize_secs: default_dap_initialize(),
dap_request_secs: default_dap_request(),
await_default_secs: default_await(),
}
}
}
fn default_dap_initialize() -> u64 {
10
}
fn default_dap_request() -> u64 {
30
}
fn default_await() -> u64 {
300
}
#[derive(Debug, Deserialize)]
pub struct DaemonConfig {
#[serde(default = "default_idle_timeout")]
pub idle_timeout_minutes: u64,
}
impl Default for DaemonConfig {
fn default() -> Self {
Self {
idle_timeout_minutes: default_idle_timeout(),
}
}
}
fn default_idle_timeout() -> u64 {
30
}
#[derive(Debug, Deserialize)]
pub struct OutputConfig {
#[serde(default = "default_max_events")]
pub max_events: usize,
#[serde(default = "default_max_bytes")]
pub max_bytes_mb: usize,
}
impl Default for OutputConfig {
fn default() -> Self {
Self {
max_events: default_max_events(),
max_bytes_mb: default_max_bytes(),
}
}
}
fn default_max_events() -> usize {
10_000
}
fn default_max_bytes() -> usize {
10
}
impl Config {
pub fn load() -> Result<Self> {
if let Some(path) = config_path() {
if path.exists() {
let content = std::fs::read_to_string(&path).map_err(|e| {
super::Error::FileRead {
path: path.display().to_string(),
error: e.to_string(),
}
})?;
return toml::from_str(&content)
.map_err(|e| super::Error::ConfigParse(e.to_string()));
}
}
Ok(Self::default())
}
pub fn get_adapter(&self, name: &str) -> Option<AdapterConfig> {
if let Some(config) = self.adapters.get(name) {
return Some(config.clone());
}
which::which(name).ok().map(|path| AdapterConfig {
path,
args: Vec::new(),
transport: TransportMode::default(),
spawn_style: TcpSpawnStyle::default(),
})
}
}