use std::fs; use std::path::{Path, PathBuf}; use serde::Deserialize; #[derive(Deserialize)] struct ConfigFile { site_title: Option, data_dir: Option, external_root: Option, listen_port: Option, footer_copyright: Option, } pub struct Config { site_title: String, data_dir: PathBuf, external_root: String, listen_port: u16, footer_copyright: Option } impl Config { pub fn read_from_file>(path: P) -> Result { let config_contents = fs::read_to_string(&path) .map_err(|_| "Unable to open config file".to_string())?; let file : ConfigFile = toml::from_str(&config_contents) .map_err(|err| err.to_string())?; let port = file.listen_port.unwrap_or(3000); Ok(Self { site_title: file.site_title .unwrap_or("Untitled StormScribe Site".to_string()), data_dir: file.data_dir.unwrap_or(path.as_ref() .canonicalize().map_err(|_| "Cannot resolve config file location".to_string())? .parent().ok_or("Cannot resolve data dir".to_string())?.to_path_buf()), external_root: file.external_root .unwrap_or(format!("http://localhost:{port}/")), listen_port: port, footer_copyright: file.footer_copyright, }) } }