structured_cms/
payload.rs1use 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 execution
120 .charge_work(core::mem::size_of_val(&*self.raw) as u64)
121 .map_err(refusal)?;
122 let provider = self.digests.provider();
123 let digests = self
124 .digests
125 .finish(outputs, execution)
126 .map_err(|error| StreamError::Callback(PayloadError::Digest(error)))?;
127 for state in self.raw {
128 execution.charge_work(1).map_err(refusal)?;
129 let answer = provider
130 .finish_raw(state, execution)
131 .map_err(|error| StreamError::Callback(PayloadError::Callback(error)))?;
132 answers.try_push(answer).map_err(refusal)?;
133 }
134 Ok(Completed {
135 digests,
136 raw: answers.into_owned(),
137 })
138 }
139}
140
141struct PayloadSink<'s, 'a, P: SignatureProvider<'a>>(&'s mut PayloadBatch<'a, P>);
142
143impl<'a, P: SignatureProvider<'a>> Sink for PayloadSink<'_, 'a, P> {
144 type Error = PayloadError<P::Error>;
145
146 fn write<W: Work>(&mut self, bytes: &[u8], execution: &W) -> Result<(), Self::Error> {
147 self.0
148 .digests
149 .feed(bytes, execution)
150 .map_err(PayloadError::Digest)?;
151 let (field, at) = self.0.digests.location();
152 for state in &mut self.0.raw {
153 execution
154 .charge_work(1)
155 .map_err(|reason| PayloadError::Processing(Error::resource(reason, field, at)))?;
156 self.0
157 .digests
158 .provider()
159 .update_raw(state, bytes, execution)
160 .map_err(PayloadError::Callback)?;
161 }
162 Ok(())
163 }
164}