use std::str;
use serde::{Deserialize, Serialize};
use crate::util::TomlValueExt;
#[derive(Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct ProjectConfig {
pub title: Option<String>,
pub authors: Option<Vec<String>>,
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
pub struct Config {
#[serde(default)]
pub project: ProjectConfig,
#[serde(flatten)]
rest: toml::Value,
}
impl Default for Config {
fn default() -> Self {
Self {
project: ProjectConfig::default(),
rest: toml::Value::default(),
}
}
}
impl str::FromStr for Config {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(toml::from_str(s)?)
}
}
#[cfg(test)]
mod test {
use super::*;
use toml::toml;
#[test]
fn config_from_str_empty() {
let config: Config = toml::from_str("").unwrap();
assert_eq!(config, Config::default());
}
#[test]
fn config_from_str_project() {
let content = r#"
[project]
title = "My Blog"
"#;
let config: Config = toml::from_str(content).unwrap();
assert_eq!(
config,
Config {
project: ProjectConfig {
title: Some("My Blog".to_string()),
..Default::default()
},
..Default::default()
}
);
}
#[test]
fn config_from_str_rest() {
let content = r#"
[plugin]
another = 5
"#;
let config: Config = toml::from_str(content).unwrap();
assert_eq!(
config,
Config {
rest: toml! {
[plugin]
another = 5
},
..Default::default()
}
);
}
#[test]
fn config_from_str_both() {
let content = r#"
[project]
title = "My Blog"
[plugin]
another = 5
"#;
let config: Config = toml::from_str(content).unwrap();
assert_eq!(
config,
Config {
project: ProjectConfig {
title: Some("My Blog".to_string()),
..Default::default()
},
rest: toml! {
[plugin]
another = 5
},
}
);
}
}