use dpp_domain::{Audience, Disclosure};
use serde::{Deserialize, Serialize};
use super::media_type::DppMediaType;
use super::request::ResolutionRequest;
use super::vocabulary::Gs1LinkType;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LinkDescriptor {
pub href: String,
pub link_type: Gs1LinkType,
pub media_type: DppMediaType,
pub disclosure: Disclosure,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
}
pub fn negotiate<'a>(
available: &'a [LinkDescriptor],
request: &ResolutionRequest,
) -> Option<&'a LinkDescriptor> {
let audience = request.audience.unwrap_or(Audience::Public);
let accessible: Vec<&LinkDescriptor> = available
.iter()
.filter(|d| audience.may_see(d.disclosure))
.collect();
if accessible.is_empty() {
return None;
}
let by_link_type: Vec<&LinkDescriptor> = if let Some(ref lt) = request.link_type {
let matched: Vec<_> = accessible
.iter()
.filter(|d| d.link_type == *lt)
.copied()
.collect();
if matched.is_empty() {
return None;
}
matched
} else {
accessible
};
let candidates = &by_link_type;
if let Some(ref mt) = request.media_type
&& let Some(exact) = candidates.iter().find(|d| d.media_type == *mt)
{
return Some(exact);
}
candidates.first().copied()
}