1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[non_exhaustive]
11pub enum ErrorCode {
12 InvalidInput,
13 ConnectionFailed,
14 Timeout,
15 BodyTooLarge,
16 HeaderTooLarge,
17 PeerRejected,
18 Cancelled,
19 Internal,
20}
21
22#[derive(Debug, Clone, thiserror::Error)]
26#[error("{code:?}: {message}")]
27pub struct CoreError {
28 pub code: ErrorCode,
29 pub message: String,
30}
31
32impl CoreError {
33 pub fn invalid_input(detail: impl std::fmt::Display) -> Self {
34 CoreError {
35 code: ErrorCode::InvalidInput,
36 message: detail.to_string(),
37 }
38 }
39 pub fn connection_failed(detail: impl std::fmt::Display) -> Self {
40 CoreError {
41 code: ErrorCode::ConnectionFailed,
42 message: detail.to_string(),
43 }
44 }
45 pub fn timeout(detail: impl std::fmt::Display) -> Self {
46 CoreError {
47 code: ErrorCode::Timeout,
48 message: detail.to_string(),
49 }
50 }
51 pub fn body_too_large(detail: impl std::fmt::Display) -> Self {
52 CoreError {
53 code: ErrorCode::BodyTooLarge,
54 message: detail.to_string(),
55 }
56 }
57 pub fn header_too_large(detail: impl std::fmt::Display) -> Self {
58 CoreError {
59 code: ErrorCode::HeaderTooLarge,
60 message: detail.to_string(),
61 }
62 }
63 pub fn peer_rejected(detail: impl std::fmt::Display) -> Self {
64 CoreError {
65 code: ErrorCode::PeerRejected,
66 message: detail.to_string(),
67 }
68 }
69 pub fn internal(detail: impl std::fmt::Display) -> Self {
70 CoreError {
71 code: ErrorCode::Internal,
72 message: detail.to_string(),
73 }
74 }
75 pub fn invalid_handle(handle: u64) -> Self {
76 CoreError {
77 code: ErrorCode::InvalidInput,
78 message: format!("unknown handle: {handle}"),
79 }
80 }
81 pub fn cancelled() -> Self {
82 CoreError {
83 code: ErrorCode::Cancelled,
84 message: "aborted".to_string(),
85 }
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn core_error_display() {
95 let e = CoreError::timeout("30s elapsed");
96 assert!(e.to_string().contains("Timeout"));
97 assert!(e.to_string().contains("30s elapsed"));
98 }
99}