1use hashbrown::HashMap;
2
3use crate::{Error, MessageFactory, MessageVisitor, Value, ValueType};
4use crate::Result;
5use crate::utils::bytes::bytes_to_string;
6use crate::utils::stacked::Stacked;
7
8pub struct TextMessageFactory {
10 pub text: String,
11 block_start: bool,
12 dynamic: Vec<bool>,
13}
14
15impl TextMessageFactory {
16 pub fn new() -> Self {
18 Self {
19 text: String::with_capacity(4096),
20 block_start: false,
21 dynamic: Vec::new(),
22 }
23 }
24
25 pub fn reset(&mut self) {
28 self.text.clear();
29 self.block_start = false;
30 self.dynamic.clear();
31 }
32
33 fn delimiter(&mut self) {
34 if !self.block_start {
35 self.text += "|";
36 } else {
37 self.block_start = false;
38 }
39 }
40}
41
42impl MessageFactory for TextMessageFactory {
43 fn start_template(&mut self, _id: u32, name: &str) {
44 self.reset();
45 self.text = format!("{name}=<");
46 self.block_start = true;
47 }
48
49 fn stop_template(&mut self) {
50 self.text += ">";
51 }
52
53 fn set_value(&mut self, _id: u32, name: &str, value: Option<Value>) {
54 if let Some(value) = value {
55 self.delimiter();
56 let value = match value {
57 Value::UInt32(v) => format!("{v}"),
58 Value::Int32(v) => format!("{v}"),
59 Value::UInt64(v) => format!("{v}"),
60 Value::Int64(v) => format!("{v}"),
61 Value::Decimal(v) => v.to_string(),
62 Value::ASCIIString(v) => v.clone(),
63 Value::UnicodeString(v) => v.clone(),
64 Value::Bytes(b) => bytes_to_string(&b),
65 };
66 self.text += &format!("{name}={value}");
67 }
68 }
69
70 fn start_sequence(&mut self, _id: u32, name: &str, _length: u32) {
71 self.delimiter();
72 self.text += &format!("{name}=");
73 }
74
75 fn start_sequence_item(&mut self, _index: u32) {
76 self.text += "<";
77 self.block_start = true;
78 }
79
80 fn stop_sequence_item(&mut self) {
81 self.text += ">";
82 }
83
84 fn stop_sequence(&mut self) {
85 self.block_start = false;
86 }
87
88 fn start_group(&mut self, name: &str) {
89 self.delimiter();
90 self.text += &format!("{name}=<");
91 self.block_start = true;
92 }
93
94 fn stop_group(&mut self) {
95 self.text += ">";
96 self.block_start = false
97 }
98
99 fn start_template_ref(&mut self, name: &str, dynamic: bool) {
100 self.dynamic.push(dynamic);
101 if dynamic {
102 self.delimiter();
103 self.text += &format!("TemplateReference=<{name}=<");
104 self.block_start = true;
105 }
106 }
107
108 fn stop_template_ref(&mut self) {
109 let dynamic = self.dynamic.pop().unwrap();
110 if dynamic {
111 self.text += ">>";
112 }
113 }
114}
115
116
117pub struct JsonMessageFactory {
119 pub json: String,
120 block_start: bool,
121 dynamic: Vec<bool>,
122}
123
124impl JsonMessageFactory {
125 pub fn new() -> Self {
127 Self {
128 json: String::with_capacity(4096),
129 block_start: false,
130 dynamic: Vec::new(),
131 }
132 }
133
134 pub fn reset(&mut self) {
137 self.json.clear();
138 self.block_start = false;
139 self.dynamic.clear();
140 }
141
142 fn delimiter(&mut self) {
143 if !self.block_start {
144 self.json += ",";
145 } else {
146 self.block_start = false;
147 }
148 }
149}
150
151impl MessageFactory for JsonMessageFactory {
152 fn start_template(&mut self, _id: u32, name: &str) {
153 self.reset();
154 self.json = format!("{{\"{name}\":{{");
155 self.block_start = true;
156 }
157
158 fn stop_template(&mut self) {
159 self.json += "}}";
160 }
161
162 fn set_value(&mut self, _id: u32, name: &str, value: Option<Value>) {
163 if let Some(value) = value {
164 self.delimiter();
165 let value = match value {
166 Value::UInt32(v) => format!("{v}"),
167 Value::Int32(v) => format!("{v}"),
168 Value::UInt64(v) => format!("{v}"),
169 Value::Int64(v) => format!("{v}"),
170 Value::Decimal(v) => format!("{v}"),
171 Value::ASCIIString(v) => format!("\"{v}\""),
172 Value::UnicodeString(v) => format!("\"{v}\""),
173 Value::Bytes(b) => bytes_to_string(&b),
174 };
175 self.json += &format!("\"{name}\":{value}");
176 }
177 }
178
179 fn start_sequence(&mut self, _id: u32, name: &str, _length: u32) {
180 self.delimiter();
181 self.json += &format!("\"{name}\":[");
182 self.block_start = true;
183 }
184
185 fn start_sequence_item(&mut self, _index: u32) {
186 self.delimiter();
187 self.json += "{";
188 self.block_start = true;
189 }
190
191 fn stop_sequence_item(&mut self) {
192 self.json += "}";
193 }
194
195 fn stop_sequence(&mut self) {
196 self.json += "]";
197 self.block_start = false;
198 }
199
200 fn start_group(&mut self, name: &str) {
201 self.delimiter();
202 self.json += &format!("\"{name}\":{{");
203 self.block_start = true;
204 }
205
206 fn stop_group(&mut self) {
207 self.json += "}";
208 self.block_start = false
209 }
210
211 fn start_template_ref(&mut self, name: &str, dynamic: bool) {
212 self.dynamic.push(dynamic);
213 if dynamic {
214 self.delimiter();
215 self.json += &format!("\"TemplateReference\":{{\"{name}\":{{");
216 self.block_start = true;
217 }
218 }
219
220 fn stop_template_ref(&mut self) {
221 let dynamic = self.dynamic.pop().unwrap();
222 if dynamic {
223 self.json += "}}";
224 }
225 }
226}
227
228
229pub struct TextMessageVisitor {
230 pub data: TextMessageValue,
231 context: Stacked<*const TextMessageValue>,
232 group_as_seq: Stacked<bool>,
233}
234
235impl TextMessageVisitor {
236 pub fn from_text(text: &str) -> Result<Self> {
237 Ok(Self {
238 data: TextMessageValue::from_text(text)?,
239 context: Stacked::new_empty(),
240 group_as_seq: Stacked::new_empty(),
241 })
242 }
243}
244
245impl MessageVisitor for TextMessageVisitor {
246 fn get_template_name(&mut self) -> Result<String> {
247 match &self.data {
248 TextMessageValue::Group(h) => {
249 match h.iter().next() {
250 None => Err(Error::Runtime("Template name not fount".to_string())),
251 Some((name, value)) => {
252 self.context.push(value);
253 Ok(name.clone())
254 }
255 }
256 }
257 _ => {
258 Err(Error::Runtime(format!("Template value expected to be TextMessageValue::Group, got {:?}", self.data)))
259 }
260 }
261 }
262
263 fn get_value(&mut self, name: &str, type_: &ValueType) -> Result<Option<Value>> {
264 let ctx = unsafe { self.context.must_peek().as_ref().unwrap() };
266 match ctx {
267 TextMessageValue::Group(context) => {
268 if let Some(v) = context.get(name) {
269 match v {
270 TextMessageValue::Value(s) => {
271 let mut value = type_.to_default_value()?;
272 value.set_from_string(s)?;
273 Ok(Some(value))
274 }
275 _ => {
276 Err(Error::Runtime(format!("Field {name} expected to be TextMessageValue::Value, got {:?}", v)))
277 }
278 }
279 } else {
280 Ok(None)
281 }
282 }
283 _ => unreachable!()
284 }
285 }
286
287 fn select_group(&mut self, name: &str) -> Result<bool> {
288 let ctx = unsafe { self.context.must_peek().as_ref().unwrap() };
290 match ctx {
291 TextMessageValue::Group(context) => {
292 if let Some(v) = context.get(name) {
293 match v {
294 TextMessageValue::Group(_) => {
295 self.context.push(v);
296 Ok(true)
297 }
298 _ => {
299 Err(Error::Runtime(format!("Field {name} expected to be TextMessageValue::Group, got {:?}", v)))
300 }
301 }
302 } else {
303 Ok(false)
304 }
305 }
306 _ => unreachable!()
307 }
308 }
309
310 fn release_group(&mut self) -> Result<()> {
311 self.context.pop();
312 Ok(())
313 }
314
315 fn select_sequence(&mut self, name: &str) -> Result<Option<usize>> {
316 let ctx = unsafe { self.context.must_peek().as_ref().unwrap() };
318 match ctx {
319 TextMessageValue::Group(context) => {
320 if let Some(v) = context.get(name) {
321 match v {
322 TextMessageValue::Group(_) => {
323 self.group_as_seq.push(true);
324 self.context.push(v);
325 Ok(Some(1))
326 }
327 TextMessageValue::Sequence(s) => {
328 let len = s.len();
329 self.group_as_seq.push(false);
330 self.context.push(v);
331 Ok(Some(len))
332 }
333 _ => {
334 Err(Error::Runtime(format!("Field {name} expected to be TextMessageValue::Sequence, got {:?}", v)))
335 }
336 }
337 } else {
338 Ok(None)
339 }
340 }
341 _ => unreachable!()
342 }
343 }
344
345 fn select_sequence_item(&mut self, index: usize) -> Result<()> {
346 if *self.group_as_seq.must_peek() {
347 return if index == 0 {
349 Ok(())
350 } else {
351 Err(Error::Runtime("Index is out of range".to_string()))
352 }
353 }
354 let ctx = unsafe { self.context.must_peek().as_ref().unwrap() };
356 match ctx {
357 TextMessageValue::Sequence(sequence) => {
358 if let Some(v) = sequence.get(index) {
359 match v {
360 TextMessageValue::Group(_) => {
361 self.context.push(v);
362 Ok(())
363 }
364 _ => {
365 Err(Error::Runtime(format!("Sequence item #{index} expected to be TextMessageValue::Group, got {:?}", v)))
366 }
367 }
368
369 } else {
370 return Err(Error::Runtime(format!("Index {} is out of range", index)));
371 }
372 }
373 _ => unreachable!()
374 }
375 }
376
377 fn release_sequence_item(&mut self) -> Result<()> {
378 self.context.pop();
379 Ok(())
380 }
381
382 fn release_sequence(&mut self) -> Result<()> {
383 if !self.group_as_seq.pop().unwrap() {
384 self.context.pop();
385 }
386 Ok(())
387 }
388
389 fn select_template_ref(&mut self, _name: &str, dynamic: bool) -> Result<Option<String>> {
390 if dynamic {
391 todo!()
392 } else {
393 Ok(None)
395 }
396 }
397
398 fn release_template_ref(&mut self) -> Result<()> {
399 Ok(())
400 }
401}
402
403#[derive(Debug, PartialEq)]
404pub enum TextMessageValue {
405 Value(String),
406 Group(HashMap<String, TextMessageValue>),
407 Sequence(Vec<TextMessageValue>),
408}
409
410impl TextMessageValue {
411 fn from_text(text: &str) -> Result<Self> {
412 return match TextMessageValue::parse_next(text)? {
413 (name, TextMessageValue::Group(value), size) => {
414 if size != text.len() {
415 Err(Error::Dynamic("Symbols left in buffer after parsing text message".to_string()))
416 } else {
417 Ok(TextMessageValue::Group(
418 HashMap::from([
419 (name, TextMessageValue::Group(value))
420 ])
421 ))
422 }
423 }
424 _ => Err(Error::Dynamic("Failed to parse message body".to_string())),
425 };
426 }
427
428 fn parse_next(text: &str) -> Result<(String, Self, usize)> {
429 let (name, rest) = text.split_once('=')
430 .ok_or_else(|| Error::Dynamic("Failed to parse next field".to_string()))?;
431 let (value, sz) = TextMessageValue::parse_value(rest)?;
432 let size = name.len() + sz + 1;
433 Ok((name.to_string(), value, size))
434 }
435
436 fn parse_value(mut text: &str) -> Result<(Self, usize)> {
437 if text.starts_with('<') {
438 let mut size = 0;
440 let mut value: Option<TextMessageValue> = None;
441 loop {
442 let (v, s) = TextMessageValue::parse_group(&text[1..])?;
443 size += s + 1;
444 text = &text[s + 1..];
445 match &mut value {
446 None => {
447 value = Some(v);
448 }
449 Some(TextMessageValue::Group(_)) => {
450 let mut seq = Vec::with_capacity(2);
451 seq.push(value.unwrap());
452 seq.push(v);
453 value = Some(TextMessageValue::Sequence(seq));
454 }
455 Some(TextMessageValue::Sequence(s)) => {
456 s.push(v);
457 }
458 _ => unreachable!(),
459 }
460 if text.starts_with('<') {
461 continue
462 }
463 break
464 }
465 Ok((value.unwrap(), size))
466 } else {
467 let i = text.find(|c: char| c == '|' || c == '>')
468 .ok_or_else(|| Error::Dynamic("Failed to parse next value (no delimiter)".to_string()))?;
469 Ok((TextMessageValue::Value(text[..i].to_string()), i))
470 }
471 }
472
473 fn parse_group(mut text: &str) -> Result<(Self, usize)> {
474 let mut size = 0;
475 let mut value: HashMap<String, TextMessageValue> = HashMap::new();
476 loop {
477 let (name, v, sz) = TextMessageValue::parse_next(text)?;
478 size += sz;
479 text = &text[sz..];
480 value.insert(name, v);
481
482 if text.starts_with('|') {
483 size += 1;
484 text = &text[1..];
485 continue
486 }
487 if text.starts_with('>') {
488 size += 1;
489 break
490 }
491 return Err(Error::Dynamic("Failed to parse group".to_string()));
492 }
493 Ok((TextMessageValue::Group(value), size))
494 }
495}
496
497#[cfg(test)]
498mod tests {
499 use super::*;
500
501 #[test]
502 fn test_parse_text_group() {
503 let (value, size) = TextMessageValue::parse_group("MessageType=0|ApplVerID=8>|").unwrap();
504 assert_eq!(value, TextMessageValue::Group(HashMap::from([
505 ("MessageType".to_string(), TextMessageValue::Value("0".to_string())),
506 ("ApplVerID".to_string(), TextMessageValue::Value("8".to_string())),
507 ])));
508 assert_eq!(size, 26);
509 }
510
511 #[test]
512 fn test_parse_text_value() {
513 let (value, size) = TextMessageValue::parse_value("CQG|").unwrap();
514 assert_eq!(value, TextMessageValue::Value("CQG".to_string()));
515 assert_eq!(size, 3);
516
517 let (value, size) = TextMessageValue::parse_value("<MessageType=0>|").unwrap();
518 assert_eq!(value, TextMessageValue::Group(HashMap::from([
519 ("MessageType".to_string(), TextMessageValue::Value("0".to_string()))
520 ])));
521 assert_eq!(size, 15);
522
523 let (value, size) = TextMessageValue::parse_value("<MessageType=0><MessageType=1>|").unwrap();
524 assert_eq!(value, TextMessageValue::Sequence(vec![
525 TextMessageValue::Group(HashMap::from([
526 ("MessageType".to_string(), TextMessageValue::Value("0".to_string()))
527 ])),
528 TextMessageValue::Group(HashMap::from([
529 ("MessageType".to_string(), TextMessageValue::Value("1".to_string()))
530 ])),
531 ]));
532 assert_eq!(size, 30);
533 }
534
535 #[test]
536 fn test_parse_test_message() {
537 let m = TextMessageValue::from_text(
538 "MDHeartbeat=<MessageType=0|ApplVerID=8|SenderCompID=CQG|MsgSeqNum=2286|SendingTime=20240712171046052>"
539 ).unwrap();
540 let r = TextMessageValue::Group(HashMap::from([
541 (
542 "MDHeartbeat".to_string(),
543 TextMessageValue::Group(HashMap::from([
544 (
545 "MessageType".to_string(),
546 TextMessageValue::Value("0".to_string())
547 ), (
548 "ApplVerID".to_string(),
549 TextMessageValue::Value("8".to_string())
550 ), (
551 "SenderCompID".to_string(),
552 TextMessageValue::Value("CQG".to_string())
553 ), (
554 "MsgSeqNum".to_string(),
555 TextMessageValue::Value("2286".to_string())
556 ), (
557 "SendingTime".to_string(),
558 TextMessageValue::Value("20240712171046052".to_string())
559 ),
560 ]))
561 )
562 ]));
563 assert_eq!(m, r);
564 }
565}