1use std::fmt;
4use std::io::{self, Write};
5
6use thiserror::Error;
7
8use ecksport_codec::CodecError;
9
10use crate::constants::*;
11
12pub type ClientResult<T> = Result<T, ClientError>;
14
15#[derive(Debug, Error)]
16pub enum ClientError {
17 #[error("tried to call with un-encodeable argument")]
18 MalformedRequest(CodecError),
19
20 #[error("no response from remote")]
21 NoResponse,
22
23 #[error("malformed response from remote ({0})")]
24 MalformedResponse(CodecError),
25
26 #[error("server rpc: {0}")]
27 ServerRpc(RpcError),
28
29 #[error("unable to parse error code")]
30 ParseErrorCode,
31
32 #[error("eio: {0}")]
33 EcksIo(#[from] ecksport_net::errors::Error),
34}
35
36impl From<RpcError> for ClientError {
37 fn from(value: RpcError) -> Self {
38 Self::ServerRpc(value)
39 }
40}
41
42#[derive(Debug, Error)]
43pub enum ServerError {
44 #[error("ecksio: {0}")]
45 EcksIo(#[from] ecksport_net::errors::Error),
46
47 #[error("io: {0}")]
48 TokioIo(#[from] tokio::io::Error),
49
50 #[error("not yet implemented")]
51 Unimplemented,
52}
53
54#[derive(Debug, Error)]
55pub enum Error {
56 #[error("unable to parse error code")]
57 ParseErrorCode,
58}
59
60pub type RpcResult<T> = Result<T, RpcError>;
62
63#[derive(Clone, Debug)]
64pub struct RpcError {
65 code: i16,
66 raw_msg: Option<Vec<u8>>,
67}
68
69impl RpcError {
70 pub fn new_code(code: i16) -> Self {
71 Self {
72 code,
73 raw_msg: None,
74 }
75 }
76
77 pub fn server<E: ToString>(code: i16, e: E) -> Self {
80 let buf = e.to_string().into_bytes();
81 Self {
82 code,
83 raw_msg: if buf.len() > 0 { Some(buf) } else { None },
84 }
85 }
86
87 pub fn code(&self) -> i16 {
88 self.code
89 }
90
91 pub fn raw_msg(&self) -> Option<&[u8]> {
92 self.raw_msg.as_ref().map(|b| b.as_slice())
93 }
94
95 pub fn kind(&self) -> RpcErrorKind {
98 match self.code {
99 c if c == ERR_INTERNAL => RpcErrorKind::Internal,
100 c if c == ERR_UNAUTH => RpcErrorKind::Unauthorized,
101 c if c == ERR_UNK_METHOD => RpcErrorKind::UnknownMethod,
102 c if c == ERR_MALFORMED_REQ => RpcErrorKind::MalformedRequest,
103 c if c > 0 => RpcErrorKind::Server(c),
104 _ => RpcErrorKind::Raw(self.code),
105 }
106 }
107
108 pub fn try_parse_msg(&self) -> Option<&str> {
111 self.raw_msg
112 .as_ref()
113 .and_then(|b| std::str::from_utf8(&b).ok())
114 }
115
116 pub fn to_vec(&self) -> Vec<u8> {
118 let mut buf = Vec::new();
119
120 {
121 let mut cur = io::Cursor::new(&mut buf);
122 cur.write_all(&self.code().to_be_bytes()).unwrap();
123 if let Some(m) = self.raw_msg() {
124 cur.write_all(m).unwrap();
125 }
126 }
127
128 buf
129 }
130
131 pub fn from_slice(buf: &[u8]) -> Result<Self, Error> {
134 if buf.len() < 2 {
135 return Err(Error::ParseErrorCode);
136 }
137
138 let code = i16::from_be_bytes(<[u8; 2]>::try_from(&buf[..2]).unwrap());
139
140 Ok(Self {
141 code,
142 raw_msg: if buf.len() > 2 {
143 Some(buf[2..].to_vec())
144 } else {
145 None
146 },
147 })
148 }
149}
150
151impl fmt::Display for RpcError {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 let k = self.kind();
155 f.write_fmt(format_args!("{k}"))?;
156
157 if let Some(aux) = self.try_parse_msg() {
158 f.write_fmt(format_args!(" ({aux})"))?;
159 } else {
160 f.write_str(" +data")?;
161 }
162
163 Ok(())
164 }
165}
166
167#[derive(Copy, Clone, Debug, Error)]
169pub enum RpcErrorKind {
170 #[error("internal error")]
172 Internal,
173
174 #[error("unauthorized request")]
176 Unauthorized,
177
178 #[error("unknown method")]
180 UnknownMethod,
181
182 #[error("malformed request")]
184 MalformedRequest,
185
186 #[error("server error {0}")]
188 Server(i16),
189
190 #[error("unknown error {0}")]
192 Raw(i16),
193}