aboutsummaryrefslogtreecommitdiff
path: root/src/error.rs
blob: 99acdd1c4b888d8289db6fa28191ee969f98928b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use err_derive::Error;
use std::io;

use log::error;

#[derive(Debug, Error)]
pub enum Error {
	#[error(display = "IO error: {}", _0)]
	Io(#[error(source)] io::Error),

	#[error(display = "Messagepack encode error: {}", _0)]
	RMPEncode(#[error(source)] rmp_serde::encode::Error),
	#[error(display = "Messagepack decode error: {}", _0)]
	RMPDecode(#[error(source)] rmp_serde::decode::Error),

	#[error(display = "Tokio join error: {}", _0)]
	TokioJoin(#[error(source)] tokio::task::JoinError),

	#[error(display = "oneshot receive error: {}", _0)]
	OneshotRecv(#[error(source)] tokio::sync::oneshot::error::RecvError),

	#[error(display = "Handshake error: {}", _0)]
	Handshake(#[error(source)] kuska_handshake::async_std::Error),

	#[error(display = "UTF8 error: {}", _0)]
	UTF8(#[error(source)] std::string::FromUtf8Error),

	#[error(display = "{}", _0)]
	Message(String),

	#[error(display = "No handler / shutting down")]
	NoHandler,

	#[error(display = "Connection closed")]
	ConnectionClosed,

	#[error(display = "Version mismatch: {}", _0)]
	VersionMismatch(String),

	#[error(display = "Remote error {}: {}", _0, _1)]
	Remote(u8, String),
}

impl Error {
	pub fn code(&self) -> u8 {
		match self {
			Self::Io(_) => 100,
			Self::TokioJoin(_) => 110,
			Self::OneshotRecv(_) => 111,
			Self::RMPEncode(_) => 10,
			Self::RMPDecode(_) => 11,
			Self::UTF8(_) => 12,
			Self::NoHandler => 20,
			Self::ConnectionClosed => 21,
			Self::Handshake(_) => 30,
			Self::VersionMismatch(_) => 31,
			Self::Remote(c, _) => *c,
			Self::Message(_) => 99,
		}
	}
}

impl<T> From<tokio::sync::watch::error::SendError<T>> for Error {
	fn from(_e: tokio::sync::watch::error::SendError<T>) -> Error {
		Error::Message("Watch send error".into())
	}
}

impl<T> From<tokio::sync::mpsc::error::SendError<T>> for Error {
	fn from(_e: tokio::sync::mpsc::error::SendError<T>) -> Error {
		Error::Message("MPSC send error".into())
	}
}

/// Ths trait adds a `.log_err()` method on `Result<(), E>` types,
/// which dismisses the error by logging it to stderr.
pub trait LogError {
	fn log_err(self, msg: &'static str);
}

impl<E> LogError for Result<(), E>
where
	E: Into<Error>,
{
	fn log_err(self, msg: &'static str) {
		if let Err(e) = self {
			error!("Error: {}: {}", msg, Into::<Error>::into(e));
		};
	}
}

impl<E, T> LogError for Result<T, E>
where
	T: LogError,
	E: Into<Error>,
{
	fn log_err(self, msg: &'static str) {
		match self {
			Err(e) => error!("Error: {}: {}", msg, Into::<Error>::into(e)),
			Ok(x) => x.log_err(msg),
		}
	}
}