1use crate::error::EncodeError;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub enum MessageType {
10 NewOrderSingle,
11 ExecutionReport,
12 MarketDataRequest,
13 Heartbeat,
14 Custom(u8),
15}
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19pub enum FieldValue {
20 String(String),
21 Integer(i64),
22 Decimal(f64),
23 Boolean(bool),
24}
25
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
28pub struct FixmlMessage {
29 pub message_type: MessageType,
30 pub fields: HashMap<String, FieldValue>,
31}
32
33impl FixmlMessage {
34 pub fn new(message_type: MessageType) -> Self {
35 Self {
36 message_type,
37 fields: HashMap::new(),
38 }
39 }
40
41 pub fn new_order_single(symbol: String, price: f64, qty: f64, side: String) -> Self {
42 let mut message = Self::new(MessageType::NewOrderSingle);
43 message.set_field("Symbol", FieldValue::String(symbol));
44 message.set_field("Price", FieldValue::Decimal(price));
45 message.set_field("OrderQty", FieldValue::Decimal(qty));
46 message.set_field("Side", FieldValue::String(side));
47 message.set_field("OrdType", FieldValue::String("2".to_string())); message
49 }
50
51 pub fn set_field(&mut self, name: &str, value: FieldValue) {
52 self.fields.insert(name.to_string(), value);
53 }
54
55 pub fn get_field(&self, name: &str) -> Option<&FieldValue> {
56 self.fields.get(name)
57 }
58
59 pub fn validate(&self) -> Result<(), EncodeError> {
60 if self.message_type == MessageType::NewOrderSingle {
61 self.require_field("Symbol")?;
62 self.require_field("Side")?;
63 self.require_field("OrderQty")?;
64 self.require_field("OrdType")?;
65 }
66 Ok(())
67 }
68
69 fn require_field(&self, name: &str) -> Result<(), EncodeError> {
70 if !self.fields.contains_key(name) {
71 return Err(EncodeError::MissingRequiredField {
72 field_name: name.to_string(),
73 });
74 }
75 Ok(())
76 }
77}