quickfix_spec_parser/model/
spec.rs1use std::io;
2
3use quick_xml::events::{BytesStart, Event};
4
5use crate::{
6 parse_xml_list, read_attribute, write_xml_container, ComponentSpec, FieldSpec, FieldValue,
7 FixSpecError, XmlObject, XmlReadable, XmlReader, XmlWritable, XmlWriter,
8};
9
10use super::message::Message;
11
12#[derive(Debug, Clone)]
14pub struct FixSpec {
15 pub version: (u8, u8, u8),
17 pub is_fixt: bool,
19 pub headers: Vec<FieldValue>,
21 pub messages: Vec<Message>,
23 pub trailers: Vec<FieldValue>,
25 pub component_specs: Vec<ComponentSpec>,
27 pub field_specs: Vec<FieldSpec>,
29}
30
31impl FixSpec {
32 pub fn new_fixt() -> Self {
34 Self {
35 version: (1, 1, 0),
36 is_fixt: true,
37 headers: vec![],
38 messages: vec![],
39 trailers: vec![],
40 component_specs: vec![],
41 field_specs: vec![],
42 }
43 }
44}
45
46impl XmlObject for FixSpec {
47 const TAG_NAME: &'static str = "fix";
48}
49
50impl XmlReadable for FixSpec {
51 fn parse_xml_node(element: &BytesStart) -> Result<Self, FixSpecError> {
52 let version = (
53 read_attribute(element, "major")?.parse()?,
54 read_attribute(element, "minor")?.parse()?,
55 read_attribute(element, "servicepack")?.parse()?,
56 );
57
58 let is_fixt = read_attribute(element, "type")? == "FIXT";
59
60 Ok(Self {
61 version,
62 is_fixt,
63 headers: Vec::new(),
64 messages: Vec::new(),
65 trailers: Vec::new(),
66 component_specs: Vec::new(),
67 field_specs: Vec::new(),
68 })
69 }
70
71 fn parse_xml_tree(element: &BytesStart, reader: &mut XmlReader) -> Result<Self, FixSpecError> {
72 let mut output = Self::parse_xml_node(element)?;
73
74 loop {
75 match reader.read_event()? {
76 Event::Start(element) => match element.name().as_ref() {
77 b"header" => output.headers = FieldValue::parse_xml_tree(reader, "header")?,
78 b"messages" => output.messages = parse_xml_list(reader, "messages")?,
79 b"trailer" => output.trailers = FieldValue::parse_xml_tree(reader, "trailer")?,
80 b"components" => output.component_specs = parse_xml_list(reader, "components")?,
81 b"fields" => output.field_specs = parse_xml_list(reader, "fields")?,
82 _ => {}
83 },
84 Event::End(element) if element.name().as_ref() == Self::TAG_NAME.as_bytes() => {
85 break
86 }
87 _ => {}
88 }
89 }
90
91 Ok(output)
92 }
93}
94
95impl XmlWritable for FixSpec {
96 fn write_xml<'a>(&self, writer: &'a mut XmlWriter) -> io::Result<&'a mut XmlWriter> {
97 writer
98 .create_element(Self::TAG_NAME)
99 .with_attribute(("type", if self.is_fixt { "FIXT" } else { "FIX" }))
100 .with_attribute(("major", self.version.0.to_string().as_str()))
101 .with_attribute(("minor", self.version.1.to_string().as_str()))
102 .with_attribute(("servicepack", self.version.2.to_string().as_str()))
103 .write_inner_content(|writer| {
104 write_xml_container(writer, "header", &self.headers)?;
105 write_xml_container(writer, "messages", &self.messages)?;
106 write_xml_container(writer, "trailer", &self.trailers)?;
107 write_xml_container(writer, "components", &self.component_specs)?;
108 write_xml_container(writer, "fields", &self.field_specs)?;
109 Ok(())
110 })
111 }
112}