1use crate::{
4 content::Content,
5 error::Error as ArchiveError,
6 zip::{MemberId, ReadFailure},
7};
8use structured_asn1::{Reader, memory::Execution, range::RangeSource};
9use structured_cms::{
10 provider::SignatureProvider,
11 timestamp::{CheckContext, CheckedTimestamp, Token, TokenExtension},
12};
13
14pub enum Context<'c, 'a, 'r> {
17 Live(&'c CheckContext<'a, 'r>),
19 Historical(&'c CheckContext<'a, 'r>),
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum InputKind {
27 Data,
29 Archive,
31}
32
33#[derive(Debug)]
35pub enum Error<SE, PE, RE, D, G> {
36 Archive(ArchiveError<SE>),
38 Payload(ReadFailure<SE, D, G>),
40 Check(structured_cms::timestamp::CheckError<ReadFailure<SE, D, G>, PE, RE>),
42}
43
44pub struct Checked<'a, D, G> {
47 token: MemberId<D, G>,
48 input: MemberId<D, G>,
49 inner: CheckedTimestamp<'a>,
50}
51
52impl<'a, D: Copy, G: Copy> Checked<'a, D, G> {
53 #[must_use]
55 pub fn token(&self) -> MemberId<D, G> {
56 self.token
57 }
58 #[must_use]
60 pub fn input(&self) -> MemberId<D, G> {
61 self.input
62 }
63 #[must_use]
65 pub fn common(&self) -> &CheckedTimestamp<'a> {
66 &self.inner
67 }
68 #[must_use]
70 pub fn into_common(self) -> CheckedTimestamp<'a> {
71 self.inner
72 }
73}
74
75impl<'v, 's, S: RangeSource> Content<'v, 's, S> {
76 #[expect(
80 clippy::result_large_err,
81 reason = "retain original timestamp diagnostic maps on refusal without a secondary allocation"
82 )]
83 pub async fn check_timestamp<'a, P, PE, RE>(
84 &'a self,
85 token: &'a Token<'a>,
86 parent: &Reader<'a>,
87 provider: &'a P,
88 context: Context<'_, 'a, '_>,
89 input: &impl crate::payload::Payload<'v, 's, S>,
90 recognizes: impl FnMut(&TokenExtension<'_>, &Execution<'_>) -> Result<bool, RE>,
91 ) -> Result<
92 Checked<'a, S::Document, S::Generation>,
93 Error<S::Error, PE, RE, S::Document, S::Generation>,
94 >
95 where
96 P: for<'scope> SignatureProvider<'scope, Error = PE>,
97 {
98 let execution = parent.execution();
99 self.require(token.message(), parent, &execution)
100 .map_err(Error::Archive)?;
101 if !core::ptr::eq(self.member().archive(), input.member().archive()) {
102 return Err(Error::Archive(ArchiveError::Foreign {
103 range: self.enclosure(),
104 }));
105 }
106 let mut source = input.source(&execution).map_err(Error::Payload)?;
107 let checked = match context {
108 Context::Live(context) => {
109 token
110 .check_async(provider, parent, context, &mut source, recognizes)
111 .await
112 }
113 Context::Historical(context) => {
114 token
115 .check_historical_async(provider, parent, context, &mut source, recognizes)
116 .await
117 }
118 }
119 .map_err(Error::Check)?;
120 self.member()
121 .archive()
122 .admit(&execution, self.enclosure())
123 .map_err(Error::Archive)?;
124 Ok(Checked {
125 token: self.member().id(),
126 input: input.member().id(),
127 inner: checked,
128 })
129 }
130}