use clappconfig::{anyhow, clap::ArgMatches, AppConfig}; use std::collections::HashMap; use std::time::Duration; #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(default)] #[serde(deny_unknown_fields)] pub(crate) struct Config { /// Log level pub(crate) logging: String, /// Per-module log levels pub(crate) log_levels: HashMap, /// Server bind address pub(crate) host: String, /// Server port pub(crate) port: u16, /// Default expiry time in seconds #[serde(with = "serde_duration_secs")] pub(crate) default_expiry: Duration, /// Max expiry time in seconds #[serde(with = "serde_duration_secs")] pub(crate) max_expiry: Duration, /// Expired post clearing interval (triggered on write) #[serde(with = "serde_duration_secs")] pub(crate) expired_gc_interval: Duration, /// Max uploaded file size in bytes pub(crate) max_file_size: usize, /// Enable persistence pub(crate) persistence: bool, /// Enable compression when persisting/loading pub(crate) compression: bool, /// Persistence file pub(crate) persist_file: String, } impl Default for Config { fn default() -> Self { Self { logging: "debug".to_string(), log_levels: Default::default(), host: "0.0.0.0".to_string(), port: 7745, default_expiry: Duration::from_secs(60 * 10), max_expiry: Duration::from_secs(60 * 10), expired_gc_interval: Duration::from_secs(60), max_file_size: 1 * (1024 * 1024), // 1MB persistence: false, compression: true, persist_file: "postit.db".to_string(), } } } impl AppConfig for Config { type Init = Config; fn logging(&self) -> &str { &self.logging } fn logging_mod_levels(&self) -> Option<&HashMap> { Some(&self.log_levels) } fn configure(self, _clap: &ArgMatches) -> anyhow::Result { Ok(self) } } mod serde_duration_secs { use serde::{self, Deserialize, Deserializer, Serializer}; use std::time::Duration; pub fn serialize(value: &Duration, se: S) -> Result where S: Serializer, { se.serialize_u64(value.as_secs()) } pub fn deserialize<'de, D>(de: D) -> Result where D: Deserializer<'de>, { let s: u64 = u64::deserialize(de)?; Ok(Duration::from_secs(s)) } }