metasearch/src/config.rs

170 lines
4.9 KiB
Rust
Raw Normal View History

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;
#[derive(Deserialize, Debug)]
2024-04-13 02:17:34 +00:00
pub struct Config {
pub bind: SocketAddr,
2024-04-28 01:41:56 +00:00
#[serde(default)]
2024-04-18 04:41:26 +00:00
pub ui: UiConfig,
2024-04-28 01:41:56 +00:00
#[serde(default)]
2024-04-18 04:41:26 +00:00
pub engines: EnginesConfig,
}
2024-04-28 01:41:56 +00:00
#[derive(Deserialize, Debug, Default)]
2024-04-18 04:41:26 +00:00
pub struct UiConfig {
#[serde(default)]
2024-04-18 04:41:26 +00:00
pub show_engine_list_separator: Option<bool>,
tweaks i am going insane 🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈🐈
2024-04-17 06:35:24 +00:00
#[serde(default)]
2024-04-18 04:41:26 +00:00
pub show_version_info: Option<bool>,
}
2024-04-28 01:41:56 +00:00
#[derive(Deserialize, Debug, Default)]
2024-04-18 04:41:26 +00:00
pub struct EnginesConfig {
#[serde(flatten)]
pub map: HashMap<Engine, DefaultableEngineConfig>,
2024-04-13 02:17:34 +00:00
}
impl Config {
2024-04-18 04:41:26 +00:00
pub fn read_or_create(config_path: &Path) -> eyre::Result<Self> {
let base_config_str = include_str!("../config-base.toml");
let mut config: Config = toml::from_str(base_config_str)?;
2024-04-13 02:17:34 +00:00
2024-04-18 04:41:26 +00:00
if !config_path.exists() {
2024-04-16 00:19:09 +00:00
info!("No config found, creating one at {config_path:?}");
2024-04-18 04:41:26 +00:00
let default_config_str = include_str!("../config-default.toml");
2024-04-13 02:17:34 +00:00
fs::write(config_path, default_config_str)?;
}
2024-04-18 04:41:26 +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
}
// Update the current config with the given config. This is used to make it so
2024-04-18 04:41:26 +00:00
// the config-base.toml is always used as a fallback if the user decides to
2024-04-13 02:17:34 +00:00
// use the default for something.
pub fn update(&mut self, new: Config) {
self.bind = new.bind;
2024-04-18 04:41:26 +00:00
self.ui.show_engine_list_separator = new
.ui
.show_engine_list_separator
.or(self.ui.show_engine_list_separator);
assert_ne!(self.ui.show_engine_list_separator, None);
self.ui.show_version_info = new.ui.show_version_info.or(self.ui.show_version_info);
assert_ne!(self.ui.show_version_info, None);
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) {
existing.update(new);
2024-04-13 02:17:34 +00:00
} else {
self.engines.map.insert(key, new);
2024-04-13 02:17:34 +00:00
}
}
}
}
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,
}
}
}
#[derive(Deserialize, Clone, Debug)]
2024-04-13 02:17:34 +00:00
#[serde(untagged)]
pub enum DefaultableEngineConfig {
Boolean(bool),
Full(FullEngineConfig),
}
impl DefaultableEngineConfig {
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)
}
}
#[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 {
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
}
self.extra = new.extra;
2024-04-13 02:17:34 +00:00
}
}