~vpzom/hitide

1c2477ed05dde6e54fd445fef82a642f39a159e7 — Colin Reeder 11 months ago 0fcebe5
Hashing and caching for icons (#100)
4 files changed, 58 insertions(+), 45 deletions(-)

A icons/build.rs
R icons/res/{notifications-some.svg => notifications_some.svg}
M icons/src/lib.rs
M src/routes/static.rs
A icons/build.rs => icons/build.rs +52 -0
@@ 0,0 1,52 @@
use std::hash::{Hash, Hasher};
use std::io::Write;

fn main() {
    println!("cargo:rerun-if-changed=res");
    let mut file =
        std::fs::File::create(format!("{}/icons.rs", std::env::var("OUT_DIR").unwrap())).unwrap();
    let mut mapping = Vec::new();

    writeln!(file, "use super::Icon;").unwrap();

    for res in std::fs::read_dir("res").unwrap() {
        let path = res.unwrap().path();
        if path.is_dir() {
            continue;
        }

        println!("{:?}", path);

        let content = std::fs::read(&path).unwrap();

        let mut hasher = std::collections::hash_map::DefaultHasher::new();
        content.hash(&mut hasher);
        let hash = hasher.finish();

        let key = format!("{}.svg", hash);

        let name = path.file_name().unwrap().to_str().unwrap();
        let name = (&name[0..name.len() - 4]).to_ascii_uppercase();

        writeln!(
            file,
            "pub const {}: Icon=Icon{{path:\"{}\",content:include_str!(\"{}\")}};",
            name,
            key,
            path.canonicalize().unwrap().to_str().unwrap()
        )
        .unwrap();

        mapping.push((key, name));
    }

    writeln!(
        file,
        "pub const ICONS_MAP: phf::Map<&'static str, &'static Icon> = phf::phf_map! {{"
    )
    .unwrap();
    for (key, name) in mapping {
        writeln!(file, "\"{}\" => &{},", key, name).unwrap();
    }
    writeln!(file, "}};").unwrap();
}

R icons/res/notifications-some.svg => icons/res/notifications_some.svg +0 -0
M icons/src/lib.rs => icons/src/lib.rs +2 -45
@@ 3,50 3,7 @@ pub struct Icon {
    pub content: &'static str,
}

macro_rules! icons_consts {
    ($i:ident => $p:expr) => {
        pub const $i: Icon = Icon {
            path: $p,
            content: include_str!(concat!("../res/", $p)),
        };
    };
    ($i1:ident => $p1:expr, $($i2:ident => $p2:expr),+) => {
        icons_consts! { $i1 => $p1 }
        icons_consts! { $($i2 => $p2),+ }
    }
mod icons {
    include!(concat!(env!("OUT_DIR"), "/icons.rs"));
}

macro_rules! icons_map {
    ($($i:ident => $p:expr),+) => {
        pub const ICONS_MAP: phf::Map<&'static str, &'static Icon> = phf::phf_map! {
            $($p => &icons::$i),+
        };
    }
}

macro_rules! icons {
    ($($i:ident => $p:expr),+) => {
        pub mod icons {
            use super::Icon;

            icons_consts! {
                $($i => $p),+
            }
        }

        icons_map! {
            $($i => $p),+
        }
    }
}

icons! {
    LOGOUT => "logout.svg",
    NOTIFICATIONS => "notifications.svg",
    NOTIFICATIONS_SOME => "notifications-some.svg",
    PERSON => "person.svg",
    UPVOTE => "upvote.svg",
    UPVOTED => "upvoted.svg"
}

pub use icons::*;

M src/routes/static.rs => src/routes/static.rs +4 -0
@@ 27,6 27,10 @@ async fn handler_static_get(
            hyper::header::CONTENT_TYPE,
            hyper::header::HeaderValue::from_static("image/svg+xml"),
        );
        resp.headers_mut().insert(
            hyper::header::CACHE_CONTROL,
            hyper::header::HeaderValue::from_static("max-age=31536000, immutable"),
        );

        Ok(resp)
    } else {