1use hotfix_message::error::EncodingError as EncodeError;
3pub use hotfix_message::field_types::Timestamp;
4pub(crate) use hotfix_message::message::{Config, Message};
5use hotfix_message::session_fields::{
6 MSG_SEQ_NUM, ORIG_SENDING_TIME, POSS_DUP_FLAG, SENDER_COMP_ID, SENDING_TIME, TARGET_COMP_ID,
7};
8pub use hotfix_message::{Part, RepeatingGroup};
9
10pub mod business_reject;
11pub mod heartbeat;
12pub mod logon;
13pub mod logout;
14pub mod parser;
15pub mod reject;
16pub mod resend_request;
17pub mod sequence_reset;
18pub mod test_request;
19pub mod verification;
20pub mod verification_issue;
21
22pub use parser::RawFixMessage;
23pub use resend_request::ResendRequest;
24
25use heartbeat::Heartbeat;
26use logon::Logon;
27use logout::Logout;
28use reject::Reject;
29use sequence_reset::SequenceReset;
30use test_request::TestRequest;
31
32static ADMIN_TYPES: [&str; 7] = [
33 Logon::MSG_TYPE,
34 Heartbeat::MSG_TYPE,
35 TestRequest::MSG_TYPE,
36 ResendRequest::MSG_TYPE,
37 Reject::MSG_TYPE,
38 SequenceReset::MSG_TYPE,
39 Logout::MSG_TYPE,
40];
41
42pub fn is_admin(message_type: &str) -> bool {
43 ADMIN_TYPES.contains(&message_type)
44}
45
46pub trait OutboundMessage: Clone + Send + 'static {
47 fn write(&self, msg: &mut Message);
48
49 fn message_type(&self) -> &str;
50}
51
52pub fn prepare_message_for_resend(msg: &mut Message) -> Result<(), &'static str> {
62 let header = msg.header_mut();
63
64 if header.get_raw(SENDING_TIME).is_none() {
65 return Err("Missing SendingTime (52)");
66 }
67
68 let already_poss_dup = header.get::<bool>(POSS_DUP_FLAG).unwrap_or(false);
69 let has_orig_sending_time = header.get_raw(ORIG_SENDING_TIME).is_some();
70
71 if already_poss_dup && has_orig_sending_time {
72 return if header.pop(SENDING_TIME).is_some() {
74 header.set(SENDING_TIME, Timestamp::utc_now());
75 Ok(())
76 } else {
77 Err("Failed to extract previous SendingTime")
78 };
79 }
80
81 if let Some(original_sending_time_field) = header.pop(SENDING_TIME) {
83 let original_ts = Timestamp::parse(&original_sending_time_field.data)
84 .ok_or("Invalid original SendingTime format")?;
85 header.set(ORIG_SENDING_TIME, original_ts);
86 header.set(SENDING_TIME, Timestamp::utc_now());
87 header.set(POSS_DUP_FLAG, true);
88 Ok(())
89 } else {
90 Err("Failed to extract original SendingTime")
91 }
92}
93
94pub fn generate_message(
95 begin_string: &str,
96 sender_comp_id: &str,
97 target_comp_id: &str,
98 msg_seq_num: u64,
99 message: impl OutboundMessage,
100) -> Result<Vec<u8>, EncodeError> {
101 let mut msg = Message::new(begin_string, message.message_type());
102 msg.set(SENDER_COMP_ID, sender_comp_id);
103 msg.set(TARGET_COMP_ID, target_comp_id.as_bytes());
104 msg.set(MSG_SEQ_NUM, msg_seq_num);
105 msg.set(SENDING_TIME, Timestamp::utc_now());
106
107 message.write(&mut msg);
108
109 msg.encode(&Config::default())
110}