diff --git a/src/config.rs b/src/config.rs index 78fdc3ad..2943cfea 100644 --- a/src/config.rs +++ b/src/config.rs @@ -294,6 +294,7 @@ impl Default for Config { } } } + impl<'de> Deserialize<'de> for Config { fn deserialize>(de: D) -> std::result::Result { let raw = Value::deserialize(de)?; @@ -310,30 +311,48 @@ impl<'de> Deserialize<'de> for Config { return Ok(Config::from_legacy(raw)); } + use serde::de::Error; let mut table = match raw { Value::Table(t) => t, _ => { - use serde::de::Error; return Err(D::Error::custom( "A config file should always be a toml table", )); } }; - let book: BookConfig = table - .remove("book") - .and_then(|value| value.try_into().ok()) - .unwrap_or_default(); + let book = if let Some(book) = table.remove("book") { + match book.try_into() { + Ok(b) => b, + Err(e) => { + return Err(D::Error::custom(e)); + } + } + } else { + BookConfig::default() + }; - let build: BuildConfig = table - .remove("build") - .and_then(|value| value.try_into().ok()) - .unwrap_or_default(); + let build = if let Some(build) = table.remove("build") { + match build.try_into() { + Ok(b) => b, + Err(e) => { + return Err(D::Error::custom(e)); + } + } + } else { + BuildConfig::default() + }; - let rust: RustConfig = table - .remove("rust") - .and_then(|value| value.try_into().ok()) - .unwrap_or_default(); + let rust = if let Some(rust) = table.remove("rust") { + match rust.try_into() { + Ok(b) => b, + Err(e) => { + return Err(D::Error::custom(e)); + } + } + } else { + RustConfig::default() + }; Ok(Config { book, @@ -1070,4 +1089,57 @@ mod tests { assert_eq!(html_config.input_404, Some("missing.md".to_string())); assert_eq!(&get_404_output_file(&html_config.input_404), "missing.html"); } + + #[test] + #[should_panic(expected = "Invalid configuration file")] + fn invalid_language_type_error() { + let src = r#" + [book] + title = "mdBook Documentation" + language = ["en", "pt-br"] + description = "Create book from markdown files. Like Gitbook but implemented in Rust" + authors = ["Mathieu David"] + src = "./source" + "#; + + Config::from_str(src).unwrap(); + } + + #[test] + #[should_panic(expected = "Invalid configuration file")] + fn invalid_title_type() { + let src = r#" + [book] + title = 20 + language = "en" + description = "Create book from markdown files. Like Gitbook but implemented in Rust" + authors = ["Mathieu David"] + src = "./source" + "#; + + Config::from_str(src).unwrap(); + } + + #[test] + #[should_panic(expected = "Invalid configuration file")] + fn invalid_build_dir_type() { + let src = r#" + [build] + build-dir = 99 + create-missing = false + "#; + + Config::from_str(src).unwrap(); + } + + #[test] + #[should_panic(expected = "Invalid configuration file")] + fn invalid_rust_edition() { + let src = r#" + [rust] + edition = "1999" + "#; + + Config::from_str(src).unwrap(); + } }