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
135
136
137
138
139
140
141
142
143
144
145
//! The error type shared by every streaming format, in both directions.
use std::fmt;
type BoxedError = Box<dyn std::error::Error + Send + Sync>;
/// The error that may occur while encoding or decoding a streamed HTTP body.
pub struct StreamError {
kind: StreamErrorKind,
source: Option<BoxedError>,
message: Option<String>,
}
impl StreamError {
/// Create a new instance of an error.
///
/// Public so that formats implemented outside this crate can report failures the same way
/// the built-in ones do.
pub fn new(kind: StreamErrorKind, source: Option<BoxedError>, message: Option<String>) -> Self {
Self {
kind,
source,
message,
}
}
/// The kind of error that occurred.
pub fn kind(&self) -> StreamErrorKind {
self.kind
}
/// The actual error that occurred.
pub fn source(&self) -> Option<&BoxedError> {
self.source.as_ref()
}
/// The message associated with the error.
pub fn message(&self) -> Option<&str> {
self.message.as_deref()
}
/// Takes the error apart, giving up ownership of its cause.
///
/// Exists so a binding crate can wrap its own error type to pass it through this crate's
/// pipeline and then recover the *original* on the way out, by downcasting the returned
/// source. Without that, a round trip would leave the caller's error nested inside a
/// `StreamError` inside their own error type, changing what their callbacks see.
pub fn into_parts(self) -> (StreamErrorKind, Option<BoxedError>, Option<String>) {
(self.kind, self.source, self.message)
}
/// A codec error carrying `source` as its cause.
pub fn codec(source: impl Into<BoxedError>) -> Self {
Self::new(StreamErrorKind::CodecError, Some(source.into()), None)
}
/// An I/O error carrying `source` as its cause.
pub fn io(source: impl Into<BoxedError>) -> Self {
Self::new(StreamErrorKind::InputOutputError, Some(source.into()), None)
}
}
/// The kind of error that occurred.
///
/// Variant names are inherited from `reqwest-streams`, whose public `StreamBodyKind` is a
/// renamed re-export of this type: renaming them would break downstream `match` arms.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum StreamErrorKind {
/// An error occured while encoding or decoding a frame or format.
CodecError,
/// An error occured while reading or writing the stream.
InputOutputError,
/// The maximum length of a single object was exceeded.
MaxLenReachedError,
/// The maximum length of the whole body was exceeded.
///
/// Only reachable on the receiving side, where the peer is not trusted.
MaxBodyLenReachedError,
}
impl StreamErrorKind {
/// A short, stable name for this kind, reported as the `error_kind` tracing field so that
/// errors can be aggregated without parsing their [`Display`] output.
///
/// [`Display`]: fmt::Display
pub fn as_str(&self) -> &'static str {
match self {
StreamErrorKind::CodecError => "codec",
StreamErrorKind::InputOutputError => "io",
StreamErrorKind::MaxLenReachedError => "max_len",
StreamErrorKind::MaxBodyLenReachedError => "max_body_len",
}
}
}
impl fmt::Debug for StreamError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut builder = f.debug_struct("StreamError");
builder.field("kind", &self.kind);
if let Some(ref source) = self.source {
builder.field("source", source);
}
if let Some(ref message) = self.message {
builder.field("message", message);
}
builder.finish()
}
}
impl fmt::Display for StreamError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.kind {
StreamErrorKind::CodecError => f.write_str("Frame/codec error")?,
StreamErrorKind::InputOutputError => f.write_str("I/O error")?,
StreamErrorKind::MaxLenReachedError => f.write_str("Max object length reached")?,
StreamErrorKind::MaxBodyLenReachedError => f.write_str("Max body length reached")?,
};
if let Some(message) = &self.message {
write!(f, ": {}", message)?;
}
if let Some(e) = &self.source {
write!(f, ": {}", e)?;
}
Ok(())
}
}
impl std::error::Error for StreamError {}
impl From<std::io::Error> for StreamError {
fn from(err: std::io::Error) -> Self {
StreamError::new(StreamErrorKind::InputOutputError, Some(Box::new(err)), None)
}
}