use crate::{
manifest, references,
zip::{Member, ReadFailure},
};
use core::future::Future;
use structured_asn1::{
memory::{HashWork, OwnedVec, Work},
range::RangeSource,
};
use structured_xades::{
attributes::AttributeXml,
binary::OwnedBinaryXml,
scalar::{ScalarXml, UriXml},
xml::{Access, AccessError, Snapshot, Xml},
};
pub mod signed;
pub trait Types {
type Id: Copy + Eq + HashWork;
type Document: Copy + Eq;
type Generation: Copy + Eq;
type Error;
}
pub trait Parsed: Types {
type View<'a>: Xml<
Id = Self::Id,
Document = Self::Document,
Generation = Self::Generation,
Error = Self::Error,
> + ScalarXml
+ AttributeXml
+ UriXml
+ OwnedBinaryXml
where
Self: 'a;
fn view(&self) -> Self::View<'_>;
fn root(&self) -> Self::Id;
}
pub trait Factory: Types {
type Parsed<'a, W: Work + 'a>: Parsed<
Id = Self::Id,
Document = Self::Document,
Generation = Self::Generation,
Error = Self::Error,
>
where
Self: 'a;
fn parse<'a, W: Work + 'a>(
&'a self,
input: OwnedVec<u8>,
execution: &'a W,
) -> impl Future<Output = Result<Self::Parsed<'a, W>, Self::Error>> + 'a;
}
pub trait Visitor<'v, 's, F: Types + ?Sized, S: RangeSource> {
type Output;
type Error;
fn visit<X, W: Work>(
self,
source: Source<'_, 'v, 's, X, S, W>,
) -> impl Future<Output = Result<Self::Output, Self::Error>>
where
X: Xml<Id = F::Id, Document = F::Document, Generation = F::Generation, Error = F::Error>
+ ScalarXml
+ AttributeXml
+ UriXml
+ OwnedBinaryXml;
}
pub struct Source<'q, 'v, 's, X: Xml, S: RangeSource, W: Work> {
member: &'q Member<'v, 's, S>,
xml: &'q X,
root: X::Id,
snapshot: Snapshot<X::Document, X::Generation>,
execution: &'q W,
}
impl<'v, 's, X: Xml, S: RangeSource, W: Work> Source<'_, 'v, 's, X, S, W> {
#[must_use]
pub fn member(&self) -> &Member<'v, 's, S> {
self.member
}
#[must_use]
pub fn xml(&self) -> &X {
self.xml
}
#[must_use]
pub fn root(&self) -> X::Id {
self.root
}
#[must_use]
pub fn snapshot(&self) -> Snapshot<X::Document, X::Generation> {
self.snapshot
}
#[must_use]
pub fn execution(&self) -> &W {
self.execution
}
}
#[derive(Debug)]
pub enum Error<SE, PE, VE, XE> {
Input(SE),
Produce(PE),
Visit(VE),
Xml(XE),
}
impl<'v, 's, S: RangeSource> Member<'v, 's, S> {
pub async fn with_xml<F: Factory, V: Visitor<'v, 's, F, S>, W: Work>(
&self,
factory: &F,
visitor: V,
work: &W,
) -> Result<
V::Output,
Error<
ReadFailure<S::Error, S::Document, S::Generation>,
F::Error,
V::Error,
AccessError<F::Error, F::Id>,
>,
> {
self.content(work)
.await
.map_err(Error::Input)?
.with_xml(factory, visitor, work)
.await
}
}
impl<'v, 's, S: RangeSource> crate::content::Content<'v, 's, S> {
pub async fn with_xml<F: Factory, V: Visitor<'v, 's, F, S>, W: Work>(
self,
factory: &F,
visitor: V,
work: &W,
) -> Result<
V::Output,
Error<
ReadFailure<S::Error, S::Document, S::Generation>,
F::Error,
V::Error,
AccessError<F::Error, F::Id>,
>,
> {
let archive = self.member().archive();
let execution = archive.session().query(work);
let (member, input) = self.into_parts();
archive
.admit(&execution, member.central_span())
.map_err(|cause| {
Error::Input(ReadFailure::Processing {
member: member.id(),
cause,
})
})?;
let document = factory
.parse(input, &execution)
.await
.map_err(Error::Produce)?;
let root = document.root();
let xml = document.view();
let snapshot = xml.snapshot();
let access = Access::new(&xml, snapshot, &execution);
access.inspect(root, |_| ()).map_err(Error::Xml)?;
member
.archive()
.admit(&execution, member.central_span())
.map_err(|cause| {
Error::Input(ReadFailure::Processing {
member: member.id(),
cause,
})
})?;
let result = visitor
.visit(Source {
member: &member,
xml: &xml,
root,
snapshot,
execution: &execution,
})
.await
.map_err(Error::Visit)?;
access.inspect(root, |_| ()).map_err(Error::Xml)?;
archive
.admit(&execution, member.central_span())
.map_err(|cause| {
Error::Input(ReadFailure::Processing {
member: member.id(),
cause,
})
})?;
Ok(result)
}
}
pub struct Manifest<'q, 'v, 's, X: Xml, S: RangeSource, W: Work> {
xml: &'q X,
execution: &'q W,
catalogue: references::Catalogue<'v, 's, X::Id, X::Document, X::Generation, S>,
}
#[derive(Debug)]
pub enum ManifestError<ME, RE> {
Inspect(ME),
Resolve(RE),
}
pub type ManifestResult<'q, 'v, 's, X, S, W> = Result<
Manifest<'q, 'v, 's, X, S, W>,
ManifestError<
manifest::Error<<X as Xml>::Error, <X as Xml>::Id>,
references::ResolveError<<X as Xml>::Error, <X as Xml>::Id, <S as RangeSource>::Error>,
>,
>;
impl<'q, 'v, 's, X, S, W> Source<'q, 'v, 's, X, S, W>
where
X: Xml + AttributeXml + ScalarXml + UriXml,
S: RangeSource,
W: Work,
{
pub fn package(
&self,
format: crate::package::Format,
) -> crate::package::InspectionResult<'v, 's, X, S> {
let access = Access::new(self.xml, self.snapshot, self.execution);
let base = self
.member
.archive()
.original(self.member.id(), self.execution)
.map_err(crate::package::Error::Archive)?;
crate::package::inspect(base, &access, self.root, format)
}
pub fn manifest(&self) -> ManifestResult<'q, 'v, 's, X, S, W> {
let access = Access::new(self.xml, self.snapshot, self.execution);
let reading = manifest::inspect(&access, self.root).map_err(ManifestError::Inspect)?;
let base = self
.member
.archive()
.original(self.member.id(), self.execution)
.map_err(|cause| ManifestError::Resolve(references::ResolveError::Archive(cause)))?;
let catalogue = references::resolve_manifest(base, reading, self.xml, self.execution)
.map_err(ManifestError::Resolve)?;
Ok(Manifest {
xml: self.xml,
execution: self.execution,
catalogue,
})
}
}
impl<'v, 's, X: Xml, S: RangeSource, W: Work> Manifest<'_, 'v, 's, X, S, W> {
#[must_use]
pub fn source(&self) -> Source<'_, 'v, 's, X, S, W> {
Source {
member: self.catalogue.base(),
xml: self.xml,
root: self.catalogue.reading().root(),
snapshot: self.catalogue.reading().snapshot(),
execution: self.execution,
}
}
#[must_use]
pub fn catalogue(
&self,
) -> &references::Catalogue<'v, 's, X::Id, X::Document, X::Generation, S> {
&self.catalogue
}
pub fn into_facts(self) -> Facts<'v, 's, X::Id, X::Document, X::Generation, S> {
Facts {
catalogue: self.catalogue,
digests: None,
}
}
}
pub struct Facts<'v, 's, N, D, G, S: RangeSource> {
catalogue: references::Catalogue<'v, 's, N, D, G, S>,
digests: Option<OwnedVec<references::DigestReading>>,
}
impl<'v, 's, N: Copy, D: Copy + Eq, G: Copy + Eq, S: RangeSource> Facts<'v, 's, N, D, G, S> {
#[must_use]
pub fn catalogue(&self) -> &references::Catalogue<'v, 's, N, D, G, S> {
&self.catalogue
}
#[must_use]
pub fn object_digests(&self) -> Option<&[references::DigestReading]> {
self.digests.as_deref()
}
}
impl<'v, 's, X: OwnedBinaryXml, S: RangeSource, W: Work> Manifest<'_, 'v, 's, X, S, W> {
pub async fn check_objects<'p, P: structured_xades::certificate::DigestProvider<'p, X>>(
self,
provider: &'p P,
) -> Result<
Facts<'v, 's, X::Id, X::Document, X::Generation, S>,
references::CheckError<
X::Error,
P::Error,
X::Id,
X::Document,
X::Generation,
S::Error,
S::Document,
S::Generation,
>,
> {
let answers = self
.catalogue
.check_objects(self.xml, provider, self.execution)
.await?
.into_answers();
Ok(Facts {
catalogue: self.catalogue,
digests: Some(answers),
})
}
}