datatrash/src/mime_relations.rs

76 lines
2.2 KiB
Rust

use std::{
collections::{HashMap, VecDeque},
str::FromStr,
};
use lazy_static::lazy_static;
use mime::Mime;
lazy_static! {
static ref ALIASES: HashMap<Mime, Mime> = load_mime_aliases();
static ref PARENTS: Vec<(Mime, Mime)> = load_mime_parent_relations();
static ref EXTENSIONS: HashMap<Mime, &'static str> = load_mime_extensions();
}
fn load_mime_aliases() -> HashMap<Mime, Mime> {
tree_magic_db::aliases()
.lines()
.flat_map(|line| line.split_once(' '))
.flat_map(|(a, b)| Some((Mime::from_str(a).ok()?, Mime::from_str(b).ok()?)))
.collect()
}
fn load_mime_parent_relations() -> Vec<(Mime, Mime)> {
tree_magic_db::subclasses()
.lines()
.flat_map(|line| line.split_once(' '))
.flat_map(|(child, parent)| {
Some((Mime::from_str(child).ok()?, Mime::from_str(parent).ok()?))
})
.collect()
}
fn load_mime_extensions() -> HashMap<Mime, &'static str> {
include_str!("../mime.types")
.lines()
.filter(|line| !line.is_empty() && !line.starts_with('#'))
.map(|line| line.split_whitespace())
.flat_map(|mut elements| Some((Mime::from_str(elements.next()?).ok()?, elements.next()?)))
.flat_map(|(mime, extension)| {
Some((ALIASES.get(&mime).unwrap_or(&mime).clone(), extension))
})
.collect()
}
pub(crate) fn get_alias(mimetype: Mime) -> Mime {
ALIASES.get(&mimetype).cloned().unwrap_or(mimetype)
}
fn get_mime_parents(mimetype: &Mime) -> Vec<&Mime> {
PARENTS
.iter()
.filter_map(|(child, parent)| (child == mimetype).then_some(parent))
.collect()
}
pub(crate) fn matches_text(mime: &Mime) -> bool {
if mime.type_() == mime::TEXT {
return true;
}
return get_mime_parents(mime).into_iter().any(matches_text);
}
pub(crate) fn get_extension(mimetype: &Mime) -> Option<&'static str> {
let mut queue = VecDeque::new();
queue.push_back(mimetype);
dbg!(&*EXTENSIONS);
while let Some(mime) = queue.pop_front() {
dbg!(mime);
match EXTENSIONS.get(mimetype).copied() {
Some(ext) => return Some(ext),
None => queue.extend(get_mime_parents(mime)),
}
}
None
}