use dpp_domain::Audience;
use super::media_type::DppMediaType;
use super::vocabulary::Gs1LinkType;
#[derive(Debug, Clone)]
pub struct ResolutionRequest {
pub link_type: Option<Gs1LinkType>,
pub media_type: Option<DppMediaType>,
pub audience: Option<Audience>,
}
impl ResolutionRequest {
pub fn from_accept_header(accept: &str) -> Self {
Self {
link_type: None,
media_type: parse_best_media_type(accept),
audience: None,
}
}
}
fn parse_best_media_type(accept: &str) -> Option<DppMediaType> {
let mut entries: Vec<(String, f32)> = accept
.split(',')
.filter_map(|entry| {
let mut parts = entry.trim().splitn(2, ';');
let media = parts.next()?.trim().to_owned();
if media.is_empty() {
return None;
}
let q = parts
.next()
.and_then(|p| p.trim().strip_prefix("q="))
.and_then(|q| q.parse::<f32>().ok())
.unwrap_or(1.0);
Some((media, q))
})
.collect();
entries.sort_by(|a, b| {
b.1.partial_cmp(&a.1)
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| {
let a_wild = a.0.contains('*');
let b_wild = b.0.contains('*');
match (a_wild, b_wild) {
(false, true) => std::cmp::Ordering::Less,
(true, false) => std::cmp::Ordering::Greater,
_ => std::cmp::Ordering::Equal,
}
})
});
entries
.iter()
.filter(|(m, q)| *q > 0.0 && !m.contains('*'))
.map(|(m, _)| DppMediaType::parse(m))
.next()
}