1use crate::{Error, ErrorCode, Result};
4use structured_asn1::memory::{OwnedVec, Work};
5use structured_asn1::{Element, Parser, Reader, Span, Tag, universal};
6
7#[derive(Debug, Clone, Copy)]
9pub struct Piece<'a> {
10 bytes: &'a [u8],
11 span: Span,
12}
13
14impl<'a> Piece<'a> {
15 #[must_use]
17 pub fn as_bytes(self) -> &'a [u8] {
18 self.bytes
19 }
20
21 #[must_use]
23 pub fn span(self) -> Span {
24 self.span
25 }
26}
27
28#[derive(Debug)]
29enum Storage<'a> {
30 One([Piece<'a>; 1]),
31 Many(OwnedVec<Piece<'a>>),
32}
33
34#[derive(Debug)]
40pub struct Octets<'a> {
41 parser: &'a Parser,
42 outer_depth: u32,
43 carrier: Span,
44 contents: Span,
45 storage: Storage<'a>,
46 length: usize,
47 field: &'static str,
48}
49
50impl<'a> Octets<'a> {
51 pub fn read_ia5(
57 parent: &Reader<'a>,
58 element: &Element<'a>,
59 field: &'static str,
60 ) -> Result<Self> {
61 parent
62 .charge(1)
63 .map_err(|cause| Error::encoding(cause, field))?;
64 let value = Self::read_tagged(parent, element, universal::IA5_STRING, false, field)?;
65 let execution = parent.execution();
66 for piece in value.pieces() {
67 execution
68 .charge_work(1 + piece.as_bytes().len() as u64)
69 .map_err(|cause| Error::resource(cause, field, piece.span().start))?;
70 if !piece.as_bytes().is_ascii() {
71 return Err(Error::schema(
72 ErrorCode::MalformedValue,
73 field,
74 piece.span().start,
75 ));
76 }
77 }
78 Ok(value)
79 }
80
81 pub fn read(parent: &Reader<'a>, element: &Element<'a>, field: &'static str) -> Result<Self> {
89 Self::read_tagged(parent, element, universal::OCTET_STRING, false, field)
90 }
91
92 pub(crate) fn read_identifier(
97 parent: &Reader<'a>,
98 element: &Element<'a>,
99 field: &'static str,
100 ) -> Result<Self> {
101 Self::read_tagged(parent, element, 0, true, field)
102 }
103
104 fn read_tagged(
105 parent: &Reader<'a>,
106 element: &Element<'a>,
107 outer_number: u32,
108 context: bool,
109 field: &'static str,
110 ) -> Result<Self> {
111 let primitive = if context {
112 Tag::context(false, outer_number)
113 } else {
114 Tag::primitive(outer_number)
115 };
116 let constructed = if context {
117 Tag::context(true, outer_number)
118 } else {
119 Tag::constructed(outer_number)
120 };
121 if element.tag() == primitive {
122 return Ok(Self {
123 parser: parent.parser(),
124 outer_depth: parent.depth(),
125 carrier: element.span(),
126 contents: element.contents_span(),
127 storage: Storage::One([Piece {
128 bytes: element.contents(),
129 span: element.contents_span(),
130 }]),
131 length: element.contents().len(),
132 field,
133 });
134 }
135 if element.tag() != constructed {
136 return Err(Error::schema(
137 ErrorCode::UnexpectedTag,
138 field,
139 element.span().start,
140 ));
141 }
142 if parent.encoding().is_der() {
143 return Err(Error::schema(
144 ErrorCode::UnexpectedTag,
145 field,
146 element.span().start,
147 ));
148 }
149 let execution = parent.execution();
150 let mut pieces = execution.vector();
151 let mut frames = execution.vector();
152 frames
153 .try_push(
154 parent
155 .enter(element)
156 .map_err(|error| Error::encoding(error, field))?,
157 )
158 .map_err(|reason| Error::resource(reason, field, element.span().start))?;
159 let mut length = 0_usize;
160 while let Some(reader) = frames.last_mut() {
161 let Some(child) = reader
162 .next_element()
163 .map_err(|error| Error::encoding(error, field))?
164 else {
165 frames.pop();
166 continue;
167 };
168 if child.tag() == Tag::primitive(universal::OCTET_STRING) {
175 length = length.checked_add(child.contents().len()).ok_or_else(|| {
176 Error::schema(ErrorCode::LengthOverflow, field, child.span().start)
177 })?;
178 pieces
179 .try_push(Piece {
180 bytes: child.contents(),
181 span: child.contents_span(),
182 })
183 .map_err(|reason| Error::resource(reason, field, child.span().start))?;
184 } else if child.tag() == Tag::constructed(universal::OCTET_STRING) {
185 let nested = reader
186 .enter(&child)
187 .map_err(|error| Error::encoding(error, field))?;
188 frames
189 .try_push(nested)
190 .map_err(|reason| Error::resource(reason, field, child.span().start))?;
191 } else {
192 return Err(Error::schema(
193 ErrorCode::UnexpectedTag,
194 field,
195 child.span().start,
196 ));
197 }
198 }
199 Ok(Self {
200 parser: parent.parser(),
201 outer_depth: parent.depth(),
202 carrier: element.span(),
203 contents: element.contents_span(),
204 storage: Storage::Many(pieces.into_owned()),
205 length,
206 field,
207 })
208 }
209
210 #[must_use]
212 pub fn pieces(&self) -> &[Piece<'a>] {
213 match &self.storage {
214 Storage::One(piece) => piece,
215 Storage::Many(pieces) => pieces,
216 }
217 }
218
219 #[must_use]
221 pub fn len(&self) -> usize {
222 self.length
223 }
224
225 #[must_use]
227 pub fn is_empty(&self) -> bool {
228 self.length == 0
229 }
230
231 #[must_use]
233 pub fn span(&self) -> Span {
234 self.carrier
235 }
236
237 pub(crate) fn content_span(&self) -> Span {
238 self.contents
239 }
240
241 pub(crate) fn outer_depth(&self) -> u32 {
242 self.outer_depth
243 }
244
245 pub(crate) fn parser(&self) -> &'a Parser {
246 self.parser
247 }
248
249 #[must_use]
251 pub fn as_one(&self) -> Option<&'a [u8]> {
252 match self.pieces() {
253 [piece] => Some(piece.bytes),
254 _ => None,
255 }
256 }
257
258 pub fn copy_in(
268 &self,
269 parent: &Reader<'_>,
270 field: &'static str,
271 at: u64,
272 ) -> Result<OwnedVec<u8>> {
273 if !core::ptr::eq(self.parser, parent.parser()) {
274 return Err(Error::pkix(structured_pkix::Error::new(
275 structured_pkix::ErrorCode::ForeignReader,
276 field,
277 at,
278 )));
279 }
280 let execution = parent.execution();
281 let refusal = |reason| Error::resource(reason, field, at);
282 execution
283 .charge_work(self.pieces().len() as u64)
284 .map_err(refusal)?;
285 let mut output = execution.vector();
286 output.try_reserve_exact(self.length).map_err(refusal)?;
288 for piece in self.pieces() {
289 output.try_extend_from_slice(piece.bytes).map_err(refusal)?;
290 }
291 Ok(output.into_owned())
292 }
293
294 pub(crate) fn same_value(
295 &self,
296 other: &Octets<'_>,
297 parent: &Reader<'_>,
298 field: &'static str,
299 at: u64,
300 ) -> Result<bool> {
301 let execution = parent.execution();
302 execution
303 .charge_work(1)
304 .map_err(|reason| Error::resource(reason, field, at))?;
305 if self.length != other.length {
306 return Ok(false);
307 }
308 for amount in [self.pieces().len(), other.pieces().len(), self.length] {
309 execution
310 .charge_work(amount as u64)
311 .map_err(|reason| Error::resource(reason, field, at))?;
312 }
313 Ok(self
314 .pieces()
315 .iter()
316 .flat_map(|piece| piece.bytes.iter())
317 .eq(other.pieces().iter().flat_map(|piece| piece.bytes.iter())))
318 }
319}
320
321#[derive(Debug)]
323pub enum SourceError {
324 Processing(Error),
326 Receiver(crate::stream::Refused),
328}
329
330impl crate::stream::Source for &Octets<'_> {
331 type Error = SourceError;
332
333 fn stream<W: Work>(
334 &mut self,
335 receiver: &mut impl crate::stream::Receiver,
336 execution: &W,
337 ) -> core::result::Result<(), Self::Error> {
338 for piece in self.pieces() {
339 execution.charge_work(1).map_err(|reason| {
340 SourceError::Processing(Error::resource(reason, self.field, piece.span.start))
341 })?;
342 receiver.write(piece.bytes).map_err(SourceError::Receiver)?;
343 }
344 Ok(())
345 }
346}