1use nom::error::ErrorKind as NomErrorKind;
2use thiserror::Error;
3
4use super::FrameType;
5use crate::{
6 error::{ErrorKind as TransportErrorKind, QuicError as TransportError},
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 TransportError {
29 fn from(e: Error) -> Self {
30 tracing::error!(" Cause by: parse frame error {e}");
31 match e {
32 Error::NoFrames => {
34 Self::with_default_fty(TransportErrorKind::ProtocolViolation, e.to_string())
35 }
36 Error::IncompleteType(_) => {
37 Self::with_default_fty(TransportErrorKind::FrameEncoding, e.to_string())
38 }
39 Error::InvalidType(_) => {
40 Self::with_default_fty(TransportErrorKind::FrameEncoding, e.to_string())
41 }
42 Error::WrongType(fty, _) => {
43 Self::new(TransportErrorKind::FrameEncoding, fty.into(), e.to_string())
44 }
45 Error::IncompleteFrame(fty, _) => {
46 Self::new(TransportErrorKind::FrameEncoding, fty.into(), e.to_string())
47 }
48 Error::ParseError(fty, _) => {
49 Self::new(TransportErrorKind::FrameEncoding, fty.into(), e.to_string())
50 }
51 }
52 }
53}
54
55impl From<nom::Err<Error>> for Error {
56 fn from(error: nom::Err<Error>) -> Self {
57 tracing::error!(" Cause by: nom error {error}");
58 match error {
59 nom::Err::Incomplete(_needed) => {
60 unreachable!("Because the parsing of QUIC packets and frames is not stream-based.")
61 }
62 nom::Err::Error(err) | nom::Err::Failure(err) => err,
63 }
64 }
65}
66
67impl nom::error::ParseError<&[u8]> for Error {
68 fn from_error_kind(_input: &[u8], _kind: NomErrorKind) -> Self {
69 debug_assert_eq!(_kind, NomErrorKind::ManyTill);
70 unreachable!("QUIC frame parser must always consume")
71 }
72
73 fn append(_input: &[u8], _kind: NomErrorKind, source: Self) -> Self {
74 debug_assert_eq!(_kind, NomErrorKind::ManyTill);
77 source
78 }
79}
80
81#[cfg(test)]
84mod tests {
85 use nom::error::ParseError;
86
87 use super::*;
88 use crate::packet::r#type::{
89 Type,
90 long::{Type::V1, Ver1},
91 };
92
93 #[test]
94 fn test_error_conversion_to_transport_error() {
95 let cases = vec![
96 (Error::NoFrames, TransportErrorKind::ProtocolViolation),
97 (
98 Error::IncompleteType("test".to_string()),
99 TransportErrorKind::FrameEncoding,
100 ),
101 (
102 Error::InvalidType(VarInt::from_u32(0x1f)),
103 TransportErrorKind::FrameEncoding,
104 ),
105 (
106 Error::WrongType(FrameType::Ping, Type::Long(V1(Ver1::INITIAL))),
107 TransportErrorKind::FrameEncoding,
108 ),
109 (
110 Error::IncompleteFrame(FrameType::Ping, "incomplete".to_string()),
111 TransportErrorKind::FrameEncoding,
112 ),
113 (
114 Error::ParseError(FrameType::Ping, "parse error".to_string()),
115 TransportErrorKind::FrameEncoding,
116 ),
117 ];
118
119 for (error, expected_kind) in cases {
120 let transport_error: TransportError = error.into();
121 assert_eq!(transport_error.kind(), expected_kind);
122 }
123 }
124
125 #[test]
126 fn test_nom_error_conversion() {
127 let error = Error::NoFrames;
128 let nom_error = nom::Err::Error(error.clone());
129 let converted: Error = nom_error.into();
130 assert_eq!(converted, error);
131
132 let nom_failure = nom::Err::Failure(error.clone());
133 let converted: Error = nom_failure.into();
134 assert_eq!(converted, error);
135 }
136
137 #[test]
138 fn test_parse_error_impl() {
139 let error = Error::ParseError(FrameType::Ping, "test error".to_string());
140 let appended = Error::append(&[], NomErrorKind::ManyTill, error.clone());
141 assert_eq!(appended, error);
142 }
143
144 #[test]
145 #[should_panic(expected = "QUIC frame parser must always consume")]
146 fn test_parse_error_unreachable() {
147 Error::from_error_kind(&[], NomErrorKind::ManyTill);
148 }
149
150 #[test]
151 fn test_error_display() {
152 let error = Error::NoFrames;
153 assert_eq!(error.to_string(), "A packet containing no frames");
154
155 let error = Error::IncompleteType("test".to_string());
156 assert_eq!(error.to_string(), "Incomplete frame type: test");
157
158 let error = Error::InvalidType(VarInt::from_u32(0x1f));
159 assert_eq!(error.to_string(), "Invalid frame type from 31");
160 }
161}