use serde::{Deserialize, Serialize};
use crate::config::{Config, MergeError, ValidationError};
#[cfg(feature = "edit")]
use crate::edit::ConfigEditError;
pub fn default_max_concurrent_solves() -> usize {
std::thread::available_parallelism().map_or(1, std::num::NonZero::get)
}
pub fn default_max_concurrent_downloads() -> usize {
50
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub struct ConcurrencyConfig {
#[serde(default = "default_max_concurrent_solves")]
pub solves: usize,
#[serde(default = "default_max_concurrent_downloads")]
pub downloads: usize,
}
impl Default for ConcurrencyConfig {
fn default() -> Self {
Self {
solves: default_max_concurrent_solves(),
downloads: default_max_concurrent_downloads(),
}
}
}
impl ConcurrencyConfig {
pub fn is_default(&self) -> bool {
ConcurrencyConfig::default() == *self
}
}
impl Config for ConcurrencyConfig {
fn get_extension_name(&self) -> String {
"concurrency".to_string()
}
fn merge_config(self, other: &Self) -> Result<Self, MergeError> {
Ok(Self {
solves: if other.solves == ConcurrencyConfig::default().solves {
self.solves
} else {
other.solves
},
downloads: if other.downloads == ConcurrencyConfig::default().downloads {
self.downloads
} else {
other.downloads
},
})
}
fn validate(&self) -> Result<(), ValidationError> {
if self.solves == 0 {
return Err(ValidationError::InvalidValue(
"solves".to_string(),
"The number of concurrent solves must be greater than 0".to_string(),
));
}
if self.downloads == 0 {
return Err(ValidationError::InvalidValue(
"downloads".to_string(),
"The number of concurrent downloads must be greater than 0".to_string(),
));
}
Ok(())
}
fn keys(&self) -> Vec<String> {
vec!["solves".to_string(), "downloads".to_string()]
}
#[cfg(feature = "edit")]
fn set(
&mut self,
key: &str,
value: Option<String>,
) -> Result<(), crate::config::ConfigEditError> {
let subkey = key.strip_prefix("concurrency.").unwrap();
match subkey {
"solves" => {
let value = value.ok_or_else(|| ConfigEditError::MissingValue {
key: key.to_string(),
})?;
self.solves = value
.parse()
.map_err(|e| ConfigEditError::NumberParseError {
key: key.to_string(),
source: e,
})?;
}
"downloads" => {
let value = value.ok_or_else(|| ConfigEditError::MissingValue {
key: key.to_string(),
})?;
self.downloads = value
.parse()
.map_err(|e| ConfigEditError::NumberParseError {
key: key.to_string(),
source: e,
})?;
}
_ => {
return Err(ConfigEditError::UnknownKeyInner {
key: key.to_string(),
})
}
}
Ok(())
}
}