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
use headers::HeaderMapExt;
use hyper::{Body, Response};


#[derive(PartialEq, Eq)]
pub enum IndexHandling {
    MapEmptyPathToIndex,
    NoIndexHandling,
}


/// Wraps a hashmap of static content generated at compile time and provides convenience
/// functions for resolving static content given a path.
pub struct StaticLookup {
    pub index_mode: IndexHandling,
    pub wasm: &'static phf::Map<&'static str, &'static [u8]>,
}

impl StaticLookup {
    /// Given a path ('/', '/css/tree.css', etc) attempt to construct a 'hyper::Response'
    /// using the static hashmap generated at compile time. Infers MIME type from path.
    ///
    /// path expected as `let x: http::uri::PathAndQuery = ..; x.as_str()`, omiting type to simplify interface
    pub fn get(&self, path: &str) -> Option<Response<Body>> {
        // drop leading '/' from path
        let path = &path[1..];

        let path = if path.len() == 0 && self.index_mode == IndexHandling::MapEmptyPathToIndex {
            "index.html"
        } else {
            path
        };

        match self.wasm.get(path).map(|p| *p) {
            None => None,
            Some(blob) => {
                let body = hyper::Body::from(blob);
                let mut resp = hyper::Response::new(body);

                let mime_type = mime_guess::from_path(path).first_or_octet_stream();
                resp.headers_mut()
                    .typed_insert(headers::ContentType::from(mime_type));
                resp.headers_mut()
                    .typed_insert(headers::AcceptRanges::bytes());
                resp.headers_mut()
                    .typed_insert(headers::ContentLength(blob.len() as u64));

                Some(resp)
            }
        }
    }
}

/// Imports the generated static wasm blobs from the build output directory as
/// generated by embed_wasm_build::compile_wasm
#[macro_export]
macro_rules! include_wasm {
    () => {
        include!(concat!(env!("OUT_DIR"), "/wasm_blobs.rs"));

        // FIXME: will fail if user aliases embed_wasm
        pub static STATIC_LOOKUP: ::embed_wasm::StaticLookup  =
            ::embed_wasm::StaticLookup{
                index_mode: ::embed_wasm::IndexHandling::MapEmptyPathToIndex,
                wasm: &WASM,
        };
    };
}