1use crate::app::slr;
4use crate::app::TsrMessageRef;
5use std::collections::BTreeMap;
6use std::time::SystemTime;
7
8#[derive(Clone, Debug, PartialEq)]
10pub enum FixFieldValue {
11 Int(i64),
12 Float(f64),
13 Char(char),
14 String(String),
15 Data(Vec<u8>),
16 Group(Vec<BTreeMap<i64, FixFieldValue>>),
17}
18
19impl From<i64> for FixFieldValue {
20 fn from(v: i64) -> Self {
21 FixFieldValue::Int(v)
22 }
23}
24
25impl From<String> for FixFieldValue {
26 fn from(v: String) -> Self {
27 FixFieldValue::String(v)
28 }
29}
30
31impl From<f64> for FixFieldValue {
32 fn from(v: f64) -> Self {
33 FixFieldValue::Float(v)
34 }
35}
36
37impl From<(u8, u16)> for FixFieldValue {
38 fn from(v: (u8, u16)) -> Self {
39 FixFieldValue::Int(((v.0 as i64) << 16) + (v.1 as i64))
40 }
41}
42
43impl From<char> for FixFieldValue {
44 fn from(v: char) -> Self {
45 FixFieldValue::Char(v)
46 }
47}
48
49impl From<usize> for FixFieldValue {
50 fn from(v: usize) -> Self {
51 FixFieldValue::Int(v as i64)
52 }
53}
54
55impl From<Vec<u8>> for FixFieldValue {
56 fn from(v: Vec<u8>) -> Self {
57 FixFieldValue::Data(v)
58 }
59}
60
61impl From<bool> for FixFieldValue {
62 fn from(v: bool) -> Self {
63 FixFieldValue::Char(if v { 't' } else { 'f' })
64 }
65}
66
67impl From<u8> for FixFieldValue {
68 fn from(v: u8) -> Self {
69 FixFieldValue::Int(v.into())
70 }
71}
72
73impl From<SystemTime> for FixFieldValue {
74 fn from(v: SystemTime) -> Self {
75 FixFieldValue::Int(v.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64)
76 }
77}
78
79#[derive(Debug, Clone, PartialEq)]
80pub struct Field {
81 tag: i64,
82 value: FixFieldValue,
83}
84
85impl Field {
86 pub fn new(tag: u32, value: FixFieldValue) -> Self {
88 Self { tag: tag as i64, value }
89 }
90
91 pub fn tag(&self) -> i64 {
93 self.tag
94 }
95
96 pub fn value(&self) -> &FixFieldValue {
98 &self.value
99 }
100}
101
102#[derive(Debug, Clone, Default, PartialEq)]
104pub struct Message {
105 pub fields: BTreeMap<i64, FixFieldValue>,
106}
107
108#[derive(Debug, Clone, Default, PartialEq)]
109pub struct PushyMessage {
110 fields: Vec<(u32, FixFieldValue)>,
111}
112
113impl TsrMessageRef for PushyMessage {
114 fn set_field(&mut self, msg_type: u32, val: slr::FixFieldValue) {
115 PushyMessage::add_field(self, msg_type, val)
116 }
117
118 fn get_field(&self, msg_type: u32) -> Option<&slr::FixFieldValue> {
119 PushyMessage::get_field(self, msg_type)
120 }
121}
122
123impl PushyMessage {
124 pub fn new() -> Self {
126 Self {
127 fields: Vec::new(),
128 }
129 }
130
131 pub fn add_field<K: Into<u32>>(&mut self, tag: K, value: slr::FixFieldValue) {
133 self.fields.push((tag.into(), value));
134 }
135
136 pub fn add_str<K: Into<u32>, S: Into<String>>(&mut self, tag: K, value: S) {
138 self.add_field(tag, slr::FixFieldValue::String(value.into()))
139 }
140
141 pub fn add_int<K: Into<u32>>(&mut self, tag: K, value: i64) {
143 self.add_field(tag, slr::FixFieldValue::Int(value))
144 }
145
146 pub fn get_field<K: Into<u32>>(&self, tag: K) -> Option<&slr::FixFieldValue> {
147 let tag = tag.into();
148 let index = self.fields.iter().position(|(t, _)| *t == tag);
149 index.map(|i| &self.fields[i].1)
150 }
151
152 pub fn msg_type(&self) -> Option<&str> {
153 match self.get_field(35u32) {
154 Some(FixFieldValue::String(s)) => Some(s.as_str()),
155 _ => None,
156 }
157 }
158
159 pub fn seq_num(&self) -> Option<u64> {
160 match self.get_field(34u32) {
161 Some(FixFieldValue::Int(n)) => Some(*n as u64),
162 _ => None,
163 }
164 }
165
166 pub fn test_indicator(&self) -> Option<bool> {
167 match self.get_field(464u32) {
168 Some(FixFieldValue::Char('Y')) => Some(true),
169 Some(FixFieldValue::Char('N')) => Some(false),
170 _ => Some(false),
171 }
172 }
173}
174
175impl TsrMessageRef for Message {
176 fn get_field(&self, msg_type: u32) -> Option<&slr::FixFieldValue> {
177 self.fields.get(&(msg_type as i64))
178 }
179
180 fn set_field(&mut self, msg_type: u32, val: slr::FixFieldValue) {
181 self.fields.insert(msg_type as i64, val);
182 }
183}
184
185impl<'a> Iterator for &'a Message {
186 type Item = slr::FixFieldValue;
187
188 fn next(&mut self) -> Option<Self::Item> {
189 None
190 }
191}
192
193impl Message {
194 pub fn new() -> Self {
196 Message {
197 fields: BTreeMap::new(),
198 }
199 }
200
201 pub fn add_field<K: Into<i64>>(&mut self, tag: K, value: slr::FixFieldValue) {
203 self.fields.insert(tag.into(), value);
204 }
205
206 pub fn add_str<K: Into<i64>, S: Into<String>>(&mut self, tag: K, value: S) {
208 self.add_field(tag, slr::FixFieldValue::String(value.into()))
209 }
210
211 pub fn add_int<K: Into<i64>>(&mut self, tag: K, value: i64) {
213 self.add_field(tag, slr::FixFieldValue::Int(value))
214 }
215
216 pub fn get_field<K: Into<i64>>(&self, tag: K) -> Option<&slr::FixFieldValue> {
217 self.fields.get(&tag.into())
218 }
219
220 pub fn msg_type(&self) -> Option<&str> {
221 match self.fields.get(&35) {
222 Some(FixFieldValue::String(s)) => Some(s.as_str()),
223 _ => None,
224 }
225 }
226
227 pub fn seq_num(&self) -> Option<u64> {
228 match self.fields.get(&34) {
229 Some(FixFieldValue::Int(n)) => Some(*n as u64),
230 _ => None,
231 }
232 }
233
234 pub fn test_indicator(&self) -> Option<bool> {
235 match self.fields.get(&464) {
236 Some(FixFieldValue::Char('Y')) => Some(true),
237 Some(FixFieldValue::Char('N')) => Some(false),
238 _ => Some(false),
239 }
240 }
241}