use crate::paths::Paths;
use anyhow::{Context, Result};
use serde::Deserialize;
#[derive(Debug, Default, Clone, Deserialize)]
pub struct Config {
#[serde(default)]
pub server: ServerConfig,
#[serde(default)]
pub auth: AuthConfig,
#[serde(default)]
pub auto_update: AutoUpdateConfig,
#[serde(default)]
pub rate_limit: RateLimitConfig,
}
#[derive(Debug, Clone, Deserialize)]
pub struct ServerConfig {
#[serde(default = "default_bind")]
pub bind: String,
#[serde(default)]
pub cors_origins: Vec<String>,
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
bind: default_bind(),
cors_origins: Vec::new(),
}
}
}
fn default_bind() -> String {
"127.0.0.1:8000".to_string()
}
#[derive(Debug, Default, Clone, Deserialize)]
pub struct AuthConfig {
#[serde(default)]
pub tokens: Vec<String>,
#[serde(default)]
pub admin_tokens: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AutoUpdateConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default = "default_interval")]
pub interval: String,
#[serde(default)]
pub pin: String,
}
impl Default for AutoUpdateConfig {
fn default() -> Self {
Self {
enabled: false,
interval: default_interval(),
pin: String::new(),
}
}
}
fn default_interval() -> String {
"24h".to_string()
}
#[derive(Debug, Clone, Deserialize)]
pub struct RateLimitConfig {
#[serde(default = "default_per_second")]
pub per_second: u64,
#[serde(default = "default_burst_size")]
pub burst_size: u32,
}
impl Default for RateLimitConfig {
fn default() -> Self {
Self {
per_second: default_per_second(),
burst_size: default_burst_size(),
}
}
}
fn default_per_second() -> u64 {
1
}
fn default_burst_size() -> u32 {
5
}
impl Config {
pub fn load(paths: &Paths) -> Result<Self> {
if !paths.config_file.exists() {
return Ok(Self::default());
}
let content = std::fs::read_to_string(&paths.config_file).with_context(|| {
format!("設定ファイル読み込み失敗: {}", paths.config_file.display())
})?;
let cfg: Self = toml::from_str(&content)
.with_context(|| format!("設定ファイルパース失敗: {}", paths.config_file.display()))?;
Ok(cfg)
}
}