1use crate::arena::{Kind, NodeId};
4use crate::document::{Document, Reading};
5use crate::error::{Error, ErrorKind, ReadFailure, Syntax};
6use crate::model::{admit, get, named, unsigned};
7use crate::range::{RangeReader, RangeSource};
8use crate::source::{Location, Source};
9use structured_asn1::{
10 Span,
11 memory::{Memory, OwnedVec, Work},
12};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum SubFilter {
17 CadesDetached,
19 Rfc3161,
21 Pkcs7Detached,
23 Other,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum Coverage {
31 Revision(usize),
33 Partial,
35}
36
37pub(crate) struct Entry {
38 pub(crate) owner: usize,
39 pub(crate) node: NodeId,
40 pub(crate) contents: NodeId,
41 pub(crate) ranges: OwnedVec<Span, Memory>,
42 pub(crate) sub_filter: Option<SubFilter>,
43 pub(crate) coverage: Coverage,
44 pub(crate) timestamp: bool,
45 pub(crate) definition: (u64, u16),
46}
47
48pub struct Failure {
51 pub location: Location,
53 pub cause: Error,
55 pub definition: (u64, u16),
57 pub revision: usize,
59 pub document_timestamp: bool,
61 pub contents: Option<Location>,
63}
64
65pub(crate) enum Position {
66 Readable(usize),
67 Unreadable(usize),
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum DefinitionKind {
73 Object,
75 ObjectStream,
77 CrossReference,
79}
80#[derive(Debug, Clone, Copy)]
82pub struct Definition {
83 pub identity: (u64, u16),
85 pub location: Location,
87 pub encoded: Location,
89 pub revision: usize,
91 pub kind: DefinitionKind,
93}
94
95pub enum Candidate<'a, 's, D, G> {
97 Readable(Signature<'a, 's, D, G>),
99 Unreadable(&'a Failure),
101}
102
103pub struct Catalogue<'s, D, G> {
107 pub(crate) readings: OwnedVec<Reading<'s, D, G>, Memory>,
108 pub(crate) entries: OwnedVec<Entry, Memory>,
109 pub(crate) failures: OwnedVec<Failure, Memory>,
110 pub(crate) order: OwnedVec<Position, Memory>,
111 pub(crate) definitions: OwnedVec<Definition, Memory>,
112}
113
114impl<'s, D: Copy + Eq, G: Copy + Eq> Catalogue<'s, D, G> {
115 #[must_use]
117 pub fn len(&self) -> usize {
118 self.entries.len()
119 }
120
121 #[must_use]
123 pub fn is_empty(&self) -> bool {
124 self.entries.is_empty()
125 }
126
127 #[must_use]
129 pub fn get(&self, index: usize) -> Option<Signature<'_, 's, D, G>> {
130 self.entries.get(index).map(|entry| Signature {
131 catalogue: self,
132 entry,
133 })
134 }
135 #[must_use]
137 pub fn candidates(&self) -> usize {
138 self.order.len()
139 }
140 #[must_use]
145 pub fn candidate(&self, index: usize) -> Option<Candidate<'_, 's, D, G>> {
146 self.order.get(index).map(|position| match position {
147 Position::Readable(index) => {
148 Candidate::Readable(self.get(*index).expect("original readable ordinal"))
149 }
150 Position::Unreadable(index) => Candidate::Unreadable(&self.failures[*index]),
151 })
152 }
153 #[must_use]
155 pub fn failures(&self) -> &[Failure] {
156 &self.failures
157 }
158 #[must_use]
160 pub fn definitions(&self) -> &[Definition] {
161 &self.definitions
162 }
163}
164
165#[derive(Clone, Copy)]
168pub struct Signature<'a, 's, D, G> {
169 catalogue: &'a Catalogue<'s, D, G>,
170 entry: &'a Entry,
171}
172
173impl<'a, 's, D: Copy + Eq, G: Copy + Eq> Signature<'a, 's, D, G> {
174 #[must_use]
176 pub fn location(self) -> Location {
177 self.owner().value.arena.nodes[self.entry.node.0].location
178 }
179
180 #[must_use]
182 pub fn contents(self) -> Location {
183 self.owner().value.arena.nodes[self.entry.contents.0].location
184 }
185
186 #[must_use]
189 pub fn ranges(self) -> &'a [Span] {
190 &self.entry.ranges
191 }
192
193 #[must_use]
195 pub fn coverage(self) -> Coverage {
196 self.entry.coverage
197 }
198
199 #[must_use]
201 pub fn sub_filter(self) -> Option<SubFilter> {
202 self.entry.sub_filter
203 }
204
205 #[must_use]
207 pub fn is_document_timestamp(self) -> bool {
208 self.entry.timestamp
209 }
210
211 #[must_use]
213 pub fn definition(self) -> (u64, u16) {
214 self.entry.definition
215 }
216
217 #[must_use]
219 pub fn defined_revision(self) -> usize {
220 self.owner().revision
221 }
222
223 pub(crate) fn catalogue(self) -> &'a Catalogue<'s, D, G> {
224 self.catalogue
225 }
226
227 pub(crate) fn owner(&self) -> &'a Reading<'s, D, G> {
228 &self.catalogue.readings[self.entry.owner]
229 }
230
231 pub(crate) fn node(&self) -> NodeId {
232 self.entry.node
233 }
234}
235
236pub struct Covered<'q, S: RangeSource> {
239 reader: RangeReader<'q, S>,
240 ranges: &'q [Span],
241}
242
243#[derive(Debug)]
245pub enum CoveredError<E> {
246 Input(crate::range::InputError<E>),
248 Receiver(structured_cms::stream::Refused),
250}
251
252impl<S: RangeSource> structured_cms::stream::AsyncSource for Covered<'_, S> {
253 type Error = CoveredError<S::Error>;
254
255 async fn stream<'q, W: Work + 'q, R: structured_cms::stream::Receiver + 'q>(
256 &'q mut self,
257 receiver: &'q mut R,
258 execution: &'q W,
259 ) -> Result<(), Self::Error> {
260 for span in self.ranges {
261 execution.charge_work(1).map_err(|cause| {
262 CoveredError::Input(crate::range::InputError::Resource {
263 location: self.reader.location(span.start, span.length),
264 cause,
265 })
266 })?;
267 let mut at = span.start;
268 let end = span.start + span.length;
269 while at < end {
270 let bytes = self
271 .reader
272 .chunk_at(at, end)
273 .await
274 .map_err(CoveredError::Input)?;
275 receiver.write(bytes).map_err(CoveredError::Receiver)?;
276 at += bytes.len() as u64;
277 }
278 }
279 self.reader
280 .check(self.reader.location(0, self.reader.stamp().length))
281 .map_err(CoveredError::Input)
282 }
283}
284
285pub(crate) fn inspect<S: RangeSource, W: Work>(
286 document: &Document<'_, S>,
287 reading: &Reading<'_, S::Document, S::Generation>,
288 owner: usize,
289 entries: &mut OwnedVec<Entry, W>,
290 failures: &mut OwnedVec<Failure, W>,
291 order: &mut OwnedVec<Position, W>,
292 work: &impl Work,
293) -> crate::Result<()> {
294 inspect_part(
295 document,
296 reading,
297 owner,
298 0..reading.value.arena.nodes.len(),
299 (reading.number, reading.generation),
300 Inspection {
301 entries,
302 failures,
303 order,
304 },
305 work,
306 )
307}
308
309struct Header {
310 byte_range: Option<NodeId>,
311 contents: Option<NodeId>,
312 timestamp: bool,
313 signature: bool,
314 sub_filter: Option<SubFilter>,
315}
316
317fn header(
318 arena: &crate::arena::Arena<impl Work>,
319 node_id: NodeId,
320 work: &impl Work,
321) -> crate::Result<Header> {
322 let byte_range = get(arena, node_id, b"ByteRange", work)?;
323 let contents = get(arena, node_id, b"Contents", work)?;
324 let type_value = get(arena, node_id, b"Type", work)?;
325 let timestamp = type_value
326 .map(|node| named(arena, node, b"DocTimeStamp", work))
327 .transpose()?
328 .unwrap_or(false);
329 let signature = type_value
330 .map(|node| named(arena, node, b"Sig", work))
331 .transpose()?
332 .unwrap_or(false);
333 let sub_filter = if let Some(sub) = get(arena, node_id, b"SubFilter", work)? {
334 Some(if named(arena, sub, b"ETSI.CAdES.detached", work)? {
335 SubFilter::CadesDetached
336 } else if named(arena, sub, b"ETSI.RFC3161", work)? {
337 SubFilter::Rfc3161
338 } else if named(arena, sub, b"adbe.pkcs7.detached", work)? {
339 SubFilter::Pkcs7Detached
340 } else {
341 SubFilter::Other
342 })
343 } else {
344 None
345 };
346 Ok(Header {
347 byte_range,
348 contents,
349 timestamp,
350 signature,
351 sub_filter,
352 })
353}
354
355pub(crate) struct Inspection<'a, W: Work> {
356 pub(crate) entries: &'a mut OwnedVec<Entry, W>,
357 pub(crate) failures: &'a mut OwnedVec<Failure, W>,
358 pub(crate) order: &'a mut OwnedVec<Position, W>,
359}
360
361pub(crate) fn inspect_part<S: RangeSource, W: Work>(
362 document: &Document<'_, S>,
363 reading: &Reading<'_, S::Document, S::Generation>,
364 owner: usize,
365 nodes: core::ops::Range<usize>,
366 definition: (u64, u16),
367 output: Inspection<'_, W>,
368 work: &impl Work,
369) -> crate::Result<()> {
370 let Inspection {
371 entries,
372 failures,
373 order,
374 } = output;
375 let arena = &reading.value.arena;
376 for (index, node) in arena.nodes[nodes.clone()].iter().enumerate() {
377 admit(work, node.location, 1)?;
378 if !matches!(node.kind, Kind::Dictionary(_, _)) {
379 continue;
380 }
381 let node_id = NodeId(nodes.start + index);
382 let Header {
383 byte_range,
384 contents,
385 timestamp,
386 signature,
387 sub_filter,
388 } = header(arena, node_id, work)?;
389 if byte_range.is_none()
390 && !timestamp
391 && !signature
392 && sub_filter != Some(SubFilter::Rfc3161)
393 {
394 continue;
395 }
396 let read = || -> crate::Result<Entry> {
397 let byte_range = byte_range.ok_or(Error {
398 kind: ErrorKind::Syntax(Syntax::Dictionary),
399 location: node.location,
400 })?;
401 let contents = contents.ok_or(Error {
402 kind: ErrorKind::Syntax(Syntax::Dictionary),
403 location: node.location,
404 })?;
405 if !matches!(arena.nodes[contents.0].kind, Kind::String(_)) {
406 return Err(Error {
407 kind: ErrorKind::Syntax(Syntax::String),
408 location: arena.nodes[contents.0].location,
409 });
410 }
411 let original = arena.nodes[contents.0].location;
412 let (ranges, coverage) =
413 parsed_ranges(document, arena, byte_range, original, node.location, work)?;
414 Ok(Entry {
415 owner,
416 node: node_id,
417 contents,
418 ranges,
419 sub_filter,
420 coverage,
421 timestamp,
422 definition,
423 })
424 };
425 let position = match read() {
426 Ok(entry) => {
427 let ordinal = entries.len();
428 entries.try_push(entry).map_err(|cause| Error {
429 kind: ErrorKind::Resource(cause),
430 location: node.location,
431 })?;
432 Position::Readable(ordinal)
433 }
434 Err(cause)
435 if matches!(
436 cause.kind,
437 ErrorKind::Resource(_) | ErrorKind::Limit(_) | ErrorKind::Foreign
438 ) =>
439 {
440 return Err(cause);
441 }
442 Err(cause) => {
443 let ordinal = failures.len();
444 failures
445 .try_push(Failure {
446 location: node.location,
447 cause,
448 definition,
449 revision: reading.revision,
450 document_timestamp: timestamp || sub_filter == Some(SubFilter::Rfc3161),
451 contents: contents.map(|node| arena.nodes[node.0].location),
452 })
453 .map_err(|cause| Error {
454 kind: ErrorKind::Resource(cause),
455 location: node.location,
456 })?;
457 Position::Unreadable(ordinal)
458 }
459 };
460 order.try_push(position).map_err(|cause| Error {
461 kind: ErrorKind::Resource(cause),
462 location: node.location,
463 })?;
464 }
465 Ok(())
466}
467
468fn parsed_ranges<S: RangeSource, W: Work>(
469 document: &Document<'_, S>,
470 arena: &crate::arena::Arena<impl Work>,
471 byte_range: NodeId,
472 original: Location,
473 location: Location,
474 work: &W,
475) -> crate::Result<(OwnedVec<Span>, Coverage)> {
476 let Kind::Array(children) = arena.nodes[byte_range.0].kind else {
477 return Err(Error {
478 kind: ErrorKind::Syntax(Syntax::Number),
479 location: arena.nodes[byte_range.0].location,
480 });
481 };
482 if children.length == 0 || children.length % 2 != 0 {
483 return Err(Error {
484 kind: ErrorKind::Syntax(Syntax::Number),
485 location: arena.nodes[byte_range.0].location,
486 });
487 }
488 let mut next = children.first;
489 let mut ranges = work.vector();
490 let mut previous_end = 0;
491 while let Some(start_link) = next {
492 admit(work, location, 2)?;
493 let first = arena.links[start_link];
494 let second = arena.links[first.next.expect("even ByteRange array")];
495 next = second.next;
496 let start = unsigned(arena, first.value, work)?;
497 let length = unsigned(arena, second.value, work)?;
498 let end = start.checked_add(length).ok_or(Error {
499 kind: ErrorKind::Syntax(Syntax::Number),
500 location,
501 })?;
502 if start < previous_end || end > document.stamp.length {
503 return Err(Error {
504 kind: ErrorKind::Syntax(Syntax::Number),
505 location: arena.nodes[first.value.0].location,
506 });
507 }
508 ranges
509 .try_push(Span { start, length })
510 .map_err(|cause| Error {
511 kind: ErrorKind::Resource(cause),
512 location,
513 })?;
514 previous_end = end;
515 }
516 let mut coverage = Coverage::Partial;
517 if original.source() == Source::File
518 && ranges.len() == 2
519 && ranges[0].start == 0
520 && ranges[0].length == original.span().start
521 && ranges[1].start == original.end()
522 {
523 for revision in 0..document.revisions() {
524 admit(work, location, 1)?;
525 if document.revision(revision).expect("bounded revision").end == previous_end {
526 coverage = Coverage::Revision(revision);
527 break;
528 }
529 }
530 }
531 Ok((ranges.into_owned(), coverage))
532}
533
534impl<'s, S: RangeSource> Document<'s, S> {
535 pub fn covered<'q, W: Work>(
538 &'q self,
539 signature: Signature<'q, 's, S::Document, S::Generation>,
540 operation: &'q W,
541 ) -> Result<Covered<'q, S>, ReadFailure<S::Error>> {
542 let owner = signature.owner();
543 if !core::ptr::eq(owner.value.session, self.session) || owner.value.stamp != self.stamp {
544 return Err(Error {
545 kind: ErrorKind::Foreign,
546 location: signature.location(),
547 }
548 .into());
549 }
550 let reader = RangeReader::new(self.source, self.session, operation)?;
551 if reader.stamp() != self.stamp {
552 return Err(crate::range::InputError::Changed {
553 location: signature.location(),
554 }
555 .into());
556 }
557 Ok(Covered {
558 reader,
559 ranges: &signature.entry.ranges,
560 })
561 }
562 pub async fn contents<W: Work>(
566 &self,
567 signature: Signature<'_, 's, S::Document, S::Generation>,
568 operation: &W,
569 ) -> Result<OwnedVec<u8, Memory>, ReadFailure<S::Error>> {
570 let owner = signature.owner();
571 self.string(owner, signature.entry.contents, usize::MAX, operation)
572 .await
573 }
574}