1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
//! **FAST** (**F**IX **A**dapted for **ST**reaming protocol) is a space and processing
//! efficient encoding method for message oriented data streams.
//!
//! The FAST protocol has been developed as part of the FIX Market Data Optimization Working Group.
//! FAST data compression algorithm is designed to optimize electronic exchange of financial data, particularly
//! for high volume, low latency data dissemination. It significantly reduces bandwidth requirements and latency
//! between sender and receiver. FAST works especially well at improving performance during periods of peak message
//! rates.
//!
//! Fot the FAST protocol description see [technical specification](https://www.fixtrading.org/standards/fast-online/).
//!
//! The `fastlib` crate provides a decoder for FAST protocol messages.
//!
//! # Usage
//!
//! ## Serialize/Deserialize using serde
//!
//! For templates defined in XML, e.g.:
//!
//! ```xml
//! <?xml version="1.0" encoding="UTF-8" ?>
//! <templates xmlns="http://www.fixprotocol.org/ns/fast/td/1.1">
//! <template name="MsgHeader">
//! <uInt32 id="34" name="MsgSeqNum"/>
//! <uInt64 id="52" name="SendingTime"/>
//! </template>
//! <template id="1" name="MDHeartbeat">
//! <templateRef name="MsgHeader"/>
//! </template>
//! <template id="2" name="MDLogout">
//! <templateRef name="MsgHeader"/>
//! <string id="58" name="Text" presence="optional"/>
//! </template>
//! </templates>
//! ```
//!
//! Define the message types in Rust:
//!
//! ```rust,ignore
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Serialize, Deserialize)]
//! enum Message {
//! MDHeartbeat(Heartbeat),
//! MDLogout(Logout),
//! }
//!
//! #[derive(Serialize, Deserialize)]
//! struct MsgHeader {
//! #[serde(rename = "MsgSeqNum")]
//! msg_seq_num: u32,
//! #[serde(rename = "SendingTime")]
//! sending_time: u64,
//! }
//!
//! #[derive(Serialize, Deserialize)]
//! #[serde(rename_all = "PascalCase")]
//! struct Heartbeat {
//! #[serde(flatten)]
//! msg_header: MsgHeader,
//! }
//!
//! #[derive(Serialize, Deserialize)]
//! #[serde(rename_all = "PascalCase")]
//! struct Logout {
//! #[serde(flatten)]
//! msg_header: MsgHeader,
//! text: Option<String>,
//! }
//! ```
//!
//! Some guidelines:
//!
//! * `<templates>` must be implemented as `enum`;
//! * `<decimal>` can be deserialized to `f64` or [`Decimal`] (if you need to preserve original scale);
//! * `<byteVector>` is a `Vec<u8>` and must be prefixed with `#[serde(with = "serde_bytes")]`;
//! * `<sequence>` is a `Vec<SequenceItem>`, where `SequenceItem` is a `struct`;
//! * `<group>` is a nested `struct`;
//! * fields with optional presence are `Option<...>`;
//! * static template reference can be plain fields from the template or flattened `struct`,
//! * dynamic template references must be `Box<Message>` with `#[serde(rename = "templateRef:N")]`, where `N`
//! is a 0-based index of the `<templateRef>` in its group.
//!
//! To deserialize a message call [`from_slice`], [`from_buffer`], [`from_vec`], [`from_bytes`] or more generic [`from_reader`] or [`from_stream`]:
//!
//! ```rust,ignore
//! use fastlib::Decoder;
//!
//! // Create a decoder from XML templates.
//! let mut decoder = Decoder::new_from_xml(include_str!("templates.xml"))?;
//!
//! // Raw data that contains one message.
//! let raw_data: Vec<u8> = vec![ ... ];
//!
//! // Deserialize a message.
//! let msg: Message = fastlib::from_slice(&mut decoder, &raw_data)?;
//! ```
//!
//! To serialize a message call [`to_vec`], [`to_bytes`], [`to_writer`], [`to_stream`] or [`to_buffer`]:
//!
//! ```rust,ignore
//! use fastlib::Encoder;
//!
//! // Create an encoder from XML templates.
//! let mut encoder = Encoder::new_from_xml(include_str!("templates.xml"))?;
//!
//! // Message to serialize.
//! let msg = Message::MDHeartbeat{
//! Heartbeat {
//! ...
//! }
//! };
//!
//! // Serialize a message.
//! let raw: Vec<u8> = fastlib::to_vec(&mut encoder, &msg)?;
//! ```
//!
//! ## Decode to JSON
//!
//! ```rust,ignore
//! use fastlib::Decoder;
//! use fastlib::JsonMessageFactory;
//!
//! // Raw data that contains one message.
//! let raw_data: Vec<u8> = vec![ ... ];
//!
//! // Create a decoder from XML templates.
//! let mut decoder = Decoder::new_from_xml(include_str!("templates.xml"))?;
//!
//! // Create a JSON message factory.
//! let mut msg = JsonMessageFactory::new();
//!
//! // Decode the message.
//! decoder.decode_vec(raw_data, &mut msg)?;
//!
//! println!("{}", msg.json);
//! ```
//!
//! ## Decode using own message factory
//!
//! **NOTE:** Decoding using own message factory is only required if very specific process of decoding
//! into very specific message types is needed. In most cases using `serde` is the way to go!
//!
//! Make a new struct that implements [`MessageFactory`] trait:
//!
//! ```rust,ignore
//! use fastlib::{MessageFactory, Value};
//!
//! // Message factory struct that will build a message during decoding.
//! pub struct MyMessageFactory {
//! }
//!
//! // Callback functions that will be called for each message during decoding process.
//! impl MessageFactory for MyMessageFactory {
//! // ... your implementation here ...
//! }
//!```
//! Then create a decoder from templates XML file and decode a message:
//!
//! ```rust,ignore
//! use fastlib::Decoder;
//!
//! // Raw data that contains one message.
//! let raw_data: Vec<u8> = vec![ ... ];
//!
//! // Create a decoder from XML templates.
//! let mut decoder = Decoder::new_from_xml(include_str!("templates.xml"))?;
//!
//! // Create a message factory.
//! let mut msg = MyMessageFactory{};
//!
//! // Decode the message.
//! decoder.decode_vec(raw_data, &mut msg)?;
//! ```
//!
//! For message factory implementation examples see [`TextMessageFactory`] and [`JsonMessageFactory`].
//!
//! ## Features
//!
//! Name | Default?
//! ---------------|---
//! `serde` | ✔
//! `rust_decimal` |
//!
//! ### `serde`
//!
//! Enables functionality for serializing and deserializing FAST messages into Rust data types.
//!
//! ### `rust_decimal`
//!
//! Enables integration with [`rust_decimal`] library.
//! Provides `From<Decimal>` implementation for [`rust_decimal::Decimal`] and `TryFrom<rust_decimal::Decimal>` for [`Decimal`].
//!
//! [`rust_decimal`]: https://docs.rs/rust_decimal/latest/rust_decimal/
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use *;
pub use *;
pub type Result<T, E = Error> = Result;