use super::{
ReferenceIdentifier, ReferenceNameError, ReferenceProperty, ReferenceTime, ReferenceTimeError,
matches_reference_name, matches_reference_time,
};
use crate::{
binary::{self, Location},
properties::CalendarXml,
scalar::TextXml,
xml::{Access, AccessError, Xml},
};
use structured_asn1::ScopedReader;
use structured_pkix::crl::CertificateList;
pub struct CrlReferenceIdentity<N> {
issuer: bool,
issued_at: ReferenceTime,
number_hint: Option<N>,
}
impl<N: Copy> CrlReferenceIdentity<N> {
#[must_use]
pub fn issuer_matches(&self) -> bool {
self.issuer
}
#[must_use]
pub fn issued_at(&self) -> ReferenceTime {
self.issued_at
}
#[must_use]
pub fn number_hint(&self) -> Option<N> {
self.number_hint
}
}
#[derive(Debug)]
pub enum CrlReferenceError<E, N> {
Access(AccessError<E, N>),
Index {
index: usize,
},
Name(ReferenceNameError<E, N>),
Time(ReferenceTimeError<E, N>),
}
pub type CrlReferenceResult<X> = Result<
Option<binary::LocatedValue<CrlReferenceIdentity<<X as Xml>::Id>, X>>,
CrlReferenceError<<X as Xml>::Error, <X as Xml>::Id>,
>;
pub fn check_crl_reference<X: TextXml + CalendarXml>(
xml: &X,
references: &ReferenceProperty<X::Id, X::Document, X::Generation>,
index: usize,
actual: &CertificateList<'_>,
operation: &ScopedReader<'_, '_>,
) -> CrlReferenceResult<X> {
let work = operation.execution();
let access = Access::new(xml, references.snapshot(), &work);
access
.query(references.node(), |_, _, _| Ok(()))
.map_err(CrlReferenceError::Access)?;
let Some(entry) = references.entries().get(index) else {
return Err(CrlReferenceError::Index { index });
};
let ReferenceIdentifier::Crl { node, number, .. } = entry.identifier() else {
return Ok(None);
};
let issuer = matches_reference_name(xml, references, index, actual.tbs().issuer(), operation)
.map_err(CrlReferenceError::Name)?
.expect("original CRL issuer entry");
let issued_at = matches_reference_time(
xml,
references,
index,
actual.tbs().this_update(),
operation,
)
.map_err(CrlReferenceError::Time)?
.expect("original CRL time entry");
access
.query(node, |_, _, _| Ok(()))
.map_err(CrlReferenceError::Access)?;
Ok(Some(binary::Located {
location: Location {
snapshot: references.snapshot(),
node,
},
value: CrlReferenceIdentity {
issuer,
issued_at,
number_hint: number,
},
}))
}