use xdg_mime::SharedMimeInfo; use std::path::Path; use std::io; use mime_guess::Mime; use std::fs::File; use std::io::Read; use smartstring::alias::String; use cached::proc_macro::cached; pub fn mime_type(db: &SharedMimeInfo, path: &Path) -> io::Result, > { // attempt to read up to the 256 bytes of the file let mut buffer = [0; 256]; let mut file = File::open(path)?; // this can be ignored because it's perfectly okay if the file is less than 256 bytes long - we only care about the // first few bytes for the purpose of mime sniffing #[allow(clippy::unused_io_amount)] file.read(&mut buffer)?; Ok(db.get_mime_type_for_data(&buffer).map(|m| m.0)) } #[cached] // TODO: avoid cloning mime if possible, although i don't really see how it would be - maybe instead of passing the mime // object, pass a hash of it? pub fn mime_extension_lookup(mime: Mime) -> Option> { if mime == mime_guess::mime::IMAGE_JPEG { // jpeg files are given the primary extension "jpe", due to the extension list being stored in alphabetical order. // to handle this particular case, return a custom vector consisting of just "jpg" and "jpeg". return Some(vec![String::from("jpg"), String::from("jpeg")]); } match mime_guess::get_mime_extensions(&mime) { // get a list of possible extensions for this mime type Some(exts) => Some(exts.iter().map(|e| String::from(*e)).collect()), None => None } }