use std::{ffi::CString, fmt};
use quickfix_ffi::{
FixSessionID_copy, FixSessionID_delete, FixSessionID_getBeginString,
FixSessionID_getSenderCompID, FixSessionID_getSessionQualifier, FixSessionID_getTargetCompID,
FixSessionID_isFIXT, FixSessionID_new, FixSessionID_t, FixSessionID_toString,
};
use crate::{utils::read_checked_cstr, QuickFixError};
pub struct SessionId(pub(crate) FixSessionID_t);
impl SessionId {
pub fn try_new(
begin_string: &str,
sender_comp_id: &str,
target_comp_id: &str,
session_qualifier: &str,
) -> Result<Self, QuickFixError> {
let ffi_begin_string = CString::new(begin_string)?;
let ffi_sender_comp_id = CString::new(sender_comp_id)?;
let ffi_target_comp_id = CString::new(target_comp_id)?;
let ffi_session_qualifier = CString::new(session_qualifier)?;
Ok(unsafe {
FixSessionID_new(
ffi_begin_string.as_ptr(),
ffi_sender_comp_id.as_ptr(),
ffi_target_comp_id.as_ptr(),
ffi_session_qualifier.as_ptr(),
)
}
.map(Self)
.expect("Fail to allocate SessionId"))
}
pub fn get_begin_string(&self) -> Option<String> {
unsafe { FixSessionID_getBeginString(self.0) }.map(read_checked_cstr)
}
pub fn get_sender_comp_id(&self) -> Option<String> {
unsafe { FixSessionID_getSenderCompID(self.0) }.map(read_checked_cstr)
}
pub fn get_target_comp_id(&self) -> Option<String> {
unsafe { FixSessionID_getTargetCompID(self.0) }.map(read_checked_cstr)
}
pub fn get_session_qualifier(&self) -> Option<String> {
unsafe { FixSessionID_getSessionQualifier(self.0) }.map(read_checked_cstr)
}
pub fn is_fixt(&self) -> bool {
let val = unsafe { FixSessionID_isFIXT(self.0) };
val != 0
}
pub fn to_repr(&self) -> String {
unsafe { FixSessionID_toString(self.0) }
.map(read_checked_cstr)
.unwrap_or_default()
}
}
impl Clone for SessionId {
fn clone(&self) -> Self {
Self(unsafe { FixSessionID_copy(self.0) }.expect("Fail to copy SessionID"))
}
}
impl fmt::Debug for SessionId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("SessionId").field(&self.to_repr()).finish()
}
}
impl Drop for SessionId {
fn drop(&mut self) {
unsafe { FixSessionID_delete(self.0) }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_clone_have_distinct_ptr() {
let session1 = SessionId::try_new("FIX.4.1", "FOO", "BAR", "").unwrap();
let session2 = session1.clone();
assert_ne!(session1.0, session2.0);
assert_eq!(session1.to_repr(), session2.to_repr());
}
}