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 bytes::Bytes;
13use quick_xml::{events::Event, Reader, Writer};
14
15mod error;
16mod model {
17    mod component;
18    mod component_spec;
19    mod field;
20    mod field_allowed_value;
21    mod field_spec;
22    mod field_type;
23    mod field_value;
24    mod group;
25    mod message;
26    mod message_category;
27    mod spec;
28
29    pub use self::component::Component;
30    pub use self::component_spec::ComponentSpec;
31    pub use self::field::Field;
32    pub use self::field_allowed_value::FieldAllowedValue;
33    pub use self::field_spec::FieldSpec;
34    pub use self::field_type::FieldType;
35    pub use self::field_value::FieldValue;
36    pub use self::group::Group;
37    pub use self::message::Message;
38    pub use self::message_category::MessageCategory;
39    pub use self::spec::FixSpec;
40}
41mod xml_ext;
42
43pub use error::*;
44pub use model::*;
45use xml_ext::*;
46
47#[doc(hidden)] // For testing
48pub use xml_ext::read_attribute;
49
50type XmlWriter = Writer<Vec<u8>>;
51type XmlReader<'a> = Reader<&'a [u8]>;
52
53/// Try converting byte array into a FIX spec tree.
54pub fn parse_spec(input: &[u8]) -> Result<FixSpec, FixSpecError> {
55    let mut reader = Reader::from_reader(input);
56    reader.config_mut().trim_text(true);
57
58    match reader.read_event()? {
59        // If we are at start of FIX spec.
60        Event::Start(e) if e.name().as_ref() == FixSpec::TAG_NAME.as_bytes() => {
61            FixSpec::parse_xml_tree(&e, &mut reader)
62        }
63        // Otherwise document is invalid
64        _ => Err(FixSpecError::InvalidDocument("invalid root")),
65    }
66}
67
68/// Convert FIX spec tree into a byte array.
69pub fn write_spec(spec: &FixSpec) -> io::Result<Bytes> {
70    let mut writer = Writer::new_with_indent(Vec::new(), b' ', 1);
71
72    spec.write_xml(&mut writer)?;
73
74    Ok(Bytes::from(writer.into_inner()))
75}