qbase/frame/
error.rs

1use nom::error::ErrorKind as NomErrorKind;
2use thiserror::Error;
3
4use super::FrameType;
5use crate::{
6    error::{ErrorKind as QuicErrorKind, QuicError},
7    packet::r#type::Type,
8    varint::VarInt,
9};
10
11/// Parse errors when decoding QUIC frames.
12#[derive(Debug, Clone, Eq, PartialEq, Error)]
13pub enum Error {
14    #[error("A packet containing no frames")]
15    NoFrames,
16    #[error("Incomplete frame type: {0}")]
17    IncompleteType(String),
18    #[error("Invalid frame type from {0}")]
19    InvalidType(VarInt),
20    #[error("Wrong frame type {0:?}")]
21    WrongType(FrameType, Type),
22    #[error("Incomplete frame {0:?}: {1}")]
23    IncompleteFrame(FrameType, String),
24    #[error("Error occurred when parsing frame {0:?}: {1}")]
25    ParseError(FrameType, String),
26}
27
28impl From<Error> for QuicError {
29    fn from(e: Error) -> Self {
30        match e {
31            // An endpoint MUST treat receipt of a packet containing no frames as a connection error of type PROTOCOL_VIOLATION.
32            Error::NoFrames => {
33                Self::with_default_fty(QuicErrorKind::ProtocolViolation, e.to_string())
34            }
35            Error::IncompleteType(_) => {
36                Self::with_default_fty(QuicErrorKind::FrameEncoding, e.to_string())
37            }
38            Error::InvalidType(_) => {
39                Self::with_default_fty(QuicErrorKind::FrameEncoding, e.to_string())
40            }
41            Error::WrongType(fty, _) => {
42                Self::new(QuicErrorKind::FrameEncoding, fty.into(), e.to_string())
43            }
44            Error::IncompleteFrame(fty, _) => {
45                Self::new(QuicErrorKind::FrameEncoding, fty.into(), e.to_string())
46            }
47            Error::ParseError(fty, _) => {
48                Self::new(QuicErrorKind::FrameEncoding, fty.into(), e.to_string())
49            }
50        }
51    }
52}
53
54impl From<nom::Err<Error>> for Error {
55    fn from(error: nom::Err<Error>) -> Self {
56        match error {
57            nom::Err::Incomplete(_needed) => {
58                unreachable!("Because the parsing of QUIC packets and frames is not stream-based.")
59            }
60            nom::Err::Error(err) | nom::Err::Failure(err) => err,
61        }
62    }
63}
64
65impl nom::error::ParseError<&[u8]> for Error {
66    fn from_error_kind(_input: &[u8], _kind: NomErrorKind) -> Self {
67        debug_assert_eq!(_kind, NomErrorKind::ManyTill);
68        unreachable!("QUIC frame parser must always consume")
69    }
70
71    fn append(_input: &[u8], _kind: NomErrorKind, source: Self) -> Self {
72        // 在解析帧时遇到了source错误,many_till期望通过ManyTill的错误类型告知
73        // 这里,源错误更有意义,所以直接返回源错误
74        debug_assert_eq!(_kind, NomErrorKind::ManyTill);
75        source
76    }
77}
78
79// TODO: conver DecodingError to quic error
80
81#[cfg(test)]
82mod tests {
83    use nom::error::ParseError;
84
85    use super::*;
86    use crate::packet::r#type::{
87        Type,
88        long::{Type::V1, Ver1},
89    };
90
91    #[test]
92    fn test_error_conversion_to_transport_error() {
93        let cases = vec![
94            (Error::NoFrames, QuicErrorKind::ProtocolViolation),
95            (
96                Error::IncompleteType("test".to_string()),
97                QuicErrorKind::FrameEncoding,
98            ),
99            (
100                Error::InvalidType(VarInt::from_u32(0x1f)),
101                QuicErrorKind::FrameEncoding,
102            ),
103            (
104                Error::WrongType(FrameType::Ping, Type::Long(V1(Ver1::INITIAL))),
105                QuicErrorKind::FrameEncoding,
106            ),
107            (
108                Error::IncompleteFrame(FrameType::Ping, "incomplete".to_string()),
109                QuicErrorKind::FrameEncoding,
110            ),
111            (
112                Error::ParseError(FrameType::Ping, "parse error".to_string()),
113                QuicErrorKind::FrameEncoding,
114            ),
115        ];
116
117        for (error, expected_kind) in cases {
118            let quic_error: QuicError = error.into();
119            assert_eq!(quic_error.kind(), expected_kind);
120        }
121    }
122
123    #[test]
124    fn test_nom_error_conversion() {
125        let error = Error::NoFrames;
126        let nom_error = nom::Err::Error(error.clone());
127        let converted: Error = nom_error.into();
128        assert_eq!(converted, error);
129
130        let nom_failure = nom::Err::Failure(error.clone());
131        let converted: Error = nom_failure.into();
132        assert_eq!(converted, error);
133    }
134
135    #[test]
136    fn test_parse_error_impl() {
137        let error = Error::ParseError(FrameType::Ping, "test error".to_string());
138        let appended = Error::append(&[], NomErrorKind::ManyTill, error.clone());
139        assert_eq!(appended, error);
140    }
141
142    #[test]
143    #[should_panic(expected = "QUIC frame parser must always consume")]
144    fn test_parse_error_unreachable() {
145        Error::from_error_kind(&[], NomErrorKind::ManyTill);
146    }
147
148    #[test]
149    fn test_error_display() {
150        let error = Error::NoFrames;
151        assert_eq!(error.to_string(), "A packet containing no frames");
152
153        let error = Error::IncompleteType("test".to_string());
154        assert_eq!(error.to_string(), "Incomplete frame type: test");
155
156        let error = Error::InvalidType(VarInt::from_u32(0x1f));
157        assert_eq!(error.to_string(), "Invalid frame type from 31");
158    }
159}