use super::{Declaration, Original, XADES, XADES_141, named, user_notice_with};
use crate::identifier;
use crate::properties::Error;
use crate::reference::LexicalSource;
use crate::scalar::{self, Datatype, ScalarXml, UriXml};
use crate::xml::{Access, AccessError, Xml};
use structured_asn1::memory::Work;
#[derive(Debug)]
pub enum SyntaxError<E, N> {
Structure(Error<E, N>),
Scalar(scalar::Error<E, N>),
Identifier(identifier::CheckError<E, N>),
}
impl<E, N> From<Error<E, N>> for SyntaxError<E, N> {
fn from(cause: Error<E, N>) -> Self {
Self::Structure(cause)
}
}
pub type SyntaxResult<X> = Result<(), SyntaxError<<X as Xml>::Error, <X as Xml>::Id>>;
pub fn check_qualifier_syntax<X: ScalarXml + UriXml, W: Work>(
access: &Access<'_, X, W>,
reading: &Original<X>,
) -> SyntaxResult<X> {
if reading.snapshot() != access.snapshot() {
return Err(Error::Access(AccessError::Changed {
node: reading.node(),
})
.into());
}
access
.query(reading.node(), |_, _, _| Ok(()))
.map_err(Error::Access)?;
let Declaration::Explicit(explicit) = reading.declaration() else {
return Ok(());
};
let mut index = 0;
while index < explicit.qualifiers.len() {
access
.execution()
.charge_work(1)
.map_err(|cause| Error::Resource {
node: reading.node(),
cause,
})?;
let qualifier = &explicit.qualifiers[index];
let mut child = access.first_child(qualifier.node).map_err(Error::Access)?;
while let Some(node) = child {
if named(access, node, XADES, "SPURI")? {
scalar::check(access, node, LexicalSource::SimpleContent, Datatype::AnyUri)
.map_err(SyntaxError::Scalar)?;
} else if named(access, node, XADES, "SPUserNotice")? {
user_notice_with(access, node, |number| {
scalar::check(
access,
number,
LexicalSource::SimpleContent,
Datatype::Integer,
)
.map_err(SyntaxError::Scalar)
})?;
} else if named(access, node, XADES_141, "SPDocSpecification")? {
let reading = identifier::read(access, node).map_err(SyntaxError::Structure)?;
identifier::check(access, &reading).map_err(SyntaxError::Identifier)?;
}
child = access
.next_sibling(qualifier.node, node)
.map_err(Error::Access)?;
}
index += 1;
}
access
.query(reading.node(), |_, _, _| Ok(()))
.map_err(Error::Access)?;
Ok(())
}