Expand description
FAST (FIX Adapted for STreaming 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.
The fastlib crate provides a decoder for FAST protocol messages.
§Usage
§Serialize/Deserialize using serde
For templates defined in XML, e.g.:
<?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:
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 asenum;<decimal>can be deserialized tof64orDecimal(if you need to preserve original scale);<byteVector>is aVec<u8>and must be prefixed with#[serde(with = "serde_bytes")];<sequence>is aVec<SequenceItem>, whereSequenceItemis astruct;<group>is a nestedstruct;- 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")], whereNis 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:
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:
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
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:
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:
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.
Structs§
- Decimal
- Represents a scaled decimal number.
- Decoder
- Decoder for FAST protocol messages.
- Encoder
- Encoder for FAST protocol messages.
- Json
Message Factory - Message factory implementation that formats decoded messages as JSON encoded
String. - Text
Message Factory - Message factory implementation that formats decoded messages as a human-readable text.
- Text
Message Visitor
Enums§
Traits§
- Message
Factory - Defines the interface for message factories.
- Message
Visitor - Defines the interface for message visitors.
- Reader
- A trait that provides methods for reading basic primitive types.
- Writer
- A trait that provides methods for writing basic primitive types.
Functions§
- from_
buffer - Decode single message from buffer. Returns the decoded message and number of bytes consumed.
- from_
bytes - Decode single message from
bytes::Bytes. - from_
reader - Decode single message from object that implements
fastlib::Readertrait. - from_
slice - Decode single message from buffer.
The
bytesslice must be consumed completely. It is an error if any bytes left after the message is decoded. - from_
stream - Decode single message from object that implements
std::io::Readtrait. - from_
vec - Decode single message from
Vec<u8>. - to_
buffer - Encode single message into pre-allocated buffer. Returns number of bytes written.
- to_
bytes - Encode single message into
bytes::BufMut. - to_
stream - Encode single message into object that implements
std::io::Writetrait. - to_vec
- Encode single message into
Vec<u8>. - to_
writer - Encode single message into object that implements
fastlib::Writertrait.