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
#[macro_use]
extern crate log;
extern crate walkdir;

#[cfg(debug_assertions)]
pub fn generate_assets(parent_path: String) -> Box<Fn(String) -> Option<Vec<u8>>> {
    use std::fs::File;
    use std::path::Path;
    use std::io::Read;
    info!("rust-embed: loading folder -> {}", parent_path);
    Box::new(move |file_path| {
        let name = &format!("{}{}", parent_path, file_path);
        let path = &Path::new(name);
        let key = String::from(path.to_str().expect("Path does not have a string representation"));
        info!("rust-embed: asset from file -> {}", key);
        let mut file = match File::open(path) {
            Ok(mut file) => file,
            Err(e) => {
                error!("rust-embed: could not open file -> {} {}", key, e);
                return None
            }
        };
        let mut data: Vec<u8> = Vec::new();
        match file.read_to_end(&mut data) {
            Ok(_) => Some(data),
            Err(e) =>  {
                error!("rust-embed: could not open file -> {} {}", key, e);
                return None
            }
        }
    })
}

#[cfg(not(debug_assertions))]
pub fn generate_assets<'a>(parent_path: String) -> Box<Fn(String) -> Option<Vec<u8>>> {
    use std::fs::File;
    use std::io::Read;
    use std::path::Path;
    use walkdir::WalkDir;
    use std::collections::HashMap;

    info!("rust-embed: loading folder -> {}", parent_path);
    let mut map = HashMap::new();
    for entry in WalkDir::new(parent_path.clone()).into_iter().filter_map(|e| e.ok()).filter(|e| e.file_type().is_file()) {
        info!("rust-embed: asset from file -> {}", entry.path().display());
        let base = &parent_path.clone();
        let key = String::from(entry.path().to_str().expect("Path does not have a string representation")).replace(base, "");
        let mut file = File::open(&Path::new(&entry.path())).unwrap_or_else(|e| {
            panic!("rust-embed: could not open file -> {} {}", key, e);
        });
        let mut data: Vec<u8> = Vec::new();
        file.read_to_end(&mut data).unwrap_or_else(|e| {
            panic!("rust-embed: could not read file -> {} {}", key, e);
        });
        map.insert(key, data);
    }
    Box::new(move |file_path| {
        match map.get(&file_path) {
            Some(s) => Some(s.to_vec()),
            None => None,
        }
    })
}

#[macro_export]
macro_rules! embed {
    ($x:expr) => ( ::generate_assets($x) )
}

#[cfg(test)]
mod tests {
    #[test]
    #[cfg(debug_assertions)]
    fn dev() {
        let asset = embed!("examples/public".to_owned());
        match asset("/index.html".to_owned()) {
            None => assert!(false, "index.html should exist"),
            _ => assert!(true),
        }
        match asset("/gg.html".to_owned()) {
            Some(_) => assert!(false, "gg.html should not exist"),
            _ => assert!(true),
        }
        match asset("/images/llama.png".to_owned()) {
            None => assert!(false, "llama.png should exist"),
            _ => assert!(true),
        }
    }

    #[test]
    #[cfg(not(debug_assertions))]
    fn prod() {
        let asset = embed!("examples/public".to_owned());
        match asset("/index.html".to_owned()) {
            None => assert!(false, "index.html should exist"),
            _ => assert!(true),
        }
        match asset("/gg.html".to_owned()) {
            Some(_) => assert!(false, "gg.html should not exist"),
            _ => assert!(true),
        }
        match asset("/images/llama.png".to_owned()) {
            None => assert!(false, "llama.png should exist"),
            _ => assert!(true),
        }
    }
}