1use std::fmt;
4
5#[derive(Debug, thiserror::Error)]
7pub enum StreamError {
8 #[error("I/O: {0}")]
9 Io(#[from] std::io::Error),
10 #[error("TLS: {0}")]
11 Tls(String),
12 #[error("connect: {0}")]
13 Connect(#[from] quinn::ConnectError),
14 #[error("connection: {0}")]
15 Connection(#[from] quinn::ConnectionError),
16 #[error("read: {0}")]
17 Read(#[from] quinn::ReadExactError),
18 #[error("write: {0}")]
19 Write(#[from] quinn::WriteError),
20 #[error("message of {len} bytes exceeds the {max}-byte limit")]
21 TooLarge { len: usize, max: usize },
22 #[error("stream ended inside a message")]
23 Truncated,
24 #[error("decode: {0}")]
25 Decode(#[from] prost::DecodeError),
26 #[error("protocol: {0}")]
28 Protocol(String),
29 #[error("server: {0}")]
31 Server(String),
32 #[error(transparent)]
33 Dsp(#[from] dspk_core::DspError),
34}
35
36impl StreamError {
37 pub(crate) fn protocol(message: impl fmt::Display) -> Self {
38 Self::Protocol(message.to_string())
39 }
40
41 pub(crate) fn reason(&self) -> String {
43 match self {
44 Self::Protocol(m) | Self::Server(m) | Self::Tls(m) => m.clone(),
45 other => other.to_string(),
46 }
47 }
48
49 pub fn is_closed_by_peer(&self) -> bool {
51 use quinn::{ConnectionError, ReadError, ReadExactError};
52 matches!(
53 self,
54 Self::Connection(ConnectionError::ApplicationClosed(_) | ConnectionError::LocallyClosed)
55 | Self::Read(ReadExactError::ReadError(ReadError::ConnectionLost(ConnectionError::ApplicationClosed(_) | ConnectionError::LocallyClosed)))
56 )
57 }
58}
59
60pub type StreamResult<T> = Result<T, StreamError>;