structured_cms/timestamp/
extension.rs1use super::record;
4use crate::{Error, ErrorCode, Octets, Result};
5use structured_asn1::memory::{Execution, OwnedVec, Work};
6use structured_asn1::{Element, Oid, Parser, Reader, Span, Tag};
7use structured_pkix::{error::CallbackError, extension};
8
9const FIELD: &str = "tstInfo.extensions";
10
11#[derive(Debug)]
13pub struct TokenExtension<'a> {
14 kind: Oid<'a>,
15 critical: bool,
16 value: Octets<'a>,
17 span: Span,
18 value_span: Span,
19}
20
21impl<'a> TokenExtension<'a> {
22 fn read<W: Work>(
23 parent: &Reader<'a>,
24 element: &Element<'a>,
25 faults: &mut OwnedVec<Error, W>,
26 ) -> Result<Self> {
27 let fields = extension::open(parent, element, FIELD).map_err(Error::pkix)?;
28 let header = fields.header();
29 if header.default_written()
30 && let Some(span) = header.critical_span()
31 {
32 record(
33 faults,
34 Error::schema(ErrorCode::DefaultWritten, FIELD, span.start),
35 )?;
36 }
37 let reading = fields
38 .read_with(|_, reader, value| {
39 Octets::read(reader, value, FIELD).map(|octets| (octets, value.span()))
40 })
41 .map_err(|error| match error {
42 CallbackError::Processing(source) => Error::pkix(source),
43 CallbackError::Callback(source) => source,
44 })?;
45 if let Some(span) = reading.trailing_span() {
46 record(
47 faults,
48 Error::schema(ErrorCode::TrailingData, FIELD, span.start),
49 )?;
50 }
51 let (value, value_span) = reading.into_value();
52 Ok(Self {
53 kind: header.kind(),
54 critical: header.is_critical(),
55 value,
56 span: header.span(),
57 value_span,
58 })
59 }
60 #[must_use]
62 pub fn kind(&self) -> Oid<'a> {
63 self.kind
64 }
65 #[must_use]
67 pub fn is_critical(&self) -> bool {
68 self.critical
69 }
70 #[must_use]
72 pub fn value(&self) -> &Octets<'a> {
73 &self.value
74 }
75 #[must_use]
77 pub fn span(&self) -> Span {
78 self.span
79 }
80 #[must_use]
82 pub fn value_span(&self) -> Span {
83 self.value_span
84 }
85}
86
87#[derive(Debug)]
90pub struct TokenExtensions<'a> {
91 entries: OwnedVec<TokenExtension<'a>>,
92 faults: OwnedVec<Error>,
93 span: Span,
94 parser: &'a Parser,
95}
96
97#[derive(Debug)]
99pub enum RecognitionError<E> {
100 Processing(Error),
102 Callback {
104 span: Span,
106 source: E,
108 },
109}
110
111impl<'a> TokenExtensions<'a> {
112 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
122 if element.tag() != Tag::context(true, 1) {
123 return Err(Error::schema(
124 ErrorCode::UnexpectedTag,
125 FIELD,
126 element.span().start,
127 ));
128 }
129 let mut inside = parent
130 .enter(element)
131 .map_err(|error| Error::encoding(error, FIELD))?;
132 let execution = parent.execution();
133 let mut entries: OwnedVec<TokenExtension<'a>, _> = execution.vector();
134 let mut faults = execution.vector();
135 while let Some(element) = inside
136 .next_element()
137 .map_err(|error| Error::encoding(error, FIELD))?
138 {
139 let candidate = TokenExtension::read(&inside, &element, &mut faults);
140 let candidate = match candidate {
141 Ok(candidate) => candidate,
142 Err(error) if error.is_terminal() => return Err(error),
143 Err(error) => {
144 record(&mut faults, error)?;
145 continue;
146 }
147 };
148 let at = candidate.span.start;
149 let mut duplicate = false;
150 for earlier in &entries {
151 execution
152 .charge_work(1)
153 .map_err(|reason| Error::resource(reason, FIELD, at))?;
154 if earlier.kind.as_bytes().len() != candidate.kind.as_bytes().len() {
155 continue;
156 }
157 execution
158 .charge_work(candidate.kind.as_bytes().len() as u64)
159 .map_err(|reason| Error::resource(reason, FIELD, at))?;
160 if earlier.kind != candidate.kind {
161 continue;
162 }
163 if earlier.critical != candidate.critical
164 || !earlier
165 .value
166 .same_value(&candidate.value, &inside, FIELD, at)?
167 {
168 return Err(Error::schema(ErrorCode::DuplicateField, FIELD, at));
169 }
170 record(
171 &mut faults,
172 Error::schema(ErrorCode::DuplicateField, FIELD, at),
173 )?;
174 duplicate = true;
175 break;
176 }
177 if !duplicate {
178 entries
179 .try_push(candidate)
180 .map_err(|reason| Error::resource(reason, FIELD, at))?;
181 }
182 }
183 if entries.is_empty() {
184 record(
185 &mut faults,
186 Error::schema(ErrorCode::MalformedValue, FIELD, element.span().start),
187 )?;
188 }
189 Ok(Self {
190 entries: entries.into_owned(),
191 faults: faults.into_owned(),
192 span: element.span(),
193 parser: parent.parser(),
194 })
195 }
196
197 #[must_use]
199 pub fn entries(&self) -> &[TokenExtension<'a>] {
200 &self.entries
201 }
202 #[must_use]
204 pub fn faults(&self) -> &[Error] {
205 &self.faults
206 }
207 #[must_use]
209 pub fn span(&self) -> Span {
210 self.span
211 }
212
213 pub fn unrecognized_critical<E>(
226 &self,
227 parent: &Reader<'_>,
228 mut recognizes: impl FnMut(&TokenExtension<'a>, &Execution<'_>) -> core::result::Result<bool, E>,
229 ) -> core::result::Result<OwnedVec<Oid<'a>>, RecognitionError<E>> {
230 if !core::ptr::eq(self.parser, parent.parser()) {
231 return Err(RecognitionError::Processing(Error::pkix(
232 structured_pkix::Error::new(
233 structured_pkix::ErrorCode::ForeignReader,
234 FIELD,
235 self.span.start,
236 ),
237 )));
238 }
239 let work = parent.execution();
240 let mut unknown = work.vector();
241 for extension in &self.entries {
242 work.charge_work(1).map_err(|reason| {
243 RecognitionError::Processing(Error::resource(reason, FIELD, extension.span.start))
244 })?;
245 if !extension.critical {
246 continue;
247 }
248 if !recognizes(extension, &work).map_err(|source| RecognitionError::Callback {
249 span: extension.span,
250 source,
251 })? {
252 unknown.try_push(extension.kind).map_err(|reason| {
253 RecognitionError::Processing(Error::resource(
254 reason,
255 FIELD,
256 extension.span.start,
257 ))
258 })?;
259 }
260 }
261 Ok(unknown.into_owned())
262 }
263}