1use crate::Error;
4use crate::Octets;
5use crate::digest::{DigestBatch, DigestError, DigestMemo, DigestOutput};
6use crate::provider::{SignatureAnswer, SignatureProvider};
7use crate::stream::{self, Sink, Source, StreamError};
8use structured_asn1::memory::{OwnedVec, Work};
9use structured_pkix::path::WorkingKey;
10
11pub struct RawRequest<'a, P: SignatureProvider<'a>> {
17 pub identity: P::SignatureIdentity,
19 pub key: WorkingKey<'a>,
21 pub signature: &'a Octets<'a>,
23}
24
25#[derive(Debug)]
27pub enum PayloadError<E> {
28 Processing(Error),
30 Callback(E),
32 Digest(DigestError<E>),
34}
35
36pub type PassError<SE, PE> = StreamError<SE, PayloadError<PE>>;
38
39pub struct PayloadBatch<'a, P: SignatureProvider<'a>> {
44 digests: DigestBatch<'a, P>,
45 raw: OwnedVec<P::RawState>,
46}
47
48pub struct Completed<'a, P: SignatureProvider<'a>> {
50 digests: DigestMemo<'a, P>,
51 raw: OwnedVec<SignatureAnswer>,
52}
53
54impl<'a, P: SignatureProvider<'a>> Completed<'a, P> {
55 #[must_use]
57 pub fn digests(&self) -> &DigestMemo<'a, P> {
58 &self.digests
59 }
60
61 #[must_use]
63 pub fn raw(&self) -> &[SignatureAnswer] {
64 &self.raw
65 }
66}
67
68impl<'a, P: SignatureProvider<'a>> PayloadBatch<'a, P> {
69 pub fn prepare<W: Work>(
75 digests: DigestBatch<'a, P>,
76 requests: OwnedVec<RawRequest<'a, P>>,
77 execution: &W,
78 ) -> Result<Self, PayloadError<P::Error>> {
79 let (field, at) = digests.location();
80 let refusal = |reason| PayloadError::Processing(Error::resource(reason, field, at));
81 let mut raw = execution.vector();
82 raw.try_reserve_exact(requests.len()).map_err(refusal)?;
83 execution
84 .charge_work(core::mem::size_of_val(&*requests) as u64)
85 .map_err(refusal)?;
86 for request in requests {
87 execution.charge_work(1).map_err(refusal)?;
88 let state = digests
89 .provider()
90 .start_raw(&request.identity, request.key, request.signature, execution)
91 .map_err(PayloadError::Callback)?;
92 raw.try_push(state).map_err(refusal)?;
93 }
94 Ok(Self {
95 digests,
96 raw: raw.into_owned(),
97 })
98 }
99
100 pub fn run<S: Source, W: Work>(
106 mut self,
107 source: &mut S,
108 execution: &W,
109 ) -> Result<Completed<'a, P>, PassError<S::Error, P::Error>> {
110 let (field, at) = self.digests.location();
111 let refusal = |reason| StreamError::Processing(Error::resource(reason, field, at));
112 let mut outputs: OwnedVec<DigestOutput<'a, P>, W> = execution.vector();
113 outputs
114 .try_reserve_exact(self.digests.len())
115 .map_err(refusal)?;
116 let mut answers = execution.vector();
117 answers.try_reserve_exact(self.raw.len()).map_err(refusal)?;
118 stream::run(source, &mut PayloadSink(&mut self), execution, field, at)?;
119 self.finish(outputs, answers, execution)
120 }
121
122 pub async fn run_async<S: stream::AsyncSource, W: Work>(
125 mut self,
126 source: &mut S,
127 execution: &W,
128 ) -> Result<Completed<'a, P>, PassError<S::Error, P::Error>> {
129 let (field, at) = self.digests.location();
130 let refusal = |cause| StreamError::Processing(Error::resource(cause, field, at));
131 let mut outputs = execution.vector();
132 outputs
133 .try_reserve_exact(self.digests.len())
134 .map_err(refusal)?;
135 let mut answers = execution.vector();
136 answers.try_reserve_exact(self.raw.len()).map_err(refusal)?;
137 stream::run_async(source, &mut PayloadSink(&mut self), execution, field, at).await?;
138 self.finish(outputs, answers, execution)
139 }
140
141 fn finish<SE, W: Work>(
142 self,
143 outputs: OwnedVec<DigestOutput<'a, P>, W>,
144 mut answers: OwnedVec<SignatureAnswer, W>,
145 execution: &W,
146 ) -> Result<Completed<'a, P>, PassError<SE, P::Error>> {
147 let (field, at) = self.digests.location();
148 let refusal = |cause| StreamError::Processing(Error::resource(cause, field, at));
149 execution
150 .charge_work(core::mem::size_of_val(&*self.raw) as u64)
151 .map_err(refusal)?;
152 let provider = self.digests.provider();
153 let digests = self
154 .digests
155 .finish(outputs, execution)
156 .map_err(|error| StreamError::Callback(PayloadError::Digest(error)))?;
157 for state in self.raw {
158 execution.charge_work(1).map_err(refusal)?;
159 let answer = provider
160 .finish_raw(state, execution)
161 .map_err(|error| StreamError::Callback(PayloadError::Callback(error)))?;
162 answers.try_push(answer).map_err(refusal)?;
163 }
164 Ok(Completed {
165 digests,
166 raw: answers.into_owned(),
167 })
168 }
169}
170
171struct PayloadSink<'s, 'a, P: SignatureProvider<'a>>(&'s mut PayloadBatch<'a, P>);
172
173impl<'a, P: SignatureProvider<'a>> Sink for PayloadSink<'_, 'a, P> {
174 type Error = PayloadError<P::Error>;
175
176 fn write<W: Work>(&mut self, bytes: &[u8], execution: &W) -> Result<(), Self::Error> {
177 self.0
178 .digests
179 .feed(bytes, execution)
180 .map_err(PayloadError::Digest)?;
181 let (field, at) = self.0.digests.location();
182 for state in &mut self.0.raw {
183 execution
184 .charge_work(1)
185 .map_err(|reason| PayloadError::Processing(Error::resource(reason, field, at)))?;
186 self.0
187 .digests
188 .provider()
189 .update_raw(state, bytes, execution)
190 .map_err(PayloadError::Callback)?;
191 }
192 Ok(())
193 }
194}