Skip to main content

nex_packet/
parse.rs

1//! Structured parse errors for diagnosable packet parsing APIs.
2
3use core::fmt;
4
5/// Structured error returned by `try_from_*` parsing APIs.
6#[derive(Clone, Debug, PartialEq, Eq)]
7#[non_exhaustive]
8pub enum ParseError {
9    /// The input buffer was shorter than the protocol minimum.
10    BufferTooShort {
11        /// Human-readable parse context.
12        context: &'static str,
13        /// Minimum required number of bytes.
14        minimum: usize,
15        /// Actual number of bytes available.
16        actual: usize,
17    },
18    /// A length-like field contained an invalid value.
19    InvalidLength {
20        /// Human-readable parse context.
21        context: &'static str,
22        /// Parsed value that failed validation.
23        value: usize,
24    },
25    /// The packet contains a malformed header field.
26    Malformed {
27        /// Human-readable parse context.
28        context: &'static str,
29    },
30    /// The packet payload was truncated relative to its header lengths.
31    Truncated {
32        /// Human-readable parse context.
33        context: &'static str,
34        /// Expected number of bytes.
35        expected: usize,
36        /// Actual number of bytes available.
37        actual: usize,
38    },
39    /// Parsing failed because a compression loop or excessive indirection was detected.
40    CompressionLoop {
41        /// Human-readable parse context.
42        context: &'static str,
43    },
44    /// Parsing failed because an unsupported or invalid pointer/compression form was encountered.
45    InvalidCompression {
46        /// Human-readable parse context.
47        context: &'static str,
48    },
49    /// A UTF-8 conversion failed while parsing text-like data.
50    InvalidUtf8 {
51        /// Human-readable parse context.
52        context: &'static str,
53    },
54}
55
56impl fmt::Display for ParseError {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        match self {
59            ParseError::BufferTooShort {
60                context,
61                minimum,
62                actual,
63            } => write!(
64                f,
65                "{context}: buffer too short (expected at least {minimum} bytes, got {actual})"
66            ),
67            ParseError::InvalidLength { context, value } => {
68                write!(f, "{context}: invalid length value {value}")
69            }
70            ParseError::Malformed { context } => write!(f, "{context}: malformed packet data"),
71            ParseError::Truncated {
72                context,
73                expected,
74                actual,
75            } => write!(
76                f,
77                "{context}: truncated payload (expected {expected} bytes, got {actual})"
78            ),
79            ParseError::CompressionLoop { context } => {
80                write!(f, "{context}: compression pointer loop detected")
81            }
82            ParseError::InvalidCompression { context } => {
83                write!(f, "{context}: invalid compression pointer")
84            }
85            ParseError::InvalidUtf8 { context } => {
86                write!(f, "{context}: invalid UTF-8 sequence")
87            }
88        }
89    }
90}
91
92impl std::error::Error for ParseError {}