diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 2ecb071fcc2a4..d78f00497ca55 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -11,64 +11,79 @@ use std::fs::File; use std::io::prelude::*; use std::io; -use std::path::{PathBuf, Path}; +use std::path::Path; use std::str; #[derive(Clone)] pub struct ExternalHtml{ + /// Content that will be included inline in the section of a + /// rendered Markdown file or generated documentation pub in_header: String, + /// Content that will be included inline between and the content of + /// a rendered Markdown file or generated documentation pub before_content: String, + /// Content that will be included inline between the content and of + /// a rendered Markdown file or generated documentation pub after_content: String } impl ExternalHtml { pub fn load(in_header: &[String], before_content: &[String], after_content: &[String]) -> Option { - match (load_external_files(in_header), - load_external_files(before_content), - load_external_files(after_content)) { - (Some(ih), Some(bc), Some(ac)) => Some(ExternalHtml { - in_header: ih, - before_content: bc, - after_content: ac - }), - _ => None - } + load_external_files(in_header) + .and_then(|ih| + load_external_files(before_content) + .map(|bc| (ih, bc)) + ) + .and_then(|(ih, bc)| + load_external_files(after_content) + .map(|ac| (ih, bc, ac)) + ) + .map(|(ih, bc, ac)| + ExternalHtml { + in_header: ih, + before_content: bc, + after_content: ac, + } + ) } } -pub fn load_string(input: &Path) -> io::Result> { - let mut f = File::open(input)?; - let mut d = Vec::new(); - f.read_to_end(&mut d)?; - Ok(str::from_utf8(&d).map(|s| s.to_string()).ok()) +pub enum LoadStringError { + ReadFail, + BadUtf8, } -macro_rules! load_or_return { - ($input: expr, $cant_read: expr, $not_utf8: expr) => { - { - let input = PathBuf::from(&$input[..]); - match ::externalfiles::load_string(&input) { - Err(e) => { - let _ = writeln!(&mut io::stderr(), - "error reading `{}`: {}", input.display(), e); - return $cant_read; - } - Ok(None) => { - let _ = writeln!(&mut io::stderr(), - "error reading `{}`: not UTF-8", input.display()); - return $not_utf8; - } - Ok(Some(s)) => s - } +pub fn load_string>(file_path: P) -> Result { + let file_path = file_path.as_ref(); + let mut contents = vec![]; + let result = File::open(file_path) + .and_then(|mut f| f.read_to_end(&mut contents)); + if let Err(e) = result { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: {}", + file_path.display(), e); + return Err(LoadStringError::ReadFail); + } + match str::from_utf8(&contents) { + Ok(s) => Ok(s.to_string()), + Err(_) => { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: not UTF-8", + file_path.display()); + Err(LoadStringError::BadUtf8) } } } -pub fn load_external_files(names: &[String]) -> Option { +fn load_external_files(names: &[String]) -> Option { let mut out = String::new(); for name in names { - out.push_str(&*load_or_return!(&name, None, None)); + let s = match load_string(name) { + Ok(s) => s, + Err(_) => return None, + }; + out.push_str(&s); out.push('\n'); } Some(out) diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 1421a3c78fc5a..f708aa5461999 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -19,7 +19,7 @@ use testing; use rustc::session::search_paths::SearchPaths; use rustc::session::config::Externs; -use externalfiles::ExternalHtml; +use externalfiles::{ExternalHtml, LoadStringError, load_string}; use html::render::reset_ids; use html::escape::Escape; @@ -58,7 +58,11 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, css.push_str(&s) } - let input_str = load_or_return!(input, 1, 2); + let input_str = match load_string(input) { + Ok(s) => s, + Err(LoadStringError::ReadFail) => return 1, + Err(LoadStringError::BadUtf8) => return 2, + }; let playground = matches.opt_str("markdown-playground-url"); if playground.is_some() { markdown::PLAYGROUND_KRATE.with(|s| { *s.borrow_mut() = Some(None); }); @@ -144,7 +148,11 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, /// Run any tests/code examples in the markdown file `input`. pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, mut test_args: Vec) -> isize { - let input_str = load_or_return!(input, 1, 2); + let input_str = match load_string(input) { + Ok(s) => s, + Err(LoadStringError::ReadFail) => return 1, + Err(LoadStringError::BadUtf8) => return 2, + }; let mut opts = TestOptions::default(); opts.no_crate_inject = true;