use anyhow::Context; use serde::{Deserialize, Serialize}; use std::fs; use std::path::PathBuf; #[derive(Serialize, Deserialize, Debug, PartialEq)] #[serde(default)] pub struct Config { /// Tuple of how big thumbnails should be - (width, height) pub thumbnail_size: (u32, u32), /// Tuple of how big thumbnails should be - (width, height) pub view_size: (u32, u32), /// Directory inside the album that the site should be output to pub output_dir: PathBuf, } impl Config { pub fn from_album(path: PathBuf) -> anyhow::Result { let config_path = path.join("photojawn.conf.yml"); let content = fs::read(&config_path).with_context(|| { format!( "Failed to read config from {}. Is this an album directory?", config_path.display(), ) })?; let cfg = serde_yml::from_slice(&content) .with_context(|| format!("Failed to parse config from {}", config_path.display()))?; Ok(cfg) } } impl Default for Config { fn default() -> Self { Self { thumbnail_size: (256, 256), view_size: (1024, 768), output_dir: PathBuf::from("site"), } } } #[cfg(test)] mod test { use super::*; use crate::skel::make_skeleton; use mktemp::Temp; #[test] fn test_default() { let c = Config::default(); assert_eq!(c.thumbnail_size, (256, 256)); assert_eq!(c.output_dir, PathBuf::from("site")); } #[test] fn from_yaml() { // Empty YAML gives full default values let default_cfg = Config::default(); let cfg: Config = serde_yml::from_str("").unwrap(); assert_eq!(cfg, default_cfg); // Default values for any unspecified fields let cfg: Config = serde_yml::from_str("thumbnail_size: [1, 1]").unwrap(); assert_ne!(cfg, default_cfg); assert_eq!(cfg.thumbnail_size, (1, 1)); assert_eq!(cfg.view_size, default_cfg.view_size); } #[test] fn from_base_album() { let tmpdir = Temp::new_dir().unwrap(); make_skeleton(&tmpdir).unwrap(); let cfg = Config::from_album(tmpdir.to_path_buf()).unwrap(); assert_eq!(cfg, Config::default()); } }