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(parent: &Reader<'a>, element: &Element<'a>, field: &'static str) -> Result<Self> {
59 Self::read_tagged(parent, element, universal::OCTET_STRING, false, field)
60 }
61
62 pub(crate) fn read_identifier(
67 parent: &Reader<'a>,
68 element: &Element<'a>,
69 field: &'static str,
70 ) -> Result<Self> {
71 Self::read_tagged(parent, element, 0, true, field)
72 }
73
74 fn read_tagged(
75 parent: &Reader<'a>,
76 element: &Element<'a>,
77 number: u32,
78 context: bool,
79 field: &'static str,
80 ) -> Result<Self> {
81 let primitive = if context {
82 Tag::context(false, number)
83 } else {
84 Tag::primitive(number)
85 };
86 let constructed = if context {
87 Tag::context(true, number)
88 } else {
89 Tag::constructed(number)
90 };
91 if element.tag() == primitive {
92 return Ok(Self {
93 parser: parent.parser(),
94 outer_depth: parent.depth(),
95 carrier: element.span(),
96 contents: element.contents_span(),
97 storage: Storage::One([Piece {
98 bytes: element.contents(),
99 span: element.contents_span(),
100 }]),
101 length: element.contents().len(),
102 field,
103 });
104 }
105 if element.tag() != constructed {
106 return Err(Error::schema(
107 ErrorCode::UnexpectedTag,
108 field,
109 element.span().start,
110 ));
111 }
112 if parent.encoding().is_der() {
113 return Err(Error::schema(
114 ErrorCode::UnexpectedTag,
115 field,
116 element.span().start,
117 ));
118 }
119 let execution = parent.execution();
120 let mut pieces = execution.vector();
121 let mut frames = execution.vector();
122 frames
123 .try_push(
124 parent
125 .enter(element)
126 .map_err(|error| Error::encoding(error, field))?,
127 )
128 .map_err(|reason| Error::resource(reason, field, element.span().start))?;
129 let mut length = 0_usize;
130 while let Some(reader) = frames.last_mut() {
131 let Some(child) = reader
132 .next_element()
133 .map_err(|error| Error::encoding(error, field))?
134 else {
135 frames.pop();
136 continue;
137 };
138 if child.tag() == Tag::primitive(universal::OCTET_STRING) {
139 length = length.checked_add(child.contents().len()).ok_or_else(|| {
140 Error::schema(ErrorCode::LengthOverflow, field, child.span().start)
141 })?;
142 pieces
143 .try_push(Piece {
144 bytes: child.contents(),
145 span: child.contents_span(),
146 })
147 .map_err(|reason| Error::resource(reason, field, child.span().start))?;
148 } else if child.tag() == Tag::constructed(universal::OCTET_STRING) {
149 let nested = reader
150 .enter(&child)
151 .map_err(|error| Error::encoding(error, field))?;
152 frames
153 .try_push(nested)
154 .map_err(|reason| Error::resource(reason, field, child.span().start))?;
155 } else {
156 return Err(Error::schema(
157 ErrorCode::UnexpectedTag,
158 field,
159 child.span().start,
160 ));
161 }
162 }
163 Ok(Self {
164 parser: parent.parser(),
165 outer_depth: parent.depth(),
166 carrier: element.span(),
167 contents: element.contents_span(),
168 storage: Storage::Many(pieces.into_owned()),
169 length,
170 field,
171 })
172 }
173
174 #[must_use]
176 pub fn pieces(&self) -> &[Piece<'a>] {
177 match &self.storage {
178 Storage::One(piece) => piece,
179 Storage::Many(pieces) => pieces,
180 }
181 }
182
183 #[must_use]
185 pub fn len(&self) -> usize {
186 self.length
187 }
188
189 #[must_use]
191 pub fn is_empty(&self) -> bool {
192 self.length == 0
193 }
194
195 #[must_use]
197 pub fn span(&self) -> Span {
198 self.carrier
199 }
200
201 pub(crate) fn content_span(&self) -> Span {
202 self.contents
203 }
204
205 pub(crate) fn outer_depth(&self) -> u32 {
206 self.outer_depth
207 }
208
209 pub(crate) fn parser(&self) -> &'a Parser {
210 self.parser
211 }
212
213 #[must_use]
215 pub fn as_one(&self) -> Option<&'a [u8]> {
216 match self.pieces() {
217 [piece] => Some(piece.bytes),
218 _ => None,
219 }
220 }
221
222 pub fn copy_in(
232 &self,
233 parent: &Reader<'_>,
234 field: &'static str,
235 at: u64,
236 ) -> Result<OwnedVec<u8>> {
237 if !core::ptr::eq(self.parser, parent.parser()) {
238 return Err(Error::pkix(structured_pkix::Error::new(
239 structured_pkix::ErrorCode::ForeignReader,
240 field,
241 at,
242 )));
243 }
244 let execution = parent.execution();
245 let refusal = |reason| Error::resource(reason, field, at);
246 execution
247 .charge_work(self.pieces().len() as u64)
248 .map_err(refusal)?;
249 let mut output = execution.vector();
250 output.try_reserve_exact(self.length).map_err(refusal)?;
252 for piece in self.pieces() {
253 output.try_extend_from_slice(piece.bytes).map_err(refusal)?;
254 }
255 Ok(output.into_owned())
256 }
257
258 pub(crate) fn same_value(
259 &self,
260 other: &Octets<'_>,
261 parent: &Reader<'_>,
262 field: &'static str,
263 at: u64,
264 ) -> Result<bool> {
265 let execution = parent.execution();
266 execution
267 .charge_work(1)
268 .map_err(|reason| Error::resource(reason, field, at))?;
269 if self.length != other.length {
270 return Ok(false);
271 }
272 for amount in [self.pieces().len(), other.pieces().len(), self.length] {
273 execution
274 .charge_work(amount as u64)
275 .map_err(|reason| Error::resource(reason, field, at))?;
276 }
277 Ok(self
278 .pieces()
279 .iter()
280 .flat_map(|piece| piece.bytes.iter())
281 .eq(other.pieces().iter().flat_map(|piece| piece.bytes.iter())))
282 }
283}
284
285#[derive(Debug)]
287pub enum SourceError {
288 Processing(Error),
290 Receiver(crate::stream::Refused),
292}
293
294impl crate::stream::Source for &Octets<'_> {
295 type Error = SourceError;
296
297 fn stream<W: Work>(
298 &mut self,
299 receiver: &mut impl crate::stream::Receiver,
300 execution: &W,
301 ) -> core::result::Result<(), Self::Error> {
302 for piece in self.pieces() {
303 execution.charge_work(1).map_err(|reason| {
304 SourceError::Processing(Error::resource(reason, self.field, piece.span.start))
305 })?;
306 receiver.write(piece.bytes).map_err(SourceError::Receiver)?;
307 }
308 Ok(())
309 }
310}