synkit_core/
error.rs

1//! Core error types for synkit.
2//!
3//! User-defined error types should implement `From<synkit::Error>` to integrate
4//! with synkit's built-in error handling.
5
6use core::fmt;
7
8/// Core synkit error type.
9///
10/// This enum captures errors that originate from synkit's internal operations.
11/// User-defined parsers should define their own error types and implement
12/// `From<Error>` to convert synkit errors into their domain-specific errors.
13///
14/// # Example
15///
16/// ```ignore
17/// use thiserror::Error;
18///
19/// #[derive(Error, Debug)]
20/// pub enum MyParseError {
21///     #[error("stream not fully consumed: {remaining} tokens remaining")]
22///     StreamNotConsumed { remaining: usize },
23///
24///     #[error("expected {expect}, found {found}")]
25///     Expected { expect: &'static str, found: String },
26///
27///     // ... other variants
28/// }
29///
30/// impl From<synkit::Error> for MyParseError {
31///     fn from(err: synkit::Error) -> Self {
32///         match err {
33///             synkit::Error::StreamNotConsumed { remaining } => {
34///                 MyParseError::StreamNotConsumed { remaining }
35///             }
36///         }
37///     }
38/// }
39/// ```
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub enum Error {
42    /// The token stream was not fully consumed after parsing.
43    ///
44    /// This error is returned by `ensure_consumed()` when there are
45    /// remaining tokens (excluding whitespace) in the stream.
46    StreamNotConsumed {
47        /// Number of remaining tokens (excluding whitespace).
48        remaining: usize,
49    },
50
51    /// Recursion limit exceeded during parsing.
52    ///
53    /// This error is returned when nested parsing exceeds the configured
54    /// maximum recursion depth. This limit exists to prevent stack overflow
55    /// from deeply nested malicious input.
56    ///
57    /// # Example
58    ///
59    /// Input like `[[[[[[...]]]]]]` with thousands of nesting levels would
60    /// trigger this error with the default limit of 128.
61    RecursionLimitExceeded {
62        /// Current recursion depth when limit was exceeded.
63        depth: usize,
64        /// Maximum allowed recursion depth.
65        limit: usize,
66    },
67
68    /// Token limit exceeded during parsing.
69    ///
70    /// This error is returned when the parser has consumed more tokens than
71    /// the configured maximum. This limit exists to prevent resource exhaustion
72    /// from extremely long inputs.
73    TokenLimitExceeded {
74        /// Number of tokens consumed when limit was exceeded.
75        consumed: usize,
76        /// Maximum allowed token count.
77        limit: usize,
78    },
79}
80
81impl fmt::Display for Error {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        match self {
84            Error::StreamNotConsumed { remaining } => {
85                write!(
86                    f,
87                    "stream not fully consumed: {} tokens remaining",
88                    remaining
89                )
90            }
91            Error::RecursionLimitExceeded { depth, limit } => {
92                write!(
93                    f,
94                    "recursion limit exceeded: depth {} > limit {}",
95                    depth, limit
96                )
97            }
98            Error::TokenLimitExceeded { consumed, limit } => {
99                write!(
100                    f,
101                    "token limit exceeded: consumed {} > limit {}",
102                    consumed, limit
103                )
104            }
105        }
106    }
107}
108
109#[cfg(feature = "std")]
110impl std::error::Error for Error {}