rusty_ems/fix_protocol.rs
1use anyhow::Result;
2use fefix::tagvalue::{Config, Decoder};
3
4/// Encodes a FIX 4.4 New Order Single message
5///
6/// This function creates a simple FIX 4.4 message for placing a new order.
7/// In production, this should be replaced with a proper FIX library with
8/// dictionary support and proper message validation.
9///
10/// # Arguments
11///
12/// * `order_id` - Client order ID
13/// * `symbol` - Trading symbol
14/// * `side` - Order side ('1' for buy, '2' for sell)
15/// * `order_qty` - Order quantity
16/// * `price` - Order price
17///
18/// # Returns
19///
20/// Returns a byte vector containing the FIX message
21#[must_use]
22pub fn encode_new_order_single_fix44(
23 order_id: &str,
24 symbol: &str,
25 side: char,
26 order_qty: f64,
27 price: f64,
28) -> Vec<u8> {
29 // Simple FIX message encoding (for testing purposes only)
30 // In production, use a proper FIX library with dictionary support
31 let time_str = rusty_common::time::format_current_time_fix();
32 let msg = format!(
33 "8=FIX.4.4\u{0001}35=D\u{0001}11={order_id}\u{0001}21=1\u{0001}55={symbol}\u{0001}54={side}\u{0001}60={time_str}\u{0001}38={order_qty}\u{0001}40=2\u{0001}44={price}\u{0001}59=0\u{0001}"
34 );
35 msg.into_bytes()
36}
37
38/// Decodes a FIX message into field tag-value pairs
39///
40/// This function parses a FIX message and extracts the field tags and values.
41/// It uses the FIX 4.4 dictionary to parse the message structure.
42///
43/// # Arguments
44///
45/// * `message` - The FIX message bytes to decode
46///
47/// # Returns
48///
49/// Returns a vector of tuples containing (tag, value) pairs, or an error if parsing fails
50///
51/// # Errors
52///
53/// Returns an error if the message cannot be parsed as a valid FIX message
54pub fn decode_fix_message(message: &[u8]) -> Result<Vec<(u32, String)>> {
55 let dict = fefix::dict::Dictionary::fix44();
56 let mut decoder = Decoder::<Config>::new(dict);
57 let msg = decoder.decode(message)?;
58 let mut fields = Vec::new();
59 for (tag, value) in msg.fields() {
60 fields.push((
61 u32::from(tag.get()),
62 String::from_utf8_lossy(value).to_string(),
63 ));
64 }
65 Ok(fields)
66}