use super::{ReferenceIdentifier, ReferenceProperty, ResponderIdentifier};
use crate::{
reference::{LexicalSource, VisitError},
scalar::{TextValue, TextXml},
xml::{Access, AccessError},
};
use structured_asn1::ScopedReader;
use structured_pkix::name::{Name, Selector};
#[derive(Debug)]
pub enum ReferenceNameError<E, N> {
Access(AccessError<E, N>),
Xml(E),
Index {
index: usize,
},
Content {
node: N,
},
Name {
node: N,
cause: structured_pkix::Error,
},
}
pub fn matches_reference_name<X: TextXml>(
xml: &X,
references: &ReferenceProperty<X::Id, X::Document, X::Generation>,
index: usize,
actual: &Name<'_>,
operation: &ScopedReader<'_, '_>,
) -> Result<Option<bool>, ReferenceNameError<X::Error, X::Id>> {
let work = operation.execution();
let access = Access::new(xml, references.snapshot(), &work);
access
.query(references.node(), |_, _, _| Ok(()))
.map_err(ReferenceNameError::Access)?;
let Some(entry) = references.entries().get(index) else {
return Err(ReferenceNameError::Index { index });
};
let node = match entry.identifier() {
ReferenceIdentifier::Crl { issuer, .. } => issuer,
ReferenceIdentifier::Ocsp {
responder: ResponderIdentifier::Name(node),
..
} => node,
_ => return Ok(None),
};
let compared = access
.query(node, |xml, snapshot, work| {
Ok(xml.with_text(
snapshot,
node,
LexicalSource::SimpleContent,
work,
|value| {
let TextValue::Present(text) = value else {
return Err(ReferenceNameError::Content { node });
};
let selector = Selector::parse_in(text, operation)
.map_err(|cause| ReferenceNameError::Name { node, cause })?;
selector
.matches_name_in(actual, operation)
.map(Some)
.map_err(|cause| ReferenceNameError::Name { node, cause })
},
))
})
.map_err(ReferenceNameError::Access)?;
compared.map_err(|cause| match cause {
VisitError::Processing(cause) => ReferenceNameError::Xml(cause),
VisitError::Visitor(cause) => cause,
})
}