quickfix_spec_parser/model/
spec.rs

1use 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/// XML FIX dictionary description.
13#[derive(Debug, Clone)]
14pub struct FixSpec {
15    /// FIX version number.
16    pub version: (u8, u8, u8),
17    /// Is FIXT ?
18    pub is_fixt: bool,
19    /// Message shared headers.
20    pub headers: Vec<FieldValue>,
21    /// Known FIX messages.
22    pub messages: Vec<Message>,
23    /// Message shared trailers.
24    pub trailers: Vec<FieldValue>,
25    /// Factorized components specs.
26    pub component_specs: Vec<ComponentSpec>,
27    /// Regular fields specs.
28    pub field_specs: Vec<FieldSpec>,
29}
30
31impl FixSpec {
32    /// Generate a new empty FIXT spec.
33    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}