1use thiserror::Error;
2
3#[derive(Debug, Error, Clone, PartialEq, Eq)]
4#[error("invalid config {config}.{field}: {message}")]
5pub struct ConfigValidationError {
6 pub config: &'static str,
7 pub field: &'static str,
8 pub message: String,
9}
10
11impl ConfigValidationError {
12 pub fn new(config: &'static str, field: &'static str, message: impl Into<String>) -> Self {
13 Self {
14 config,
15 field,
16 message: message.into(),
17 }
18 }
19}
20
21pub mod server {
22 use std::io;
23
24 use thiserror::Error;
25
26 use super::ConfigValidationError;
27
28 #[derive(Debug, Error, Clone, PartialEq, Eq)]
29 pub enum ServerError {
30 #[error("io error: {message}")]
31 Io { message: String },
32 #[error("invalid config: {details}")]
33 InvalidConfig { details: String },
34 #[error("listener is already started")]
35 AlreadyStarted,
36 #[error("listener is not started")]
37 NotStarted,
38 #[error("listener command channel closed")]
39 CommandChannelClosed,
40 #[error("listener accept channel closed")]
41 AcceptChannelClosed,
42 #[error("listener worker stopped unexpectedly")]
43 WorkerStopped,
44 }
45
46 impl From<io::Error> for ServerError {
47 fn from(value: io::Error) -> Self {
48 Self::Io {
49 message: value.to_string(),
50 }
51 }
52 }
53
54 impl From<ConfigValidationError> for ServerError {
55 fn from(value: ConfigValidationError) -> Self {
56 Self::InvalidConfig {
57 details: value.to_string(),
58 }
59 }
60 }
61
62 impl From<ServerError> for io::Error {
63 fn from(value: ServerError) -> Self {
64 let kind = match value {
65 ServerError::AlreadyStarted => io::ErrorKind::AlreadyExists,
66 ServerError::NotStarted => io::ErrorKind::NotConnected,
67 ServerError::CommandChannelClosed
68 | ServerError::AcceptChannelClosed
69 | ServerError::WorkerStopped => io::ErrorKind::BrokenPipe,
70 ServerError::Io { .. } | ServerError::InvalidConfig { .. } => {
71 io::ErrorKind::InvalidInput
72 }
73 };
74 io::Error::new(kind, value.to_string())
75 }
76 }
77}
78
79#[derive(Debug, Error)]
80pub enum EncodeError {
81 #[error("missing reliable index for reliable frame")]
82 MissingReliableIndex,
83 #[error("missing sequence index for sequenced frame")]
84 MissingSequenceIndex,
85 #[error("missing ordering index for ordered/sequenced frame")]
86 MissingOrderingIndex,
87 #[error("missing ordering channel for ordered/sequenced frame")]
88 MissingOrderingChannel,
89 #[error("missing split metadata for split frame")]
90 MissingSplitInfo,
91 #[error("frame payload length does not match bit length")]
92 FrameBitLengthMismatch,
93 #[error("ack/nack record count overflow: {0}")]
94 AckRecordOverflow(usize),
95 #[error("mtu out of supported range: {0}")]
96 InvalidMtu(u16),
97 #[error("offline pong motd is too long: {0} bytes")]
98 OfflinePongMotdTooLong(usize),
99 #[error("invalid datagram flags: 0x{0:02x}")]
100 InvalidDatagramFlags(u8),
101}
102
103#[derive(Debug, Error)]
104pub enum DecodeError {
105 #[error("unexpected eof")]
106 UnexpectedEof,
107 #[error("unknown reliability value: {0}")]
108 UnknownReliability(u8),
109 #[error("invalid frame bit length: {0}")]
110 InvalidFrameBitLength(u16),
111 #[error("invalid ack packet")]
112 InvalidAckPacket,
113 #[error("invalid datagram flags: 0x{0:02x}")]
114 InvalidDatagramFlags(u8),
115 #[error("invalid offline packet id: 0x{0:02x}")]
116 InvalidOfflinePacketId(u8),
117 #[error("invalid connected packet id: 0x{0:02x}")]
118 InvalidConnectedPacketId(u8),
119 #[error("invalid magic for unconnected packet")]
120 InvalidMagic,
121 #[error("invalid ip address version: {0}")]
122 InvalidAddrVersion(u8),
123 #[error("invalid open connection request 2 layout")]
124 InvalidRequest2Layout,
125 #[error("split index out of range")]
126 SplitIndexOutOfRange,
127 #[error("split count cannot be zero")]
128 SplitCountZero,
129 #[error("split metadata missing while split flag is set")]
130 MissingSplitInfo,
131 #[error("split count mismatch")]
132 SplitCountMismatch,
133 #[error("split packet exceeds maximum part limit")]
134 SplitTooLarge,
135 #[error("split assembler buffer is full")]
136 SplitBufferFull,
137 #[error("invalid ack range count: {0}")]
138 InvalidAckRangeCount(u16),
139}