quickfix_spec_parser/
lib.rs

1#![warn(missing_docs)]
2
3/*! FIX XML file spec parser.
4 *
5 * Allow reading official FIX XML dictionary and convert it to a struct / enum model.
6 *
7 * **NOTE** This crate is not a code generator. It only help having a clear representation of what FIX dictionary are.
8 */
9
10use std::io;
11
12use quick_xml::{events::Event, Reader, Writer};
13
14mod error;
15mod model {
16    mod component;
17    mod component_spec;
18    mod field;
19    mod field_allowed_value;
20    mod field_spec;
21    mod field_type;
22    mod field_value;
23    mod group;
24    mod message;
25    mod message_category;
26    mod spec;
27
28    pub use self::component::Component;
29    pub use self::component_spec::ComponentSpec;
30    pub use self::field::Field;
31    pub use self::field_allowed_value::FieldAllowedValue;
32    pub use self::field_spec::FieldSpec;
33    pub use self::field_type::FieldType;
34    pub use self::field_value::FieldValue;
35    pub use self::group::Group;
36    pub use self::message::Message;
37    pub use self::message_category::MessageCategory;
38    pub use self::spec::FixSpec;
39}
40mod xml_ext;
41
42pub use error::*;
43pub use model::*;
44use xml_ext::*;
45
46#[doc(hidden)] // For testing
47pub use xml_ext::read_attribute;
48
49type XmlWriter = Writer<Vec<u8>>;
50type XmlReader<'a> = Reader<&'a [u8]>;
51
52/// Try converting byte array into a FIX spec tree.
53pub fn parse_spec(input: &[u8]) -> Result<FixSpec, FixSpecError> {
54    let mut reader = Reader::from_reader(input);
55    reader.config_mut().trim_text(true);
56
57    match reader.read_event()? {
58        // If we are at start of FIX spec.
59        Event::Start(e) if e.name().as_ref() == FixSpec::TAG_NAME.as_bytes() => {
60            FixSpec::parse_xml_tree(&e, &mut reader)
61        }
62        // Otherwise document is invalid
63        _ => Err(FixSpecError::InvalidDocument("invalid root")),
64    }
65}
66
67/// Convert FIX spec tree into a byte array.
68pub fn write_spec(spec: &FixSpec) -> io::Result<Vec<u8>> {
69    let mut writer = Writer::new_with_indent(Vec::new(), b' ', 1);
70
71    spec.write_xml(&mut writer)?;
72
73    Ok(writer.into_inner())
74}