Skip to main content

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}