hotfix_dictionary/
dictionary.rs1use crate::{Component, ComponentData, Datatype, DatatypeData, Field, FieldData};
2
3use crate::message_definition::{MessageData, MessageDefinition};
4use crate::quickfix::{ParseDictionaryError, QuickFixReader};
5use crate::string::SmartString;
6use fnv::FnvHashMap;
7
8#[derive(Debug, Clone)]
25pub struct Dictionary {
26 pub(crate) version: String,
27
28 pub(crate) data_types_by_name: FnvHashMap<SmartString, DatatypeData>,
29
30 pub(crate) fields_by_tags: FnvHashMap<u32, FieldData>,
31 pub(crate) field_tags_by_name: FnvHashMap<SmartString, u32>,
32
33 pub(crate) components_by_name: FnvHashMap<SmartString, ComponentData>,
34
35 pub(crate) messages_by_msgtype: FnvHashMap<SmartString, MessageData>,
36 pub(crate) message_msgtypes_by_name: FnvHashMap<SmartString, SmartString>,
37}
38
39impl Dictionary {
40 pub fn new<S: ToString>(version: S) -> Self {
42 Dictionary {
43 version: version.to_string(),
44 data_types_by_name: FnvHashMap::default(),
45 fields_by_tags: FnvHashMap::default(),
46 field_tags_by_name: FnvHashMap::default(),
47 components_by_name: FnvHashMap::default(),
48 messages_by_msgtype: FnvHashMap::default(),
49 message_msgtypes_by_name: FnvHashMap::default(),
50 }
51 }
52
53 pub fn from_quickfix_spec(input: &str) -> Result<Self, ParseDictionaryError> {
56 let xml_document =
57 roxmltree::Document::parse(input).map_err(|_| ParseDictionaryError::InvalidFormat)?;
58 QuickFixReader::new(&xml_document)
59 }
60
61 pub fn version(&self) -> &str {
71 self.version.as_str()
72 }
73
74 pub fn load_from_file(path: &str) -> Result<Self, ParseDictionaryError> {
75 let spec = std::fs::read_to_string(path)
76 .unwrap_or_else(|_| panic!("unable to read FIX dictionary file at {path}"));
77 Dictionary::from_quickfix_spec(&spec)
78 }
79
80 #[cfg(feature = "fix40")]
82 #[cfg_attr(doc_cfg, doc(cfg(feature = "fix40")))]
83 pub fn fix40() -> Self {
84 let spec = include_str!("resources/quickfix/FIX-4.0.xml");
85 Dictionary::from_quickfix_spec(spec).unwrap()
86 }
87
88 #[cfg(feature = "fix41")]
90 #[cfg_attr(doc_cfg, doc(cfg(feature = "fix41")))]
91 pub fn fix41() -> Self {
92 let spec = include_str!("resources/quickfix/FIX-4.1.xml");
93 Dictionary::from_quickfix_spec(spec).unwrap()
94 }
95
96 #[cfg(feature = "fix42")]
98 #[cfg_attr(doc_cfg, doc(cfg(feature = "fix42")))]
99 pub fn fix42() -> Self {
100 let spec = include_str!("resources/quickfix/FIX-4.2.xml");
101 Dictionary::from_quickfix_spec(spec).unwrap()
102 }
103
104 #[cfg(feature = "fix43")]
106 #[cfg_attr(doc_cfg, doc(cfg(feature = "fix43")))]
107 pub fn fix43() -> Self {
108 let spec = include_str!("resources/quickfix/FIX-4.3.xml");
109 Dictionary::from_quickfix_spec(spec).unwrap()
110 }
111
112 #[cfg(feature = "fix44")]
114 pub fn fix44() -> Self {
115 let spec = include_str!("resources/quickfix/FIX-4.4.xml");
116 Dictionary::from_quickfix_spec(spec).unwrap()
117 }
118
119 #[cfg(feature = "fix50")]
121 #[cfg_attr(doc_cfg, doc(cfg(feature = "fix50")))]
122 pub fn fix50() -> Self {
123 let spec = include_str!("resources/quickfix/FIX-5.0.xml");
124 Dictionary::from_quickfix_spec(spec).unwrap()
125 }
126
127 #[cfg(feature = "fix50sp1")]
129 #[cfg_attr(doc_cfg, doc(cfg(feature = "fix50sp1")))]
130 pub fn fix50sp1() -> Self {
131 let spec = include_str!("resources/quickfix/FIX-5.0-SP1.xml");
132 Dictionary::from_quickfix_spec(spec).unwrap()
133 }
134
135 #[cfg(feature = "fix50sp2")]
137 #[cfg_attr(doc_cfg, doc(cfg(feature = "fix50sp1")))]
138 pub fn fix50sp2() -> Self {
139 let spec = include_str!("resources/quickfix/FIX-5.0-SP2.xml");
140 Dictionary::from_quickfix_spec(spec).unwrap()
141 }
142
143 #[cfg(feature = "fixt11")]
145 #[cfg_attr(doc_cfg, doc(cfg(feature = "fixt11")))]
146 pub fn fixt11() -> Self {
147 let spec = include_str!("resources/quickfix/FIXT-1.1.xml");
148 Dictionary::from_quickfix_spec(spec).unwrap()
149 }
150
151 pub fn common_dictionaries() -> Vec<Dictionary> {
155 vec![
156 #[cfg(feature = "fix40")]
157 Self::fix40(),
158 #[cfg(feature = "fix41")]
159 Self::fix41(),
160 #[cfg(feature = "fix42")]
161 Self::fix42(),
162 #[cfg(feature = "fix43")]
163 Self::fix43(),
164 #[cfg(feature = "fix44")]
165 Self::fix44(),
166 #[cfg(feature = "fix50")]
167 Self::fix50(),
168 #[cfg(feature = "fix50sp1")]
169 Self::fix50sp1(),
170 #[cfg(feature = "fix50sp2")]
171 Self::fix50sp2(),
172 #[cfg(feature = "fixt11")]
173 Self::fixt11(),
174 ]
175 }
176
177 pub fn message_by_name(&self, name: &str) -> Option<MessageDefinition<'_>> {
189 let msg_type = self.message_msgtypes_by_name.get(name)?;
190 self.message_by_msgtype(msg_type)
191 }
192
193 pub fn message_by_msgtype(&self, msgtype: &str) -> Option<MessageDefinition<'_>> {
205 self.messages_by_msgtype
206 .get(msgtype)
207 .map(|data| MessageDefinition(self, data))
208 }
209
210 pub fn component_by_name(&self, name: &str) -> Option<Component<'_>> {
212 self.components_by_name
213 .get(name)
214 .map(|data| Component(self, data))
215 }
216
217 pub fn datatype_by_name(&self, name: &str) -> Option<Datatype<'_>> {
227 self.data_types_by_name
228 .get(name)
229 .map(|data| Datatype(self, data))
230 }
231
232 pub fn field_by_tag(&self, tag: u32) -> Option<Field<'_>> {
243 self.fields_by_tags
244 .get(&tag)
245 .map(|data| Field::new(self, data))
246 }
247
248 pub fn field_by_name(&self, name: &str) -> Option<Field<'_>> {
250 let tag = self.field_tags_by_name.get(name)?;
251 self.field_by_tag(*tag)
252 }
253
254 pub fn datatypes(&self) -> Vec<Datatype<'_>> {
265 self.data_types_by_name
266 .values()
267 .map(|data| Datatype(self, data))
268 .collect()
269 }
270
271 pub fn messages(&self) -> Vec<MessageDefinition<'_>> {
283 self.messages_by_msgtype
284 .values()
285 .map(|data| MessageDefinition(self, data))
286 .collect()
287 }
288
289 pub fn fields(&self) -> Vec<Field<'_>> {
292 self.fields_by_tags
293 .values()
294 .map(|data| Field::new(self, data))
295 .collect()
296 }
297
298 pub fn components(&self) -> Vec<Component<'_>> {
301 self.components_by_name
302 .values()
303 .map(|data| Component(self, data))
304 .collect()
305 }
306}