1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use walkdir::{DirEntry, WalkDir};

pub fn from<P: AsRef<Path>>(path: P) -> WalkPaths {
    WalkPaths::new(path.as_ref().to_path_buf())
}

#[derive(Debug)]
pub enum Cast {
    Str,
    Bytes,
}

#[derive(Debug)]
pub struct WalkPaths {
    entry_path: PathBuf,
    entries: Vec<DirEntry>,
    cast: Cast,
}

impl WalkPaths {
    fn new(path: PathBuf) -> WalkPaths {
        WalkPaths {
            entry_path: path.to_owned(),
            entries: WalkDir::new(path)
                .into_iter()
                .filter_map(|e| {
                    if let Ok(dir_entry) = e {
                        if !dir_entry.path().is_dir() {
                            return Some(dir_entry);
                        }
                    }
                    None
                })
                .collect(),
            cast: Cast::Str,
        }
    }

    pub fn filter<P>(self, predicate: P) -> WalkPaths
    where
        P: FnMut(&DirEntry) -> bool,
    {
        WalkPaths {
            entries: self.entries.into_iter().filter(predicate).collect(),
            ..self
        }
    }

    pub fn bytes(self) -> WalkPaths {
        WalkPaths {
            cast: Cast::Bytes,
            ..self
        }
    }

    pub fn str(self) -> WalkPaths {
        WalkPaths {
            cast: Cast::Str,
            ..self
        }
    }

    pub fn to<P: AsRef<Path>>(self, path: P) -> Result<(), Box<dyn std::error::Error>> {
        let path = path.as_ref().to_path_buf();
        match self.cast {
            Cast::Str => write(path, String::from("include_str"), self),
            Cast::Bytes => write(path, String::from("include_bytes"), self),
        }
    }
}

fn write(path: PathBuf, stmacro: String, walk_paths: WalkPaths) -> Result<(), Box<dyn Error>> {
    let mut all_the_files = File::create(&path)?;

    writeln!(&mut all_the_files, r#"use std::collections::HashMap;"#,)?;
    writeln!(&mut all_the_files, r#""#,)?;
    writeln!(&mut all_the_files, r#"#[allow(dead_code)]"#,)?;
    writeln!(
        &mut all_the_files,
        r#"pub fn getAll() -> HashMap<&'static str, &'static str> {{"#,
    )?;
    writeln!(&mut all_the_files, r#"    let mut out = HashMap::new();"#,)?;

    for f in walk_paths.entries {
        let f = f
            .path()
            .strip_prefix(
                path.parent()
                    // TODO: Fix
                    .ok_or(".... fail to get parent path  ....")?,
            )
            .ok()
            .map_or(f.path(), |el| el);

        writeln!(
            &mut all_the_files,
            r#"    out.insert("{path}", {stmacro}!("{path}"));"#,
            stmacro = stmacro,
            path = f.display()
        )?;
    }

    writeln!(&mut all_the_files, r#"    out"#,)?;
    writeln!(&mut all_the_files, r#"}}"#,)?;

    Ok(())
}