use std::fmt::Display;
use longport_httpcli::HttpClientError;
use longport_wscli::WsClientError;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
DecodeProtobuf(#[from] prost::DecodeError),
#[error(transparent)]
DecodeJSON(#[from] serde_json::Error),
#[error("parse field: {name}: {error}")]
ParseField {
name: &'static str,
error: String,
},
#[error("unknown command: {0}")]
UnknownCommand(
u8,
),
#[error("invalid security symbol: {symbol}")]
InvalidSecuritySymbol {
symbol: String,
},
#[error(transparent)]
HttpClient(#[from] HttpClientError),
#[error(transparent)]
WsClient(#[from] WsClientError),
#[cfg(feature = "blocking")]
#[error(transparent)]
Blocking(#[from] crate::blocking::BlockingError),
}
impl Error {
#[inline]
pub(crate) fn parse_field_error(name: &'static str, error: impl Display) -> Self {
Self::ParseField {
name,
error: error.to_string(),
}
}
pub fn into_simple_error(self) -> SimpleError {
match self {
Error::HttpClient(HttpClientError::OpenApi {
code,
message,
trace_id,
}) => SimpleError::Response {
code: code as i64,
message,
trace_id,
},
Error::WsClient(WsClientError::ResponseError {
detail: Some(detail),
..
}) => SimpleError::Response {
code: detail.code as i64,
message: detail.msg,
trace_id: String::new(),
},
Error::DecodeProtobuf(_)
| Error::DecodeJSON(_)
| Error::InvalidSecuritySymbol { .. }
| Error::ParseField { .. }
| Error::UnknownCommand(_)
| Error::HttpClient(_)
| Error::WsClient(_) => SimpleError::Other(self.to_string()),
#[cfg(feature = "blocking")]
Error::Blocking(_) => SimpleError::Other(self.to_string()),
}
}
}
pub type Result<T> = ::std::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum SimpleError {
#[error("response error: code={code} message={message}")]
Response {
code: i64,
message: String,
trace_id: String,
},
#[error("other error: {0}")]
Other(String),
}
impl From<Error> for SimpleError {
#[inline]
fn from(err: Error) -> Self {
err.into_simple_error()
}
}
impl SimpleError {
pub fn code(&self) -> Option<i64> {
match self {
SimpleError::Response { code, .. } => Some(*code),
SimpleError::Other(_) => None,
}
}
pub fn trace_id(&self) -> Option<&str> {
match self {
SimpleError::Response { trace_id, .. } => Some(trace_id),
SimpleError::Other(_) => None,
}
}
pub fn message(&self) -> &str {
match self {
SimpleError::Response { message, .. } => message.as_str(),
SimpleError::Other(message) => message.as_str(),
}
}
}