menmos_std/
fs.rs

1use std::collections::HashMap;
2use std::path::Path;
3
4use once_cell::sync::OnceCell;
5
6const MIMETYPES_BYTES: &[u8] = include_bytes!("data/mime-types.json");
7
8fn mimetype_map() -> &'static HashMap<String, String> {
9    static MIME_MAP: OnceCell<HashMap<String, String>> = OnceCell::new();
10    MIME_MAP.get_or_init(|| {
11        match serde_json::from_slice::<HashMap<String, String>>(MIMETYPES_BYTES) {
12            Ok(map) => map,
13            Err(e) => {
14                // We're ok with panicking here, this can only happen if we ship invalid JSON.
15                // If that happens, the tests will catch it.
16                panic!("invalid meta map: {}", e);
17            }
18        }
19    })
20}
21
22/// Try to get the mimetype of a given path.
23///
24/// The path doesn't have to exist.
25///
26/// # Examples
27/// ```
28/// let my_file = "test.txt";
29///
30/// let mimetype = menmos_std::fs::mimetype(my_file);
31/// assert_eq!(mimetype, Some(String::from("text/plain")));
32/// ```
33pub fn mimetype<P: AsRef<Path>>(path: P) -> Option<String> {
34    let data = mimetype_map();
35    let extension = path.as_ref().extension()?.to_str()?;
36    data.get(extension).cloned()
37}
38
39#[cfg(test)]
40mod tests {
41    use super::mimetype;
42
43    #[test]
44    fn detect_file_mime_type() {
45        let path = "foo.html";
46        let mime_type = mimetype(path);
47
48        assert!(mime_type.is_some());
49        assert_eq!(mime_type.unwrap(), "text/html");
50    }
51
52    #[test]
53    fn detect_no_mime_type() {
54        let path = "foo.invalid";
55        let mime_type = mimetype(path);
56
57        assert!(mime_type.is_none());
58    }
59}