s2n_quic_core/stream/
error.rs1use crate::{application, connection, frame::ConnectionClose, transport};
5use core::{fmt, panic};
6
7#[derive(PartialEq, Eq, Debug, Copy, Clone)]
9#[non_exhaustive]
10pub enum StreamError {
11 #[non_exhaustive]
15 InvalidStream {
16 source: &'static panic::Location<'static>,
17 },
18 #[non_exhaustive]
23 StreamReset {
24 error: application::Error,
25 source: &'static panic::Location<'static>,
26 },
27 #[non_exhaustive]
29 SendAfterFinish {
30 source: &'static panic::Location<'static>,
31 },
32 #[non_exhaustive]
38 MaxStreamDataSizeExceeded {
39 source: &'static panic::Location<'static>,
40 },
41 #[non_exhaustive]
43 ConnectionError { error: connection::Error },
44 #[non_exhaustive]
46 NonReadable {
47 source: &'static panic::Location<'static>,
48 },
49 #[non_exhaustive]
51 NonWritable {
52 source: &'static panic::Location<'static>,
53 },
54 #[non_exhaustive]
58 SendingBlocked {
59 source: &'static panic::Location<'static>,
60 },
61 #[non_exhaustive]
66 NonEmptyOutput {
67 source: &'static panic::Location<'static>,
68 },
69}
70
71#[cfg(feature = "std")]
72impl std::error::Error for StreamError {}
73
74impl fmt::Display for StreamError {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 match self {
77 Self::InvalidStream { .. } => {
78 write!(f, "The Stream ID which was referenced is invalid")
79 }
80 Self::StreamReset { error, .. } => write!(
81 f,
82 "The Stream had been reset with the error {:?} by {}",
83 error,
84 crate::endpoint::Location::Remote,
85 ),
86 Self::SendAfterFinish { .. } => write!(
87 f,
88 "A send attempt had been performed on a Stream after it was closed"
89 ),
90 Self::MaxStreamDataSizeExceeded { .. } => {
91 write!(f, "Attempting to write data would exceed the stream limit")
92 }
93 Self::ConnectionError { error, .. } => error.fmt(f),
94 Self::NonReadable { .. } => write!(f, "The stream is not readable"),
95 Self::NonWritable { .. } => write!(f, "The stream is not writable"),
96 Self::SendingBlocked { .. } => write!(f, "The stream is blocked on writing data"),
97 Self::NonEmptyOutput { .. } => write!(
98 f,
99 "The stream was provided a non-empty placeholder buffer for receiving data."
100 ),
101 }
102 }
103}
104
105impl StreamError {
106 pub fn source(&self) -> &'static panic::Location<'static> {
108 match self {
109 StreamError::InvalidStream { source } => source,
110 StreamError::StreamReset { source, .. } => source,
111 StreamError::SendAfterFinish { source } => source,
112 StreamError::MaxStreamDataSizeExceeded { source } => source,
113 StreamError::ConnectionError { error } => error.source(),
114 StreamError::NonReadable { source } => source,
115 StreamError::NonWritable { source } => source,
116 StreamError::SendingBlocked { source } => source,
117 StreamError::NonEmptyOutput { source } => source,
118 }
119 }
120
121 #[track_caller]
122 #[inline]
123 #[doc(hidden)]
124 pub fn invalid_stream() -> StreamError {
125 let source = panic::Location::caller();
126 StreamError::InvalidStream { source }
127 }
128
129 #[track_caller]
130 #[inline]
131 #[doc(hidden)]
132 pub fn stream_reset(error: application::Error) -> StreamError {
133 let source = panic::Location::caller();
134 StreamError::StreamReset { source, error }
135 }
136
137 #[track_caller]
138 #[inline]
139 #[doc(hidden)]
140 pub fn send_after_finish() -> StreamError {
141 let source = panic::Location::caller();
142 StreamError::SendAfterFinish { source }
143 }
144
145 #[track_caller]
146 #[inline]
147 #[doc(hidden)]
148 pub fn max_stream_data_size_exceeded() -> StreamError {
149 let source = panic::Location::caller();
150 StreamError::MaxStreamDataSizeExceeded { source }
151 }
152
153 #[track_caller]
154 #[inline]
155 #[doc(hidden)]
156 pub fn non_readable() -> StreamError {
157 let source = panic::Location::caller();
158 StreamError::NonReadable { source }
159 }
160
161 #[track_caller]
162 #[inline]
163 #[doc(hidden)]
164 pub fn non_writable() -> StreamError {
165 let source = panic::Location::caller();
166 StreamError::NonWritable { source }
167 }
168
169 #[track_caller]
170 #[inline]
171 #[doc(hidden)]
172 pub fn sending_blocked() -> StreamError {
173 let source = panic::Location::caller();
174 StreamError::SendingBlocked { source }
175 }
176
177 #[track_caller]
178 #[inline]
179 #[doc(hidden)]
180 pub fn non_empty_output() -> StreamError {
181 let source = panic::Location::caller();
182 StreamError::NonEmptyOutput { source }
183 }
184}
185
186impl application::error::TryInto for StreamError {
187 fn application_error(&self) -> Option<application::Error> {
188 if let StreamError::ConnectionError { error, .. } = self {
189 error.application_error()
190 } else {
191 None
192 }
193 }
194}
195
196impl From<connection::Error> for StreamError {
197 fn from(error: connection::Error) -> Self {
198 Self::ConnectionError { error }
199 }
200}
201
202impl From<transport::Error> for StreamError {
203 #[track_caller]
204 fn from(error: transport::Error) -> Self {
205 let error: connection::Error = error.into();
206 error.into()
207 }
208}
209
210impl From<ConnectionClose<'_>> for StreamError {
211 #[track_caller]
212 fn from(error: ConnectionClose) -> Self {
213 let error: connection::Error = error.into();
214 error.into()
215 }
216}
217
218#[cfg(feature = "std")]
219impl From<StreamError> for std::io::Error {
220 fn from(error: StreamError) -> Self {
221 let kind = error.into();
222 std::io::Error::new(kind, error)
223 }
224}
225
226#[cfg(feature = "std")]
227impl From<StreamError> for std::io::ErrorKind {
228 fn from(error: StreamError) -> Self {
229 use std::io::ErrorKind;
230 match error {
231 StreamError::InvalidStream { .. } => ErrorKind::NotFound,
232 StreamError::StreamReset { .. } => ErrorKind::ConnectionReset,
233 StreamError::SendAfterFinish { .. } => ErrorKind::BrokenPipe,
234 StreamError::MaxStreamDataSizeExceeded { .. } => ErrorKind::Other,
235 StreamError::ConnectionError { error, .. } => error.into(),
236 StreamError::NonReadable { .. } => ErrorKind::Other,
237 StreamError::NonWritable { .. } => ErrorKind::Other,
238 StreamError::SendingBlocked { .. } => ErrorKind::WouldBlock,
239 StreamError::NonEmptyOutput { .. } => ErrorKind::InvalidInput,
240 }
241 }
242}