#[must_use]
pub fn find_mime_match<'a>(requested: &str, available: &'a [String]) -> Option<&'a str> {
if let Some(found) = available.iter().find(|m| m.as_str() == requested) {
return Some(found.as_str());
}
if !requested.starts_with("text/") {
return None;
}
let base = requested.split(';').next()?;
if requested.contains(';') {
if let Some(found) = available.iter().find(|m| m.as_str() == base) {
return Some(found.as_str());
}
} else {
for suffix in [";charset=utf-8", ";charset=UTF-8"] {
let with_charset = format!("{requested}{suffix}");
if let Some(found) = available.iter().find(|m| m.as_str() == with_charset) {
return Some(found.as_str());
}
}
}
available
.iter()
.find(|m| m.split(';').next() == Some(base))
.map(String::as_str)
}
#[cfg(test)]
mod tests {
use super::find_mime_match;
fn types(list: &[&str]) -> Vec<String> {
list.iter().map(|t| (*t).to_owned()).collect()
}
#[test]
fn an_exact_match_is_returned() {
let available = types(&["text/plain", "text/html"]);
assert_eq!(find_mime_match("text/html", &available), Some("text/html"));
}
#[test]
fn a_requested_charset_is_stripped() {
let available = types(&["text/plain"]);
assert_eq!(
find_mime_match("text/plain;charset=utf-8", &available),
Some("text/plain")
);
}
#[test]
fn a_missing_charset_is_added() {
let available = types(&["text/plain;charset=utf-8"]);
assert_eq!(
find_mime_match("text/plain", &available),
Some("text/plain;charset=utf-8")
);
}
#[test]
fn non_text_types_get_no_charset_fallback() {
let available = types(&["image/png;foo=bar"]);
assert_eq!(find_mime_match("image/png", &available), None);
}
#[test]
fn an_exact_match_beats_a_charset_variant() {
let available = types(&["text/plain;charset=utf-8", "text/plain"]);
assert_eq!(
find_mime_match("text/plain", &available),
Some("text/plain")
);
}
#[test]
fn any_charset_of_the_same_base_type_is_accepted() {
let available = types(&["text/plain;charset=iso-8859-1"]);
assert_eq!(
find_mime_match("text/plain", &available),
Some("text/plain;charset=iso-8859-1")
);
}
}