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