2024-04-13 02:17:34 +00:00
|
|
|
use std::{collections::HashMap, fs, net::SocketAddr, path::Path};
|
|
|
|
|
|
|
|
use once_cell::sync::Lazy;
|
|
|
|
use serde::Deserialize;
|
2024-04-16 00:19:09 +00:00
|
|
|
use tracing::info;
|
2024-04-13 02:17:34 +00:00
|
|
|
|
|
|
|
use crate::engines::Engine;
|
|
|
|
|
2024-04-16 02:49:40 +00:00
|
|
|
#[derive(Deserialize, Debug)]
|
2024-04-13 02:17:34 +00:00
|
|
|
pub struct Config {
|
|
|
|
pub bind: SocketAddr,
|
2024-04-16 02:49:40 +00:00
|
|
|
#[serde(default)]
|
|
|
|
pub engine_list_separator: Option<bool>,
|
2024-04-17 06:35:24 +00:00
|
|
|
#[serde(default)]
|
|
|
|
pub version_info: Option<bool>,
|
2024-04-13 02:17:34 +00:00
|
|
|
pub engines: EnginesConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Config {
|
|
|
|
pub fn read_or_create() -> eyre::Result<Self> {
|
|
|
|
let default_config_str = include_str!("../default-config.toml");
|
2024-04-15 04:35:23 +00:00
|
|
|
let mut config: Config = toml::from_str(default_config_str)?;
|
2024-04-13 02:17:34 +00:00
|
|
|
|
2024-04-17 06:35:24 +00:00
|
|
|
let config_path = std::env::args().nth(1).unwrap_or("config.toml".into());
|
|
|
|
let config_path = Path::new(&config_path);
|
2024-04-13 02:17:34 +00:00
|
|
|
if config_path.exists() {
|
2024-04-15 04:35:23 +00:00
|
|
|
let given_config = toml::from_str::<Config>(&fs::read_to_string(config_path)?)?;
|
|
|
|
config.update(given_config);
|
|
|
|
Ok(config)
|
2024-04-13 02:17:34 +00:00
|
|
|
} else {
|
2024-04-16 00:19:09 +00:00
|
|
|
info!("No config found, creating one at {config_path:?}");
|
2024-04-13 02:17:34 +00:00
|
|
|
fs::write(config_path, default_config_str)?;
|
2024-04-15 04:35:23 +00:00
|
|
|
Ok(config)
|
2024-04-13 02:17:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the current config with the given config. This is used to make it so
|
|
|
|
// the default-config.toml is always used as a fallback if the user decides to
|
|
|
|
// use the default for something.
|
2024-04-16 07:04:44 +00:00
|
|
|
pub fn update(&mut self, new: Config) {
|
|
|
|
self.bind = new.bind;
|
|
|
|
self.engine_list_separator = new.engine_list_separator.or(self.engine_list_separator);
|
2024-04-16 02:49:40 +00:00
|
|
|
assert_ne!(self.engine_list_separator, None);
|
2024-04-17 06:35:24 +00:00
|
|
|
self.version_info = new.version_info.or(self.version_info);
|
|
|
|
assert_ne!(self.version_info, None);
|
2024-04-16 07:04:44 +00:00
|
|
|
for (key, new) in new.engines.map {
|
2024-04-13 02:17:34 +00:00
|
|
|
if let Some(existing) = self.engines.map.get_mut(&key) {
|
2024-04-16 07:04:44 +00:00
|
|
|
existing.update(new);
|
2024-04-13 02:17:34 +00:00
|
|
|
} else {
|
2024-04-16 07:04:44 +00:00
|
|
|
self.engines.map.insert(key, new);
|
2024-04-13 02:17:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-16 02:49:40 +00:00
|
|
|
#[derive(Deserialize, Debug)]
|
2024-04-13 02:17:34 +00:00
|
|
|
pub struct EnginesConfig {
|
|
|
|
#[serde(flatten)]
|
|
|
|
pub map: HashMap<Engine, DefaultableEngineConfig>,
|
|
|
|
}
|
|
|
|
|
|
|
|
static DEFAULT_ENABLED_FULL_ENGINE_CONFIG: Lazy<FullEngineConfig> =
|
|
|
|
Lazy::new(FullEngineConfig::default);
|
|
|
|
static DEFAULT_DISABLED_FULL_ENGINE_CONFIG: Lazy<FullEngineConfig> =
|
|
|
|
Lazy::new(|| FullEngineConfig {
|
|
|
|
enabled: false,
|
|
|
|
..Default::default()
|
|
|
|
});
|
|
|
|
|
|
|
|
impl EnginesConfig {
|
|
|
|
pub fn get(&self, engine: Engine) -> &FullEngineConfig {
|
|
|
|
match self.map.get(&engine) {
|
|
|
|
Some(engine_config) => match engine_config {
|
|
|
|
DefaultableEngineConfig::Boolean(enabled) => {
|
|
|
|
if *enabled {
|
|
|
|
&DEFAULT_ENABLED_FULL_ENGINE_CONFIG
|
|
|
|
} else {
|
|
|
|
&DEFAULT_DISABLED_FULL_ENGINE_CONFIG
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DefaultableEngineConfig::Full(full) => full,
|
|
|
|
},
|
|
|
|
None => &DEFAULT_ENABLED_FULL_ENGINE_CONFIG,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-16 02:49:40 +00:00
|
|
|
#[derive(Deserialize, Clone, Debug)]
|
2024-04-13 02:17:34 +00:00
|
|
|
#[serde(untagged)]
|
|
|
|
pub enum DefaultableEngineConfig {
|
|
|
|
Boolean(bool),
|
|
|
|
Full(FullEngineConfig),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DefaultableEngineConfig {
|
2024-04-16 07:04:44 +00:00
|
|
|
pub fn update(&mut self, new: Self) {
|
|
|
|
let mut self_full = FullEngineConfig::from(self.clone());
|
|
|
|
let other_full = FullEngineConfig::from(new);
|
|
|
|
self_full.update(other_full);
|
|
|
|
*self = DefaultableEngineConfig::Full(self_full);
|
2024-04-13 02:17:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for DefaultableEngineConfig {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Boolean(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-16 02:49:40 +00:00
|
|
|
#[derive(Deserialize, Clone, Debug)]
|
2024-04-13 02:17:34 +00:00
|
|
|
pub struct FullEngineConfig {
|
|
|
|
#[serde(default = "default_true")]
|
|
|
|
pub enabled: bool,
|
|
|
|
|
|
|
|
/// The priority of this engine relative to the other engines. The default
|
|
|
|
/// is 1, and a value of 0 is treated as the default.
|
|
|
|
#[serde(default)]
|
|
|
|
pub weight: f64,
|
|
|
|
/// Per-engine configs. These are parsed at request time.
|
|
|
|
#[serde(flatten)]
|
|
|
|
#[serde(default)]
|
|
|
|
pub extra: toml::Table,
|
|
|
|
}
|
|
|
|
|
|
|
|
// serde expects a function as the default, this just exists so "enabled" is
|
|
|
|
// always true by default
|
|
|
|
fn default_true() -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<DefaultableEngineConfig> for FullEngineConfig {
|
|
|
|
fn from(config: DefaultableEngineConfig) -> Self {
|
|
|
|
match config {
|
|
|
|
DefaultableEngineConfig::Boolean(enabled) => Self {
|
|
|
|
enabled,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
DefaultableEngineConfig::Full(full) => full,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for FullEngineConfig {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
enabled: true,
|
|
|
|
weight: 1.0,
|
|
|
|
extra: Default::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FullEngineConfig {
|
2024-04-16 07:04:44 +00:00
|
|
|
pub fn update(&mut self, new: Self) {
|
|
|
|
self.enabled = new.enabled;
|
|
|
|
if new.weight != 0. {
|
|
|
|
self.weight = new.weight;
|
2024-04-13 02:17:34 +00:00
|
|
|
}
|
2024-04-16 07:04:44 +00:00
|
|
|
self.extra = new.extra;
|
2024-04-13 02:17:34 +00:00
|
|
|
}
|
|
|
|
}
|