1use super::{Error, Source, Types};
4use crate::{
5 content::Content,
6 error::{Error as ArchiveError, resource},
7 uri::{self, Part},
8 zip::{Archive, Member, MemberId, ReadFailure},
9};
10use core::future::Future;
11use structured_asn1::{
12 memory::{MemoryError, OwnedVec, Work},
13 range::RangeSource,
14};
15use structured_xades::{
16 attributes::AttributeXml,
17 binary::OwnedBinaryXml,
18 binding::{Coverage, Status},
19 reference::{Completeness, Descriptor, Parent, ReferenceXml, VisitError},
20 scalar::{ScalarXml, UriXml},
21 xml::{Access, AccessError, Snapshot, Xml},
22};
23
24pub struct Resource<'v, 's, S: RangeSource> {
29 member: Member<'v, 's, S>,
30}
31impl<S: RangeSource> Resource<'_, '_, S> {
32 #[must_use]
34 pub fn member(&self) -> MemberId<S::Document, S::Generation> {
35 self.member.id()
36 }
37}
38
39pub struct Loaded<'v, 's, S: RangeSource> {
41 content: Content<'v, 's, S>,
42}
43impl<'v, 's, S: RangeSource> Loaded<'v, 's, S> {
44 pub fn into_parts(self) -> (OwnedVec<u8>, Resource<'v, 's, S>) {
48 let (member, bytes) = self.content.into_parts();
49 (bytes, Resource { member })
50 }
51}
52
53pub enum Lookup<'v, 's, S: RangeSource> {
55 Loaded(Loaded<'v, 's, S>),
57 SameDocument(Part),
59 Part(Part),
61 Root,
63 Missing,
65 Ambiguous,
67 Negative(uri::Negative),
69}
70
71pub struct Resources<'v, 's, S: RangeSource> {
75 archive: &'v Archive<'s, S>,
76 base: MemberId<S::Document, S::Generation>,
77}
78impl<'v, 's, S: RangeSource> Resources<'v, 's, S> {
79 #[must_use]
81 pub fn base(&self) -> MemberId<S::Document, S::Generation> {
82 self.base
83 }
84 pub async fn load<W: Work>(
92 &self,
93 base: MemberId<S::Document, S::Generation>,
94 uri: &str,
95 work: &W,
96 ) -> Result<Lookup<'v, 's, S>, ReadFailure<S::Error, S::Document, S::Generation>> {
97 let execution = self.archive.session().query(work);
98 let fail = |cause| ReadFailure::Processing {
99 member: base,
100 cause,
101 };
102 let base = self.archive.original(base, &execution).map_err(fail)?;
103 let target = uri::resolve(base.name(), uri, &execution)
104 .map_err(|cause| fail(resource(base.central_span(), cause)))?;
105 let names = match target {
106 uri::Target::Negative(cause) => return Ok(Lookup::Negative(cause)),
107 uri::Target::SameDocument(part) => return Ok(Lookup::SameDocument(part)),
108 uri::Target::Root(_) => return Ok(Lookup::Root),
109 uri::Target::Member {
110 name,
111 part: Part::Whole,
112 } => self.archive.find(name.as_ref(), &execution).map_err(fail)?,
113 uri::Target::Member { part, .. } => return Ok(Lookup::Part(part)),
114 };
115 if names.is_empty() {
116 return Ok(Lookup::Missing);
117 }
118 if names.len() != 1 {
119 return Ok(Lookup::Ambiguous);
120 }
121 let member = names
122 .member(0, &execution)
123 .map_err(fail)?
124 .expect("one exact original candidate");
125 let content = member.content(&execution).await?;
126 Ok(Lookup::Loaded(Loaded { content }))
127 }
128}
129
130pub struct MemberReference<'a, 'v, 's, N, S: RangeSource> {
133 pub descriptor: Descriptor<'a, N>,
135 pub resource: Option<&'a Resource<'v, 's, S>>,
137}
138
139pub trait MemberReferences<'v, 's, S: RangeSource>: ReferenceXml {
144 fn visit_member_references<VE, W: Work>(
146 &self,
147 snapshot: Snapshot<Self::Document, Self::Generation>,
148 signature: Self::Id,
149 work: &W,
150 visitor: impl for<'a> FnMut(MemberReference<'a, 'v, 's, Self::Id, S>) -> Result<(), VE>,
151 ) -> Result<Completeness<Self::Id>, VisitError<Self::Error, VE>>;
152}
153
154pub trait SignatureParsed<'v, 's, S: RangeSource>: Types {
157 type View<'a>: Xml<
159 Id = Self::Id,
160 Document = Self::Document,
161 Generation = Self::Generation,
162 Error = Self::Error,
163 > + ScalarXml
164 + AttributeXml
165 + UriXml
166 + OwnedBinaryXml
167 + MemberReferences<'v, 's, S>
168 where
169 Self: 'a;
170 fn view(&self) -> Self::View<'_>;
172 fn root(&self) -> Self::Id;
174}
175
176pub trait SignatureFactory<'v, 's, S: RangeSource>: Types {
179 type Parsed<'a, W: Work + 'a>: SignatureParsed<
181 'v,
182 's,
183 S,
184 Id = Self::Id,
185 Document = Self::Document,
186 Generation = Self::Generation,
187 Error = Self::Error,
188 >
189 where
190 Self: 'a,
191 'v: 'a,
192 's: 'a,
193 's: 'v,
194 S: 's + 'v + 'a;
195 fn parse_signed<'a, W: Work + 'a>(
199 &'a self,
200 input: OwnedVec<u8>,
201 resources: &'a Resources<'v, 's, S>,
202 work: &'a W,
203 ) -> impl Future<Output = Result<Self::Parsed<'a, W>, Self::Error>> + 'a
204 where
205 'v: 'a,
206 's: 'a,
207 's: 'v,
208 S: 's + 'v + 'a;
209}
210
211pub trait SignatureVisitor<'v, 's, F: Types + ?Sized, S: RangeSource> {
213 type Output;
215 type Error;
217 fn visit<X, W: Work>(
219 self,
220 source: Source<'_, 'v, 's, X, S, W>,
221 ) -> impl Future<Output = Result<Self::Output, Self::Error>>
222 where
223 X: Xml<Id = F::Id, Document = F::Document, Generation = F::Generation, Error = F::Error>
224 + ScalarXml
225 + AttributeXml
226 + UriXml
227 + OwnedBinaryXml
228 + MemberReferences<'v, 's, S>;
229}
230
231impl<'v, 's, S: RangeSource> Content<'v, 's, S> {
232 pub async fn with_signed_xml<
236 F: SignatureFactory<'v, 's, S>,
237 V: SignatureVisitor<'v, 's, F, S>,
238 W: Work,
239 >(
240 self,
241 factory: &F,
242 visitor: V,
243 work: &W,
244 ) -> Result<
245 V::Output,
246 Error<
247 ReadFailure<S::Error, S::Document, S::Generation>,
248 F::Error,
249 V::Error,
250 AccessError<F::Error, F::Id>,
251 >,
252 > {
253 let archive = self.member().archive();
254 let execution = archive.session().query(work);
255 let (member, input) = self.into_parts();
256 let failure = |cause| {
257 Error::Input(ReadFailure::Processing {
258 member: member.id(),
259 cause,
260 })
261 };
262 archive
263 .admit(&execution, member.central_span())
264 .map_err(failure)?;
265 let resources = Resources {
266 archive,
267 base: member.id(),
268 };
269 let document = factory
270 .parse_signed(input, &resources, &execution)
271 .await
272 .map_err(Error::Produce)?;
273 let root = document.root();
274 let xml = document.view();
275 let snapshot = xml.snapshot();
276 let access = Access::new(&xml, snapshot, &execution);
277 access.inspect(root, |_| ()).map_err(Error::Xml)?;
278 archive
279 .admit(&execution, member.central_span())
280 .map_err(failure)?;
281 let result = visitor
282 .visit(Source {
283 member: &member,
284 xml: &xml,
285 root,
286 snapshot,
287 execution: &execution,
288 })
289 .await
290 .map_err(Error::Visit)?;
291 access.inspect(root, |_| ()).map_err(Error::Xml)?;
292 archive
293 .admit(&execution, member.central_span())
294 .map_err(failure)?;
295 Ok(result)
296 }
297}
298impl<'v, 's, S: RangeSource> Member<'v, 's, S> {
299 pub async fn with_signed_xml<
301 F: SignatureFactory<'v, 's, S>,
302 V: SignatureVisitor<'v, 's, F, S>,
303 W: Work,
304 >(
305 &self,
306 factory: &F,
307 visitor: V,
308 work: &W,
309 ) -> Result<
310 V::Output,
311 Error<
312 ReadFailure<S::Error, S::Document, S::Generation>,
313 F::Error,
314 V::Error,
315 AccessError<F::Error, F::Id>,
316 >,
317 > {
318 self.content(work)
319 .await
320 .map_err(Error::Input)?
321 .with_signed_xml(factory, visitor, work)
322 .await
323 }
324}
325
326#[derive(Debug, Clone, Copy)]
328pub struct Reference<N, D, G> {
329 pub node: N,
331 pub parent: Parent<N>,
333 pub input: Option<MemberId<D, G>>,
335 pub status: Status,
337 pub coverage: Coverage,
339 pub object_location: structured_xades::reference::ObjectLocation,
341}
342pub struct Signature<N, D, G> {
344 pub occurrence: crate::xml::Signature<N>,
346 pub status: Status,
348 pub completeness: Completeness<N>,
350 pub references: OwnedVec<Reference<N, D, G>>,
352}
353pub struct Facts<'v, 's, N, D, G, S: RangeSource> {
355 member: Member<'v, 's, S>,
356 reading: crate::xml::Reading<N, D, G>,
357 signatures: OwnedVec<Signature<N, S::Document, S::Generation>>,
358}
359
360pub struct Assessment<'a, A, N, D, G, SD, SG> {
363 member: MemberId<SD, SG>,
364 snapshot: Snapshot<D, G>,
365 signature: N,
366 inner: structured_xades::baseline::Assessment<'a, A, N, D, G>,
367}
368impl<A, N: Copy, D: Copy, G: Copy, SD: Copy, SG: Copy> Assessment<'_, A, N, D, G, SD, SG> {
369 #[must_use]
371 pub fn member(&self) -> MemberId<SD, SG> {
372 self.member
373 }
374 #[must_use]
376 pub fn signature(&self) -> N {
377 self.signature
378 }
379 #[must_use]
381 pub fn xades(&self) -> &structured_xades::baseline::Assessment<'_, A, N, D, G> {
382 &self.inner
383 }
384}
385#[derive(Debug)]
387pub enum LevelError<E, N, SE> {
388 Xml(AccessError<E, N>),
390 Foreign,
392 Archive(ArchiveError<SE>),
394 Xades(structured_xades::baseline::LevelError),
396}
397pub type AssessmentResult<'a, A, X, S> = Result<
399 Assessment<
400 'a,
401 A,
402 <X as Xml>::Id,
403 <X as Xml>::Document,
404 <X as Xml>::Generation,
405 <S as RangeSource>::Document,
406 <S as RangeSource>::Generation,
407 >,
408 LevelError<<X as Xml>::Error, <X as Xml>::Id, <S as RangeSource>::Error>,
409>;
410pub type LevelAnswer<'r, 'a, A, N, D, G, SD, SG> = Option<&'r Assessment<'a, A, N, D, G, SD, SG>>;
412pub type InspectionResult<'v, 's, X, S> = Result<
414 Facts<'v, 's, <X as Xml>::Id, <X as Xml>::Document, <X as Xml>::Generation, S>,
415 InspectError<<X as Xml>::Error, <X as Xml>::Id, <S as RangeSource>::Error>,
416>;
417pub type MemberAssessment<'a, A, N, D, G, S> =
419 Assessment<'a, A, N, D, G, <S as RangeSource>::Document, <S as RangeSource>::Generation>;
420pub type LevelsResult<'r, 'a, A, N, D, G, S> = Result<
422 Levels<'r, 'a, A, N, D, G, <S as RangeSource>::Document, <S as RangeSource>::Generation>,
423 JoinError<<S as RangeSource>::Error>,
424>;
425
426impl<'v, 's, X, S, W> Source<'_, 'v, 's, X, S, W>
427where
428 X: MemberReferences<'v, 's, S>,
429 S: RangeSource,
430 W: Work,
431{
432 pub fn assess<'a, A>(
436 &self,
437 evidence: structured_xades::baseline::Evidence<'a, A, X::Id, X::Document, X::Generation>,
438 ) -> AssessmentResult<'a, A, X, S> {
439 use structured_xades::baseline::Evidence;
440 let prepared = match &evidence {
441 Evidence::Basic(value) => value.inputs().fields.prepared(),
442 Evidence::Timestamped(value) => value.basic().inputs().fields.prepared(),
443 Evidence::LongTerm(value)
444 | Evidence::Archival {
445 long_term: value, ..
446 } => value.timed().basic().inputs().fields.prepared(),
447 };
448 let containers = prepared.bound().containers();
449 if containers.snapshot() != self.snapshot {
450 return Err(LevelError::Foreign);
451 }
452 let signature = containers.signature();
453 let access = Access::new(self.xml, self.snapshot, self.execution);
454 if !access
455 .has_name(
456 signature,
457 structured_xades::xml::Name {
458 namespace: crate::manifest::DS,
459 local: "Signature",
460 },
461 )
462 .map_err(LevelError::Xml)?
463 {
464 return Err(LevelError::Foreign);
465 }
466 self.member
467 .archive()
468 .admit(self.execution, self.member.central_span())
469 .map_err(LevelError::Archive)?;
470 let inner = structured_xades::baseline::assess(evidence).map_err(LevelError::Xades)?;
471 Ok(Assessment {
472 member: self.member.id(),
473 snapshot: self.snapshot,
474 signature,
475 inner,
476 })
477 }
478}
479
480pub struct Levels<'r, 'a, A, N, D, G, SD, SG> {
482 answers: OwnedVec<LevelAnswer<'r, 'a, A, N, D, G, SD, SG>>,
483 all_roots: bool,
484}
485impl<'r, 'a, A, N, D, G, SD, SG> Levels<'r, 'a, A, N, D, G, SD, SG> {
486 #[must_use]
489 pub fn answers(&self) -> &[LevelAnswer<'r, 'a, A, N, D, G, SD, SG>] {
490 &self.answers
491 }
492 #[must_use]
495 pub fn all_roots_requested_level_met(&self) -> bool {
496 self.all_roots
497 }
498}
499#[derive(Debug)]
501pub enum JoinError<E> {
502 Archive(ArchiveError<E>),
504 Foreign,
506 Duplicate,
508}
509impl<N: Copy + Eq + structured_asn1::memory::HashWork, D: Copy + Eq, G: Copy + Eq, S: RangeSource>
510 Facts<'_, '_, N, D, G, S>
511{
512 pub fn levels<'r, 'a, A, W: Work>(
515 &self,
516 supplied: &[&'r MemberAssessment<'a, A, N, D, G, S>],
517 work: &W,
518 ) -> LevelsResult<'r, 'a, A, N, D, G, S> {
519 let archive = self.member.archive();
520 let execution = archive.session().query(work);
521 archive
522 .admit(&execution, self.member.central_span())
523 .map_err(JoinError::Archive)?;
524 let refusal = |cause| JoinError::Archive(resource(self.member.central_span(), cause));
525 let mut originals = execution.map();
526 for (index, signature) in self.signatures.iter().enumerate() {
527 originals
528 .try_insert(signature.occurrence.node, index)
529 .map_err(refusal)?;
530 }
531 let mut selected = execution.map();
532 for (index, value) in supplied.iter().enumerate() {
533 execution.charge_work(1).map_err(refusal)?;
534 if value.member != self.member.id()
535 || value.snapshot != self.reading.snapshot()
536 || originals
537 .get(&value.signature, &execution)
538 .map_err(refusal)?
539 .is_none()
540 {
541 return Err(JoinError::Foreign);
542 }
543 if selected
544 .try_insert(value.signature, index)
545 .map_err(refusal)?
546 .is_some()
547 {
548 return Err(JoinError::Duplicate);
549 }
550 }
551 let mut answers = execution.vector();
552 answers
553 .try_reserve_exact(self.signatures.len())
554 .map_err(refusal)?;
555 let mut roots = 0usize;
556 let mut all_roots = true;
557 for signature in &self.signatures {
558 let answer = selected
559 .get(&signature.occurrence.node, &execution)
560 .map_err(refusal)?
561 .map(|index| supplied[*index]);
562 if signature.occurrence.direct {
563 roots += 1;
564 match answer {
565 Some(value) if value.inner.all_requirements_met() => {}
566 _ => all_roots = false,
567 }
568 }
569 answers.try_push(answer).map_err(refusal)?;
570 }
571 archive
572 .admit(&execution, self.member.central_span())
573 .map_err(JoinError::Archive)?;
574 Ok(Levels {
575 answers: answers.into_owned(),
576 all_roots: roots != 0 && all_roots,
577 })
578 }
579}
580impl<'v, 's, N: Copy, D: Copy, G: Copy, S: RangeSource> Facts<'v, 's, N, D, G, S> {
581 #[must_use]
583 pub fn member(&self) -> &Member<'v, 's, S> {
584 &self.member
585 }
586 #[must_use]
588 pub fn reading(&self) -> &crate::xml::Reading<N, D, G> {
589 &self.reading
590 }
591 #[must_use]
593 pub fn signatures(&self) -> &[Signature<N, S::Document, S::Generation>] {
594 &self.signatures
595 }
596}
597#[derive(Debug)]
599pub enum InspectError<E, N, SE> {
600 Wrapper(crate::xml::Error<E, N>),
602 Xml(AccessError<E, N>),
604 References(VisitError<E, ReferenceError<SE>>),
606 Archive(ArchiveError<SE>),
608}
609#[derive(Debug)]
611pub enum ReferenceError<E> {
612 Archive(ArchiveError<E>),
614 Foreign,
616 Resource(MemoryError),
618}
619impl<'v, 's, X, S, W> Source<'_, 'v, 's, X, S, W>
620where
621 X: AttributeXml + MemberReferences<'v, 's, S>,
622 S: RangeSource,
623 W: Work,
624{
625 pub fn signatures(&self) -> InspectionResult<'v, 's, X, S> {
628 let access = Access::new(self.xml, self.snapshot, self.execution);
629 let reading = crate::xml::inspect(self.xml, self.root, self.execution)
630 .map_err(InspectError::Wrapper)?;
631 let mut signatures = self.execution.vector();
632 for occurrence in reading.signatures() {
633 access
634 .inspect(occurrence.node, |_| ())
635 .map_err(InspectError::Xml)?;
636 let status = self
637 .xml
638 .signature_status(self.snapshot, occurrence.node, self.execution)
639 .map_err(|cause| InspectError::Xml(AccessError::Xml(cause)))?;
640 let mut references = self.execution.vector();
641 let completeness = self
642 .xml
643 .visit_member_references(self.snapshot, occurrence.node, self.execution, |item| {
644 let input = if let Some(resource) = item.resource {
645 self.execution
646 .charge_work(1)
647 .map_err(ReferenceError::Resource)?;
648 if !core::ptr::eq(resource.member.archive(), self.member.archive()) {
649 return Err(ReferenceError::Foreign);
650 }
651 self.member
652 .archive()
653 .original(resource.member(), self.execution)
654 .map_err(ReferenceError::Archive)?;
655 Some(resource.member())
656 } else {
657 None
658 };
659 references
660 .try_push(Reference {
661 node: item.descriptor.reference.node,
662 parent: item.descriptor.parent,
663 input,
664 status: item.descriptor.reference.status,
665 coverage: item.descriptor.reference.coverage,
666 object_location: item.descriptor.object_location,
667 })
668 .map_err(ReferenceError::Resource)
669 })
670 .map_err(InspectError::References)?;
671 access
672 .inspect(occurrence.node, |_| ())
673 .map_err(InspectError::Xml)?;
674 signatures
675 .try_push(Signature {
676 occurrence: *occurrence,
677 status,
678 completeness,
679 references: references.into_owned(),
680 })
681 .map_err(|cause| {
682 InspectError::Wrapper(crate::xml::Error::Resource {
683 node: occurrence.node,
684 cause,
685 })
686 })?;
687 }
688 let member = self
689 .member
690 .archive()
691 .original(self.member.id(), self.execution)
692 .map_err(InspectError::Archive)?;
693 access
694 .inspect(self.root, |_| ())
695 .map_err(InspectError::Xml)?;
696 Ok(Facts {
697 member,
698 reading,
699 signatures: signatures.into_owned(),
700 })
701 }
702}