cadmpeg_core/decode/probe.rs
1// SPDX-License-Identifier: Apache-2.0
2//! Committed-parse failure types.
3//!
4//! Reverse-engineered decoding is speculative: try an interpretation, and a
5//! miss means try the next. Leaf reads stay `Option` so the probe path builds
6//! no errors and makes no allocations. The commit transition is realized by the
7//! `req_*` mirror API on [`View`](super::View): a committed required read
8//! returns `Result<T, ParseError>`, so once an interpretation is accepted a
9//! failure is classified and cannot be turned back into "try the next
10//! candidate".
11
12use super::error::SourceLocation;
13use crate::CodecError;
14
15/// A classified failure after commitment, with its location.
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ParseError {
18 /// Where the failure occurred.
19 pub location: SourceLocation,
20 /// What kind of failure it was.
21 pub kind: ParseErrorKind,
22 /// The committed operation in progress.
23 pub operation: &'static str,
24}
25
26impl ParseError {
27 /// Replaces the operation label as the error crosses a parsing boundary.
28 #[must_use]
29 pub fn during(mut self, operation: &'static str) -> Self {
30 self.operation = operation;
31 self
32 }
33}
34
35impl From<ParseError> for CodecError {
36 fn from(error: ParseError) -> Self {
37 match error.kind {
38 ParseErrorKind::UnexpectedEof { .. } => {
39 CodecError::truncated(error.location, error.operation)
40 }
41 ParseErrorKind::InvalidValue => CodecError::malformed(format_args!(
42 "invalid value during {} at space {} offset {}",
43 error.operation,
44 error.location.space.index(),
45 error.location.offset
46 )),
47 ParseErrorKind::InvalidFraming => CodecError::malformed(format_args!(
48 "invalid framing during {} at space {} offset {}",
49 error.operation,
50 error.location.space.index(),
51 error.location.offset
52 )),
53 }
54 }
55}
56
57/// The classified reason a committed parse failed.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum ParseErrorKind {
60 /// A required read extended past the view's end.
61 UnexpectedEof {
62 /// How many bytes the read needed.
63 needed: u64,
64 },
65 /// A value inside the view was inconsistent.
66 InvalidValue,
67 /// The framing inside the view was inconsistent.
68 InvalidFraming,
69}