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#[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 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 debug_assert_eq!(_kind, NomErrorKind::ManyTill);
75 source
76 }
77}
78
79#[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}