use super::{CheckError, CheckResult, Checked, Report, check};
use crate::{
binary::BinaryXml,
digest::StreamingDigest,
prepare::{Preparation, Prepared},
timestamp::TimestampXml,
xml::{Access, Xml},
};
use structured_asn1::memory::{OwnedVec, Work};
pub struct PreparedChecks<'prepared, N, D, G, E> {
prepared: &'prepared Preparation<N, D, G>,
reports: OwnedVec<Report<N, D, G, E>>,
agrees: bool,
}
impl<N: Copy, D: Copy, G: Copy, E> PreparedChecks<'_, N, D, G, E> {
#[must_use]
pub fn prepared(&self) -> &Preparation<N, D, G> {
self.prepared
}
#[must_use]
pub fn reports(&self) -> &[Report<N, D, G, E>] {
&self.reports
}
#[must_use]
pub fn all_written_renewals_agree(&self) -> bool {
self.agrees
}
}
pub type PreparedResult<'prepared, X, PE> = CheckResult<
PreparedChecks<
'prepared,
<X as Xml>::Id,
<X as Xml>::Document,
<X as Xml>::Generation,
<X as Xml>::Error,
>,
X,
PE,
>;
pub fn check_prepared<'prepared, X: TimestampXml + BinaryXml, P: StreamingDigest<X>, W: Work>(
xml: &X,
prepared: &'prepared Prepared<X>,
provider: &P,
work: &W,
) -> PreparedResult<'prepared, X, P::Error> {
let layout = prepared.bound().containers();
let signature = layout.signature();
let access = Access::new(xml, layout.snapshot(), work);
access
.query(signature, |_, _, _| Ok(()))
.map_err(CheckError::Access)?;
let mut reports: OwnedVec<Checked<X>, W> = work.vector();
reports
.try_reserve_exact(prepared.renewed().len())
.map_err(|cause| CheckError::Resource {
node: signature,
cause,
})?;
let mut agrees = true;
let mut ordinal = 0;
while ordinal < prepared.renewed().len() {
work.charge_work(1).map_err(|cause| CheckError::Resource {
node: signature,
cause,
})?;
let reading = &prepared.renewed()[ordinal];
let report = check(xml, reading, provider, work)?;
agrees &= report.agrees();
reports
.try_push(report)
.map_err(|cause| CheckError::Resource {
node: reading.node(),
cause,
})?;
ordinal += 1;
}
access
.query(signature, |_, _, _| Ok(()))
.map_err(CheckError::Access)?;
Ok(PreparedChecks {
prepared,
reports: reports.into_owned(),
agrees,
})
}