1use std::fmt::{self, Debug, Display, Formatter};
2
3type BoxError = Box<dyn std::error::Error + Send + Sync>;
4
5#[non_exhaustive]
8pub enum Error {
9 UnknownField { field_name: Option<String> },
12
13 IncompleteFieldData { field_name: Option<String> },
15
16 IncompleteHeaders,
18
19 ReadHeaderFailed(httparse::Error),
21
22 DecodeHeaderName { name: String, cause: BoxError },
25
26 DecodeHeaderValue { value: Vec<u8>, cause: BoxError },
29
30 IncompleteStream,
32
33 FieldSizeExceeded { limit: u64, field_name: Option<String> },
35
36 StreamSizeExceeded { limit: u64 },
38
39 StreamReadFailed(BoxError),
41
42 LockFailure,
44
45 NoMultipart,
47
48 DecodeContentType(mime::FromStrError),
50
51 NoBoundary,
53
54 #[cfg(feature = "json")]
57 #[cfg_attr(nightly, doc(cfg(feature = "json")))]
58 DecodeJson(serde_json::Error),
59}
60
61impl Debug for Error {
62 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
63 Display::fmt(self, f)
64 }
65}
66
67impl Display for Error {
68 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
69 match self {
70 Error::UnknownField { field_name } => {
71 let name = field_name.as_deref().unwrap_or("<unknown>");
72 write!(f, "unknown field received: {:?}", name)
73 }
74 Error::IncompleteFieldData { field_name } => {
75 let name = field_name.as_deref().unwrap_or("<unknown>");
76 write!(f, "field {:?} received with incomplete data", name)
77 }
78 Error::DecodeHeaderName { name, .. } => {
79 write!(f, "failed to decode field's raw header name: {:?}", name)
80 }
81 Error::DecodeHeaderValue { .. } => {
82 write!(f, "failed to decode field's raw header value")
83 }
84 Error::FieldSizeExceeded { limit, field_name } => {
85 let name = field_name.as_deref().unwrap_or("<unknown>");
86 write!(f, "field {:?} exceeded the size limit: {} bytes", name, limit)
87 }
88 Error::StreamSizeExceeded { limit } => {
89 write!(f, "stream size exceeded limit: {} bytes", limit)
90 }
91 Error::ReadHeaderFailed(_) => write!(f, "failed to read headers"),
92 Error::StreamReadFailed(_) => write!(f, "failed to read stream"),
93 Error::DecodeContentType(_) => write!(f, "failed to decode Content-Type"),
94 Error::IncompleteHeaders => write!(f, "failed to read field complete headers"),
95 Error::IncompleteStream => write!(f, "incomplete multipart stream"),
96 Error::LockFailure => write!(f, "failed to lock multipart state"),
97 Error::NoMultipart => write!(f, "Content-Type is not multipart/form-data"),
98 Error::NoBoundary => write!(f, "multipart boundary not found in Content-Type"),
99 #[cfg(feature = "json")]
100 Error::DecodeJson(_) => write!(f, "failed to decode field data as JSON"),
101 }
102 }
103}
104
105impl std::error::Error for Error {
106 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
107 match self {
108 Error::ReadHeaderFailed(e) => Some(e),
109 Error::DecodeHeaderName { cause, .. } => Some(cause.as_ref()),
110 Error::DecodeHeaderValue { cause, .. } => Some(cause.as_ref()),
111 Error::StreamReadFailed(e) => Some(e.as_ref()),
112 Error::DecodeContentType(e) => Some(e),
113 #[cfg(feature = "json")]
114 Error::DecodeJson(e) => Some(e),
115 Error::UnknownField { .. }
116 | Error::IncompleteFieldData { .. }
117 | Error::IncompleteHeaders
118 | Error::IncompleteStream
119 | Error::FieldSizeExceeded { .. }
120 | Error::StreamSizeExceeded { .. }
121 | Error::LockFailure
122 | Error::NoMultipart
123 | Error::NoBoundary => None,
124 }
125 }
126}
127
128impl PartialEq for Error {
129 fn eq(&self, other: &Self) -> bool {
130 self.to_string().eq(&other.to_string())
131 }
132}
133
134impl Eq for Error {}