use std::sync::Arc;
use rpki::uri;
use rpki::repository::cert::{Cert, ResourceCert};
use rpki::repository::tal::TalInfo;
use rpki::repository::x509::{Validity, Time};
use crate::slurm::ExceptionInfo;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct PayloadInfo {
head: Result<Arc<PublishInfo>, Arc<ExceptionInfo>>,
tail: Option<Box<PayloadInfo>>,
}
impl PayloadInfo {
pub fn add_published(&mut self, info: Arc<PublishInfo>) {
self.tail = Some(Box::new(PayloadInfo {
head: Ok(info),
tail: self.tail.take()
}));
}
pub fn add_local(&mut self, info: Arc<ExceptionInfo>) {
self.tail = Some(Box::new(PayloadInfo {
head: Err(info),
tail: self.tail.take()
}));
}
pub fn iter(&self) -> PayloadInfoIter<'_> {
PayloadInfoIter { info: Some(self) }
}
pub fn tal_name(&self) -> Option<&str> {
self.head.as_ref().map(|info| info.tal.name()).ok()
}
pub fn uri(&self) -> Option<&uri::Rsync> {
self.head.as_ref().ok().and_then(|info| info.uri.as_ref())
}
pub fn validity(&self) -> Option<Validity> {
self.head.as_ref().map(|info| info.roa_validity).ok()
}
pub fn publish_info(&self) -> Option<&PublishInfo> {
match self.head {
Ok(ref info) => Some(info),
Err(_) => None
}
}
pub fn exception_info(&self) -> Option<&ExceptionInfo> {
match self.head {
Ok(_) => None,
Err(ref info) => Some(info),
}
}
}
impl From<Arc<PublishInfo>> for PayloadInfo {
fn from(src: Arc<PublishInfo>) -> Self {
PayloadInfo { head: Ok(src), tail: None }
}
}
impl From<Arc<ExceptionInfo>> for PayloadInfo {
fn from(src: Arc<ExceptionInfo>) -> Self {
PayloadInfo { head: Err(src), tail: None }
}
}
impl<'a> IntoIterator for &'a PayloadInfo {
type Item = &'a PayloadInfo;
type IntoIter = PayloadInfoIter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Clone, Debug)]
pub struct PayloadInfoIter<'a> {
info: Option<&'a PayloadInfo>,
}
impl<'a> Iterator for PayloadInfoIter<'a> {
type Item = &'a PayloadInfo;
fn next(&mut self) -> Option<Self::Item> {
let res = self.info?;
self.info = res.tail.as_ref().map(AsRef::as_ref);
Some(res)
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct PublishInfo {
pub tal: Arc<TalInfo>,
pub uri: Option<uri::Rsync>,
pub roa_validity: Validity,
pub chain_validity: Validity,
pub point_stale: Time,
}
impl PublishInfo {
pub fn signed_object(
cert: &ResourceCert,
ca_validity: Validity,
point_stale: Time,
) -> Self {
PublishInfo {
tal: cert.tal().clone(),
uri: cert.signed_object().cloned().map(|mut uri| {
uri.unshare(); uri
}),
roa_validity: cert.validity(),
chain_validity: cert.validity().trim(ca_validity),
point_stale,
}
}
pub fn router_cert(
cert: &Cert,
uri: &uri::Rsync,
tal: Arc<TalInfo>,
ca_validity: Validity,
point_stale: Time,
) -> Self {
PublishInfo {
tal,
uri: Some(uri.clone()),
roa_validity: cert.validity(),
chain_validity: cert.validity().trim(ca_validity),
point_stale,
}
}
}