From 10bcc4a12ec9b4ff980f345efbe4b350090b7be7 Mon Sep 17 00:00:00 2001 From: Arthur LE MOIGNE Date: Wed, 20 Mar 2024 10:35:18 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20more=20field=20to=20dictionar?= =?UTF-8?q?y=5Fitem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- quickfix/src/dictionary_item.rs | 134 ++++++++++++++++++++++++- quickfix/tests/test_dictionary_item.rs | 87 +++++++++++++++- 2 files changed, 216 insertions(+), 5 deletions(-) diff --git a/quickfix/src/dictionary_item.rs b/quickfix/src/dictionary_item.rs index 7f04e48..edbcbaa 100644 --- a/quickfix/src/dictionary_item.rs +++ b/quickfix/src/dictionary_item.rs @@ -1,6 +1,6 @@ #![allow(missing_debug_implementations)] -use crate::{Dictionary, QuickFixError}; +use crate::{DayOfWeek, Dictionary, QuickFixError}; /// Trait that represent quickfix configuration parameter. /// @@ -77,6 +77,30 @@ impl_dictionary_item!(SocketConnectPort as i32); pub struct SocketConnectHost<'a>(pub &'a str); impl_dictionary_item!(SocketConnectHost as String); +/// Initiator port to connect from. +pub struct SocketConnectSourcePort(pub u32); +impl_dictionary_item!(SocketConnectSourcePort as i32); + +/// Initiator host to connect from. +pub struct SocketConnectSourceHost<'a>(pub &'a str); +impl_dictionary_item!(SocketConnectSourceHost as String); + +/// Set SO_REUSEADDR flag when creating socket. +pub struct SocketReuseAddress(pub bool); +impl_dictionary_item!(SocketReuseAddress); + +/// Set TCP_NODELAY flag when creating socket. +pub struct SocketNodelay(pub bool); +impl_dictionary_item!(SocketNodelay); + +/// Configure SO_SNDBUF socket parameter. +pub struct SocketSendBufferSize(pub u16); +impl_dictionary_item!(SocketSendBufferSize as i32); + +/// Configure SO_RCVBUF socket parameter. +pub struct SocketReceiveBufferSize(pub u16); +impl_dictionary_item!(SocketReceiveBufferSize as i32); + /// Time in second to wait before reconnect. pub struct ReconnectInterval(pub u16); impl_dictionary_item!(ReconnectInterval as i32); @@ -85,18 +109,66 @@ impl_dictionary_item!(ReconnectInterval as i32); pub struct HeartBtInt(pub u16); impl_dictionary_item!(HeartBtInt as i32); +/// Send redundant resend requests. +pub struct SendRedundantResendRequests(pub bool); +impl_dictionary_item!(SendRedundantResendRequests); + +/// Send next expected message sequence number. +pub struct SendNextExpectedMsgSeqNum(pub bool); +impl_dictionary_item!(SendNextExpectedMsgSeqNum); + +/// Use local time. +pub struct UseLocalTime(pub bool); +impl_dictionary_item!(UseLocalTime); + /// Session start time. pub struct StartTime<'a>(pub &'a str); impl_dictionary_item!(StartTime as String); +/// Session start day. +pub struct StartDay(pub DayOfWeek); +impl_dictionary_item!(StartDay); + /// Session end time. pub struct EndTime<'a>(pub &'a str); impl_dictionary_item!(EndTime as String); +/// Session end day. +pub struct EndDay(pub DayOfWeek); +impl_dictionary_item!(EndDay); + +/// Logon time. +pub struct LogonTime<'a>(pub &'a str); +impl_dictionary_item!(LogonTime as String); + +/// Logon day. +pub struct LogonDay(pub DayOfWeek); +impl_dictionary_item!(LogonDay); + +/// Logon timeout. +pub struct LogonTimeout(pub u16); +impl_dictionary_item!(LogonTimeout as i32); + +/// Logout time. +pub struct LogoutTime<'a>(pub &'a str); +impl_dictionary_item!(LogoutTime as String); + +/// Logout day. +pub struct LogoutDay(pub DayOfWeek); +impl_dictionary_item!(LogoutDay); + +/// Logout timeout. +pub struct LogoutTimeout(pub u16); +impl_dictionary_item!(LogoutTimeout as i32); + /// Application version ID. pub struct DefaultApplVerID<'a>(pub &'a str); impl_dictionary_item!(DefaultApplVerID as String); +/// Parse and use data dictionary. +pub struct UseDataDictionary(pub bool); +impl_dictionary_item!(UseDataDictionary); + /// Data dictionary XML spec path. pub struct DataDictionary<'a>(pub &'a str); impl_dictionary_item!(DataDictionary as String); @@ -109,6 +181,66 @@ impl_dictionary_item!(TransportDataDictionary as String); pub struct FileStorePath<'a>(pub &'a str); impl_dictionary_item!(FileStorePath as String); +/// Validate message comp ID. +pub struct CheckCompID(pub bool); +impl_dictionary_item!(CheckCompID); + +/// Validate message latency. +pub struct CheckLatency(pub bool); +impl_dictionary_item!(CheckLatency); + +/// Max allowed latency. +pub struct MaxLatency(pub i32); +impl_dictionary_item!(MaxLatency); + +/// Validate message header length and checksum. +pub struct ValidateLengthAndChecksum(pub bool); +impl_dictionary_item!(ValidateLengthAndChecksum); + +/// Validate message fields sent in wrong order. +pub struct ValidateFieldsOutOfOrder(pub bool); +impl_dictionary_item!(ValidateFieldsOutOfOrder); + +/// Validate message fields inner values. +pub struct ValidateFieldsHaveValues(pub bool); +impl_dictionary_item!(ValidateFieldsHaveValues); + +/// Validate user custom fields. +pub struct ValidateUserDefinedFields(pub bool); +impl_dictionary_item!(ValidateUserDefinedFields); + +/// Allow unknown message fields. +pub struct AllowUnknownMsgFields(pub bool); +impl_dictionary_item!(AllowUnknownMsgFields); + +/// Preserve message fields order. +pub struct PreserveMessageFieldsOrder(pub bool); +impl_dictionary_item!(PreserveMessageFieldsOrder); + +/// Reset FIX session on logon. +pub struct ResetOnLogon(pub bool); +impl_dictionary_item!(ResetOnLogon); + +/// Reset FIX session on logout. +pub struct ResetOnLogout(pub bool); +impl_dictionary_item!(ResetOnLogout); + +/// Reset FIX session on disconnection. +pub struct ResetOnDisconnect(pub bool); +impl_dictionary_item!(ResetOnDisconnect); + +/// Refresh FIX session on logon. +pub struct RefreshOnLogon(pub bool); +impl_dictionary_item!(RefreshOnLogon); + +/// Built-in HTTP server main port. +pub struct HttpAcceptPort(pub u32); +impl_dictionary_item!(HttpAcceptPort as i32); + +/// Persist FIX messages. +pub struct PersistMessages(pub bool); +impl_dictionary_item!(PersistMessages); + impl DictionaryItem for (&'static str, &str) { fn apply_param(&self, dict: &mut Dictionary) -> Result<(), QuickFixError> { dict.set(self.0, self.1.to_string()) diff --git a/quickfix/tests/test_dictionary_item.rs b/quickfix/tests/test_dictionary_item.rs index 73114b8..db01290 100644 --- a/quickfix/tests/test_dictionary_item.rs +++ b/quickfix/tests/test_dictionary_item.rs @@ -8,14 +8,47 @@ fn test_build() { &SocketAcceptPort(42), &SocketConnectPort(56), &SocketConnectHost("10.8.0.3"), + &SocketConnectSourcePort(69), + &SocketConnectSourceHost("10.8.0.4"), + &SocketReuseAddress(true), + &SocketNodelay(false), + &SocketSendBufferSize(4096), + &SocketReceiveBufferSize(8192), &ReconnectInterval(20), &HeartBtInt(30), + &SendRedundantResendRequests(true), + &SendNextExpectedMsgSeqNum(false), + &UseLocalTime(true), &StartTime("00:00:05"), + &StartDay(DayOfWeek::Monday), &EndTime("23:59:55"), + &EndDay(DayOfWeek::Saturday), + &LogonTime("12:00:00"), + &LogonDay(DayOfWeek::Tuesday), + &LogonTimeout(90), + &LogoutTime("18:00:00"), + &LogoutDay(DayOfWeek::Friday), + &LogoutTimeout(15), &DefaultApplVerID("8"), + &UseDataDictionary(true), &DataDictionary("foo/FIX50.xml"), &TransportDataDictionary("bar/FIXT11.xml"), &FileStorePath("my_store"), + &CheckCompID(true), + &CheckLatency(false), + &MaxLatency(-20), + &ValidateLengthAndChecksum(false), + &ValidateFieldsOutOfOrder(false), + &ValidateFieldsHaveValues(true), + &ValidateUserDefinedFields(true), + &AllowUnknownMsgFields(false), + &PreserveMessageFieldsOrder(true), + &ResetOnLogon(true), + &ResetOnLogout(true), + &ResetOnDisconnect(false), + &RefreshOnLogon(true), + &HttpAcceptPort(9090), + &PersistMessages(false), &("foo", "bar"), ]) .unwrap(); @@ -33,17 +66,43 @@ fn test_build() { dict.get::("ConnectionType").as_deref(), Ok("acceptor") ); - assert_eq!(dict.get::("SocketAcceptPort"), Ok(42)); - assert_eq!(dict.get::("SocketConnectPort"), Ok(56)); + assert_eq!(dict.get("SocketAcceptPort"), Ok(42)); + assert_eq!(dict.get("SocketConnectPort"), Ok(56)); assert_eq!( dict.get::("SocketConnectHost").as_deref(), Ok("10.8.0.3") ); - assert_eq!(dict.get::("ReconnectInterval"), Ok(20)); - assert_eq!(dict.get::("HeartBtInt"), Ok(30)); + assert_eq!(dict.get("SocketConnectSourcePort"), Ok(69)); + assert_eq!( + dict.get::("SocketConnectSourceHost").as_deref(), + Ok("10.8.0.4") + ); + assert_eq!(dict.get("SocketReuseAddress"), Ok(true)); + assert_eq!(dict.get("SocketNodelay"), Ok(false)); + assert_eq!(dict.get("SocketSendBufferSize"), Ok(4096)); + assert_eq!(dict.get("SocketReceiveBufferSize"), Ok(8192)); + + assert_eq!(dict.get("ReconnectInterval"), Ok(20)); + assert_eq!(dict.get("HeartBtInt"), Ok(30)); + + assert_eq!(dict.get("SendRedundantResendRequests"), Ok(true)); + assert_eq!(dict.get("SendNextExpectedMsgSeqNum"), Ok(false)); + + assert_eq!(dict.get("UseLocalTime"), Ok(true)); assert_eq!(dict.get::("StartTime").as_deref(), Ok("00:00:05")); + assert_eq!(dict.get::("StartDay").as_deref(), Ok("MO")); assert_eq!(dict.get::("EndTime").as_deref(), Ok("23:59:55")); + assert_eq!(dict.get::("EndDay").as_deref(), Ok("SA")); + + assert_eq!(dict.get::("LogonTime").as_deref(), Ok("12:00:00")); + assert_eq!(dict.get::("LogonDay").as_deref(), Ok("TU")); + assert_eq!(dict.get("LogonTimeout"), Ok(90)); + assert_eq!(dict.get::("LogoutTime").as_deref(), Ok("18:00:00")); + assert_eq!(dict.get::("LogoutDay").as_deref(), Ok("FR")); + assert_eq!(dict.get("LogoutTimeout"), Ok(15)); + assert_eq!(dict.get::("DefaultApplVerID").as_deref(), Ok("8")); + assert_eq!(dict.get("UseDataDictionary"), Ok(true)); assert_eq!( dict.get::("DataDictionary").as_deref(), Ok("foo/FIX50.xml") @@ -57,4 +116,24 @@ fn test_build() { Ok("my_store") ); assert_eq!(dict.get::("foo").as_deref(), Ok("bar")); + + assert_eq!(dict.get("CheckCompID"), Ok(true)); + assert_eq!(dict.get("CheckLatency"), Ok(false)); + assert_eq!(dict.get("MaxLatency"), Ok(-20)); + assert_eq!(dict.get("ValidateLengthAndChecksum"), Ok(false)); + assert_eq!(dict.get("ValidateFieldsOutOfOrder"), Ok(false)); + assert_eq!(dict.get("ValidateFieldsHaveValues"), Ok(true)); + assert_eq!(dict.get("ValidateUserDefinedFields"), Ok(true)); + assert_eq!(dict.get("AllowUnknownMsgFields"), Ok(false)); + assert_eq!(dict.get("PreserveMessageFieldsOrder"), Ok(true)); + + assert_eq!(dict.get("ResetOnLogon"), Ok(true)); + assert_eq!(dict.get("ResetOnLogout"), Ok(true)); + assert_eq!(dict.get("ResetOnDisconnect"), Ok(false)); + + assert_eq!(dict.get("RefreshOnLogon"), Ok(true)); + + assert_eq!(dict.get("HttpAcceptPort"), Ok(9090)); + + assert_eq!(dict.get("PersistMessages"), Ok(false)); }