use std::ffi::{CStr, NulError};
use quickfix_ffi::{Fix_clearLastErrorMessage, Fix_getLastErrorCode, Fix_getLastErrorMessage};
use thiserror::Error;
#[derive(Debug, Error, PartialEq, Eq, Clone)]
pub enum QuickFixError {
#[error("invalid function return code: code={0}, msg={1}")]
InvalidFunctionReturnCode(i8, String),
#[error("Invalid argument: {0}")]
InvalidArgument(String),
#[error("quickfix: {0}")]
DataDictionaryNotFound(String),
#[error("quickfix: {0}")]
FieldNotFound(String),
#[error("quickfix: {0}")]
FieldConvertError(String),
#[error("quickfix: {0}")]
MessageParseError(String),
#[error("quickfix: {0}")]
InvalidMessage(String),
#[error("quickfix: {0}")]
ConfigError(String),
#[error("quickfix: {0}")]
RuntimeError(String),
#[error("quickfix: {0}")]
InvalidTagNumber(String),
#[error("quickfix: {0}")]
RequiredTagMissing(String),
#[error("quickfix: {0}")]
TagNotDefinedForMessage(String),
#[error("quickfix: {0}")]
NoTagValue(String),
#[error("quickfix: {0}")]
IncorrectTagValue(String),
#[error("quickfix: {0}")]
IncorrectDataFormat(String),
#[error("quickfix: {0}")]
IncorrectMessageStructure(String),
#[error("quickfix: {0}")]
DuplicateFieldNumber(String),
#[error("quickfix: {0}")]
InvalidMessageType(String),
#[error("quickfix: {0}")]
UnsupportedMessageType(String),
#[error("quickfix: {0}")]
UnsupportedVersion(String),
#[error("quickfix: {0}")]
TagOutOfOrder(String),
#[error("quickfix: {0}")]
RepeatedTag(String),
#[error("quickfix: {0}")]
RepeatingGroupCountMismatch(String),
#[error("quickfix: {0}")]
DoNotSend(String),
#[error("quickfix: {0}")]
RejectLogon(String),
#[error("quickfix: {0}")]
SessionNotFound(String),
#[error("quickfix: {0}")]
IOException(String),
#[error("quickfix: {0}")]
SocketException(String),
#[error("quickfix: {0}")]
SocketSendFailed(String),
#[error("quickfix: {0}")]
SocketRecvFailed(String),
#[error("quickfix: {0}")]
SocketCloseFailed(String),
}
impl QuickFixError {
pub fn invalid_argument<T: Into<String>>(msg: T) -> Self {
Self::InvalidArgument(msg.into())
}
pub fn from_last_error() -> Self {
match unsafe { Fix_getLastErrorCode() } {
-10 => Self::DataDictionaryNotFound(last_quickfix_error_message_or_default()),
-11 => Self::FieldNotFound(last_quickfix_error_message_or_default()),
-12 => Self::FieldConvertError(last_quickfix_error_message_or_default()),
-13 => Self::MessageParseError(last_quickfix_error_message_or_default()),
-14 => Self::InvalidMessage(last_quickfix_error_message_or_default()),
-15 => Self::ConfigError(last_quickfix_error_message_or_default()),
-16 => Self::RuntimeError(last_quickfix_error_message_or_default()),
-17 => Self::InvalidTagNumber(last_quickfix_error_message_or_default()),
-18 => Self::RequiredTagMissing(last_quickfix_error_message_or_default()),
-19 => Self::TagNotDefinedForMessage(last_quickfix_error_message_or_default()),
-20 => Self::NoTagValue(last_quickfix_error_message_or_default()),
-21 => Self::IncorrectTagValue(last_quickfix_error_message_or_default()),
-22 => Self::IncorrectDataFormat(last_quickfix_error_message_or_default()),
-23 => Self::IncorrectMessageStructure(last_quickfix_error_message_or_default()),
-24 => Self::DuplicateFieldNumber(last_quickfix_error_message_or_default()),
-25 => Self::InvalidMessageType(last_quickfix_error_message_or_default()),
-26 => Self::UnsupportedMessageType(last_quickfix_error_message_or_default()),
-27 => Self::UnsupportedVersion(last_quickfix_error_message_or_default()),
-28 => Self::TagOutOfOrder(last_quickfix_error_message_or_default()),
-29 => Self::RepeatedTag(last_quickfix_error_message_or_default()),
-30 => Self::RepeatingGroupCountMismatch(last_quickfix_error_message_or_default()),
-31 => Self::DoNotSend(last_quickfix_error_message_or_default()),
-32 => Self::RejectLogon(last_quickfix_error_message_or_default()),
-33 => Self::SessionNotFound(last_quickfix_error_message_or_default()),
-34 => Self::IOException(last_quickfix_error_message_or_default()),
-35 => Self::SocketException(last_quickfix_error_message_or_default()),
-36 => Self::SocketSendFailed(last_quickfix_error_message_or_default()),
-37 => Self::SocketRecvFailed(last_quickfix_error_message_or_default()),
-38 => Self::SocketCloseFailed(last_quickfix_error_message_or_default()),
value => {
Self::InvalidFunctionReturnCode(value, last_quickfix_error_message_or_default())
}
}
}
}
impl From<NulError> for QuickFixError {
fn from(value: NulError) -> Self {
Self::InvalidArgument(value.to_string())
}
}
fn last_quickfix_error_message_or_default() -> String {
last_quickfix_error_message()
.unwrap_or_else(|| "Cannot get last error message from quickfix library".to_string())
}
fn last_quickfix_error_message() -> Option<String> {
unsafe {
let raw_error = Fix_getLastErrorMessage()?;
let error = CStr::from_ptr(raw_error.as_ptr());
let error_msg = error.to_string_lossy().to_string();
Fix_clearLastErrorMessage();
Some(error_msg)
}
}