1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::fmt::{self, Debug, Display, Formatter};

type BoxError = Box<dyn std::error::Error + Send + Sync>;

/// A set of errors that can occur during parsing multipart stream and in other
/// operations.
#[non_exhaustive]
pub enum Error {
    /// An unknown field is detected when multipart
    /// [`constraints`](crate::Constraints::allowed_fields) are added.
    UnknownField { field_name: Option<String> },

    /// The field data is found incomplete.
    IncompleteFieldData { field_name: Option<String> },

    /// Couldn't read the field headers completely.
    IncompleteHeaders,

    /// Failed to read headers.
    ReadHeaderFailed(httparse::Error),

    /// Failed to decode the field's raw header name to
    /// [`HeaderName`](http::header::HeaderName) type.
    DecodeHeaderName { name: String, cause: BoxError },

    /// Failed to decode the field's raw header value to
    /// [`HeaderValue`](http::header::HeaderValue) type.
    DecodeHeaderValue { value: Vec<u8>, cause: BoxError },

    /// Multipart stream is incomplete.
    IncompleteStream,

    /// The incoming field size exceeded the maximum limit.
    FieldSizeExceeded { limit: u64, field_name: Option<String> },

    /// The incoming stream size exceeded the maximum limit.
    StreamSizeExceeded { limit: u64 },

    /// Stream read failed.
    StreamReadFailed(BoxError),

    /// Failed to lock the multipart shared state for any changes.
    LockFailure,

    /// The `Content-Type` header is not `multipart/form-data`.
    NoMultipart,

    /// Failed to convert the `Content-Type` to [`mime::Mime`] type.
    DecodeContentType(mime::FromStrError),

    /// No boundary found in `Content-Type` header.
    NoBoundary,

    /// Failed to decode the field data as `JSON` in
    /// [`field.json()`](crate::Field::json) method.
    #[cfg(feature = "json")]
    #[cfg_attr(nightly, doc(cfg(feature = "json")))]
    DecodeJson(serde_json::Error),
}

impl Debug for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        Display::fmt(self, f)
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Error::UnknownField { field_name } => {
                let name = field_name.as_deref().unwrap_or("<unknown>");
                write!(f, "unknown field received: {:?}", name)
            }
            Error::IncompleteFieldData { field_name } => {
                let name = field_name.as_deref().unwrap_or("<unknown>");
                write!(f, "field {:?} received with incomplete data", name)
            }
            Error::DecodeHeaderName { name, .. } => {
                write!(f, "failed to decode field's raw header name: {:?}", name)
            }
            Error::DecodeHeaderValue { .. } => {
                write!(f, "failed to decode field's raw header value")
            }
            Error::FieldSizeExceeded { limit, field_name } => {
                let name = field_name.as_deref().unwrap_or("<unknown>");
                write!(f, "field {:?} exceeded the size limit: {} bytes", name, limit)
            }
            Error::StreamSizeExceeded { limit } => {
                write!(f, "stream size exceeded limit: {} bytes", limit)
            }
            Error::ReadHeaderFailed(_) => write!(f, "failed to read headers"),
            Error::StreamReadFailed(_) => write!(f, "failed to read stream"),
            Error::DecodeContentType(_) => write!(f, "failed to decode Content-Type"),
            Error::IncompleteHeaders => write!(f, "failed to read field complete headers"),
            Error::IncompleteStream => write!(f, "incomplete multipart stream"),
            Error::LockFailure => write!(f, "failed to lock multipart state"),
            Error::NoMultipart => write!(f, "Content-Type is not multipart/form-data"),
            Error::NoBoundary => write!(f, "multipart boundary not found in Content-Type"),
            #[cfg(feature = "json")]
            Error::DecodeJson(_) => write!(f, "failed to decode field data as JSON"),
        }
    }
}

impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Error::ReadHeaderFailed(e) => Some(e),
            Error::DecodeHeaderName { cause, .. } => Some(cause.as_ref()),
            Error::DecodeHeaderValue { cause, .. } => Some(cause.as_ref()),
            Error::StreamReadFailed(e) => Some(e.as_ref()),
            Error::DecodeContentType(e) => Some(e),
            #[cfg(feature = "json")]
            Error::DecodeJson(e) => Some(e),
            Error::UnknownField { .. }
            | Error::IncompleteFieldData { .. }
            | Error::IncompleteHeaders
            | Error::IncompleteStream
            | Error::FieldSizeExceeded { .. }
            | Error::StreamSizeExceeded { .. }
            | Error::LockFailure
            | Error::NoMultipart
            | Error::NoBoundary => None,
        }
    }
}

impl PartialEq for Error {
    fn eq(&self, other: &Self) -> bool {
        self.to_string().eq(&other.to_string())
    }
}

impl Eq for Error {}