Skip to main content

structured_xades/prepare/
uri.rs

1//! URI/OID scalar execution over the original prepared property models.
2
3use super::Prepared;
4use crate::reference::LexicalSource;
5use crate::scalar::{Datatype, ScalarXml, UriXml};
6use crate::xml::{Access, AccessError, Xml};
7use crate::{commitment, format, identifier, policy, scalar};
8use structured_asn1::memory::{MemoryError, Work};
9
10/// Original URI/OID stage failure, with original source and typed cause.
11#[derive(Debug)]
12pub enum UriError<E, N> {
13    /// Foreign source/generation or current-operation dispatch refusal.
14    Access(AccessError<E, N>),
15    /// Original identifier schema failed before scalar interpretation.
16    Structure(crate::properties::Error<E, N>),
17    /// Original URI/OID meaning or documentation refusal.
18    Identifier(identifier::CheckError<E, N>),
19    /// Original requested anyURI value refused or remained unsupported.
20    Scalar(scalar::Error<E, N>),
21    /// A recognized original policy qualifier's URI/integer refusal.
22    Policy(policy::SyntaxError<E, N>),
23}
24
25/// Original prepared URI checks in the XML owner's error/identity domain.
26pub type UriResult<X> = Result<(), UriError<<X as Xml>::Error, <X as Xml>::Id>>;
27
28/// Check all prepared object-format, commitment, policy and policy-store URI
29/// values, including identifier qualifiers/documentation and recognized policy
30/// qualifier integers. This reuses original selected models and the same scalar/
31/// identifier kernels; it does not repeat reference resolution/provider work.
32///
33/// Declared attributes, dates, binary payloads, open-format semantics, type
34/// derivation and complete baseline evidence are separate obligations. In
35/// particular this result cannot promote an unprocessed XMLDSig/counter/path/
36/// timestamp/status receipt into a successful B level. No implicit I/O occurs.
37pub fn check_uris<X: ScalarXml + UriXml, W: Work>(
38    prepared: &Prepared<X>,
39    access: &Access<'_, X, W>,
40) -> UriResult<X> {
41    let layout = prepared.bound().containers();
42    let root = layout.signature();
43    if layout.snapshot() != access.snapshot() {
44        return Err(UriError::Access(AccessError::Changed { node: root }));
45    }
46    access
47        .query(root, |_, _, _| Ok(()))
48        .map_err(UriError::Access)?;
49    let mut at = 0;
50    while at < prepared.formats().len() {
51        admit(access, root)?;
52        let original = prepared.formats()[at].original();
53        format::check_encoding(access, original).map_err(UriError::Scalar)?;
54        scalar::check(
55            access,
56            original.node(),
57            LexicalSource::Attribute(crate::xml::Name {
58                namespace: "",
59                local: "ObjectReference",
60            }),
61            Datatype::AnyUri,
62        )
63        .map_err(UriError::Scalar)?;
64        if let Some(node) = original.identifier() {
65            let identifier = identifier::read(access, node).map_err(UriError::Structure)?;
66            identifier::check(access, &identifier).map_err(UriError::Identifier)?;
67        }
68        at += 1;
69    }
70    let mut at = 0;
71    while at < prepared.commitments().len() {
72        admit(access, root)?;
73        let original = prepared.commitments()[at].original();
74        identifier::check(access, original.kind()).map_err(UriError::Identifier)?;
75        if let commitment::Objects::References(nodes) = original.objects() {
76            let mut index = 0;
77            while index < nodes.len() {
78                admit(access, original.node())?;
79                scalar::check(
80                    access,
81                    nodes[index],
82                    LexicalSource::SimpleContent,
83                    Datatype::AnyUri,
84                )
85                .map_err(UriError::Scalar)?;
86                index += 1;
87            }
88        }
89        at += 1;
90    }
91    if let Some(original) = prepared.policy() {
92        admit(access, root)?;
93        if let policy::Declaration::Explicit(explicit) = original.declaration() {
94            identifier::check(access, &explicit.identifier).map_err(UriError::Identifier)?;
95        }
96        policy::check_qualifier_syntax(access, original).map_err(UriError::Policy)?;
97    }
98    if let Some(original) = prepared.policy_store() {
99        admit(access, root)?;
100        identifier::check(access, original.specification()).map_err(UriError::Identifier)?;
101        if let policy::StoredDocument::Local(node) = original.document() {
102            scalar::check(access, node, LexicalSource::SimpleContent, Datatype::AnyUri)
103                .map_err(UriError::Scalar)?;
104        }
105    }
106    access
107        .query(root, |_, _, _| Ok(()))
108        .map_err(UriError::Access)
109}
110
111fn admit<X: Xml, W: Work>(access: &Access<'_, X, W>, node: X::Id) -> UriResult<X> {
112    access
113        .execution()
114        .charge_work(1)
115        .map_err(|cause: MemoryError| UriError::Access(AccessError::Resource { node, cause }))
116}