1 use std::env;
2 use std::io::{self, Write, BufRead};
3 use std::fs::{self, DirEntry};
4 use std::ffi::OsString;
5 use std::path::{Path, PathBuf};
6 
7 // one possible implementation of walking a directory only visiting files
visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry) -> io::Result<()>) -> io::Result<()>8 fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry) -> io::Result<()>)
9               -> io::Result<()> {
10     if dir.is_dir() {
11         for entry in fs::read_dir(dir)? {
12             let entry = entry?;
13             let path = entry.path();
14             if path.is_dir() {
15                 visit_dirs(&path, cb)?;
16             } else {
17                 cb(&entry)?;
18             }
19         }
20     }
21     Ok(())
22 }
23 
manifest_dir() -> PathBuf24 fn manifest_dir() -> PathBuf {
25     PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap())
26 }
27 
out_dir() -> PathBuf28 fn out_dir() -> PathBuf {
29     env::var_os("OUT_DIR").unwrap().into()
30 }
31 
lib_path() -> PathBuf32 fn lib_path() -> PathBuf {
33     out_dir().join("src/lib.rs")
34 }
35 
translate_path(src: &Path) -> PathBuf36 fn translate_path(src: &Path) -> PathBuf {
37     let src = src.to_str().unwrap();
38     format!("{}rs", &src[..src.len() - 2]).into()
39 }
40 
translate2rs(src: &DirEntry) -> io::Result<()>41 fn translate2rs(src: &DirEntry) -> io::Result<()> {
42     let path = src.path();
43     if path.extension() != Some(&OsString::from("md")) {
44         return Ok(());
45     }
46 
47     let sink_filename = out_dir().join(
48         translate_path(&path).strip_prefix(&manifest_dir()).unwrap());
49 
50     eprintln!("{:?} -> {:?}", path, sink_filename);
51     println!("rerun-if-changed={}", path.to_str().unwrap());
52 
53     fs::create_dir_all(sink_filename.parent().unwrap())?;
54     let mut sink = fs::File::create(sink_filename)?;
55 
56     for line in io::BufReader::new(fs::File::open(&path)?).lines() {
57         writeln!(&mut sink, "//! {}", line?)?;
58     }
59 
60     let mut lib =
61         fs::OpenOptions::new().create(true).append(true).open(&lib_path())?;
62     writeln!(&mut lib, "pub mod {};", path.file_stem().unwrap().to_str().unwrap())?;
63 
64     Ok(())
65 }
66 
main()67 fn main() {
68     let _ = fs::remove_file(&lib_path());
69     visit_dirs(&manifest_dir().join("src"), &translate2rs).unwrap();
70 }
71