1use std::num::{ParseFloatError, ParseIntError};
3use std::sync::mpsc::{RecvError, RecvTimeoutError, TryRecvError};
4use std::{error, fmt, io};
5
6const ALREADY_CONNECTED: (i32, &str) = (501, "Already connected.");
7const CONNECT_FAIL: (i32, &str) = (502, "Couldn't connect to TWS. Confirm that \"Enable ActiveX and Socket EClients\"
8 is enabled and connection port is the same as \"Socket Port\" on the
9 TWS \"Edit->Global Configuration...->API->Settings\" menu. Live Trading ports:
10 TWS: 7496; IB Gateway: 4001. Simulated Trading ports for new installations
11 of version 954.1 or newer: TWS: 7497; IB Gateway: 4002");
12const UPDATE_TWS: (i32, &str) = (503, "The TWS is out of date and must be upgraded.");
13const NOT_CONNECTED: (i32, &str) = (504, "Not connected.");
14const UNKNOWN_ID: (i32, &str) = (505, "Fatal TwsError: Unknown message id.");
15const UNSUPPORTED: (i32, &str) = (506, "UNSUPPORTED version");
16const BAD_LENGTH: (i32, &str) = (507, "Bad message length.");
17const BAD_MESSAGE: (i32, &str) = (508, "Bad message.");
18const SOCKET_EXCEPTION: (i32, &str) = (509, "Exception caught while reading socket.");
19const FAIL_CREATE_SOCK: (i32, &str) = (520, "Failed to create socket.");
20const SSL_FAIL: (i32, &str) = (530, "SSL specific TwsError.");
21
22#[derive(Clone, Debug)]
23pub enum TwsError {
24 AlreadyConnected,
25 ConnectFail,
26 UpdateTws,
27 NotConnected,
28 UnknownId,
29 Unsupported,
30 BadLength,
31 BadMessage,
32 SocketException,
33 FailCreateSock,
34 SslFail,
35}
36
37impl TwsError {
38 pub fn code(&self) -> i32 {
39 match *self {
40 TwsError::AlreadyConnected => ALREADY_CONNECTED.0,
41 TwsError::ConnectFail => CONNECT_FAIL.0,
42 TwsError::UpdateTws => UPDATE_TWS.0,
43 TwsError::NotConnected => NOT_CONNECTED.0,
44 TwsError::UnknownId => UNKNOWN_ID.0,
45 TwsError::Unsupported => UNSUPPORTED.0,
46 TwsError::BadLength => BAD_LENGTH.0,
47 TwsError::BadMessage => BAD_MESSAGE.0,
48 TwsError::SocketException => SOCKET_EXCEPTION.0,
49 TwsError::FailCreateSock => FAIL_CREATE_SOCK.0,
50 TwsError::SslFail => SSL_FAIL.0,
51 }
52 }
53 pub fn message(&self) -> &'static str {
54 match *self {
55 TwsError::AlreadyConnected => ALREADY_CONNECTED.1,
56 TwsError::ConnectFail => CONNECT_FAIL.1,
57 TwsError::UpdateTws => UPDATE_TWS.1,
58 TwsError::NotConnected => NOT_CONNECTED.1,
59 TwsError::UnknownId => UNKNOWN_ID.1,
60 TwsError::Unsupported => UNSUPPORTED.1,
61 TwsError::BadLength => BAD_LENGTH.1,
62 TwsError::BadMessage => BAD_MESSAGE.1,
63 TwsError::SocketException => SOCKET_EXCEPTION.1,
64 TwsError::FailCreateSock => FAIL_CREATE_SOCK.1,
65 TwsError::SslFail => SSL_FAIL.1,
66 }
67 }
68}
69
70impl error::Error for TwsError {}
71
72impl fmt::Display for TwsError {
73 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
74 write!(fmt, "Code: {}, Message: {}", self.code(), self.message())
75 }
76}
77
78pub enum IBKRApiLibError {
80 Io(io::Error),
81 ParseFloat(ParseFloatError),
82 ParseInt(ParseIntError),
83 RecvError(RecvError),
84 TryRecvError(TryRecvError),
85 RecvTimeoutError(RecvTimeoutError),
86 ApiError(TwsApiReportableError),
87}
88
89impl fmt::Display for IBKRApiLibError {
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 match self {
92 IBKRApiLibError::Io(ref err) => write!(f, "IO error: {}", err),
95 IBKRApiLibError::ParseFloat(ref err) => write!(f, "Parse error: {}", err),
96 IBKRApiLibError::ParseInt(ref err) => write!(f, "Parse error: {}", err),
97 IBKRApiLibError::RecvError(ref err) => write!(f, "Recieve error: {}", err),
98 IBKRApiLibError::TryRecvError(ref err) => write!(f, "TryRecieve error: {}", err),
99 IBKRApiLibError::RecvTimeoutError(ref err) => write!(f, "Reader Send error {}", err),
100 IBKRApiLibError::ApiError(ref err) => write!(f, "TWS Error: {}", err),
101 }
102 }
103}
104
105impl fmt::Debug for IBKRApiLibError {
106 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107 match self {
108 IBKRApiLibError::Io(ref err) => write!(f, "IO error: {}", err),
111 IBKRApiLibError::ParseFloat(ref err) => write!(f, "Parse error: {}", err),
112 IBKRApiLibError::ParseInt(ref err) => write!(f, "Parse error: {}", err),
113 IBKRApiLibError::RecvError(ref err) => write!(f, "Receive error: {}", err),
114 IBKRApiLibError::TryRecvError(ref err) => write!(f, "TryReceive error {}", err),
115 IBKRApiLibError::RecvTimeoutError(ref err) => write!(f, "Reader Send error {}", err),
116 IBKRApiLibError::ApiError(ref err) => write!(f, "TWS Error: {}", err),
117 }
118 }
119}
120
121impl error::Error for IBKRApiLibError {
122 fn cause(&self) -> Option<&dyn error::Error> {
123 match self {
124 IBKRApiLibError::Io(ref err) => Some(err),
129 IBKRApiLibError::ParseFloat(ref err) => Some(err),
130 IBKRApiLibError::ParseInt(ref err) => Some(err),
131 IBKRApiLibError::RecvError(ref err) => Some(err),
132 IBKRApiLibError::TryRecvError(ref err) => Some(err),
133 IBKRApiLibError::RecvTimeoutError(ref err) => Some(err),
134 IBKRApiLibError::ApiError(ref err) => Some(err),
135 }
136 }
137}
138
139impl From<io::Error> for IBKRApiLibError {
140 fn from(err: io::Error) -> IBKRApiLibError {
141 IBKRApiLibError::Io(err)
142 }
143}
144
145impl From<ParseIntError> for IBKRApiLibError {
146 fn from(err: ParseIntError) -> IBKRApiLibError {
147 IBKRApiLibError::ParseInt(err)
148 }
149}
150
151impl From<ParseFloatError> for IBKRApiLibError {
152 fn from(err: ParseFloatError) -> IBKRApiLibError {
153 IBKRApiLibError::ParseFloat(err)
154 }
155}
156
157impl From<RecvError> for IBKRApiLibError {
158 fn from(err: RecvError) -> IBKRApiLibError {
159 IBKRApiLibError::RecvError(err)
160 }
161}
162
163impl From<RecvTimeoutError> for IBKRApiLibError {
164 fn from(err: RecvTimeoutError) -> IBKRApiLibError {
165 IBKRApiLibError::RecvTimeoutError(err)
166 }
167}
168
169impl From<TwsApiReportableError> for IBKRApiLibError {
170 fn from(err: TwsApiReportableError) -> IBKRApiLibError {
171 IBKRApiLibError::ApiError(err)
172 }
173}
174
175#[derive(Clone, Debug)]
176pub struct TwsApiReportableError {
177 pub req_id: i32,
178 pub code: String,
179 pub description: String,
180}
181
182impl TwsApiReportableError {
183 pub fn new(req_id: i32, code: String, description: String) -> Self {
184 Self {
185 req_id: req_id,
186 code: code,
187 description: description,
188 }
189 }
190}
191
192impl fmt::Display for TwsApiReportableError {
193 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194 write!(
195 f,
196 "TWS Error: req_id = {}. code = {}. description = {}",
197 self.req_id, self.code, self.description
198 )
199 }
200}
201
202impl error::Error for TwsApiReportableError {}