Skip to content

MyJetTools/rust-fix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rust-fix

Zero-dependency FIX (Financial Information eXchange) protocol library for Rust, optimized for low-latency trading engines.

Handles FIX message building, parsing, checksum validation, and field access with minimal heap allocations.

Add to your project

[dependencies]
rust-fix = { git = "https://github.com/MyJetTools/rust-fix.git", tag = "0.2.0" }

Choosing the right API

The library provides three main types. Pick the one that fits your use case:

Type Use case Allocations Owns data?
FixMessageWriter Build and send outgoing messages 1 (Vec<u8> body) Yes
FixMessageReader Parse and read incoming messages 0 (borrows input) No
FixMessageBuilder Parse, store, access, and reserialize 2 (Vec<u8> buffer + Vec index) Yes
  • Hot path (sending): FixMessageWriter
  • Hot path (receiving): FixMessageReader - zero-copy, iterates over borrowed input
  • Need to store parsed message: FixMessageBuilder

Examples

Build and send a FIX message

use rust_fix::FixMessageWriter;

let mut msg = FixMessageWriter::new("FIX.4.4", "A"); // version, message type (35=A Logon)
msg.with_value(34, "1092");                           // MsgSeqNum
msg.with_value(49, "TESTBUY1");                       // SenderCompID
msg.with_value(52, "20180920-18:24:59.643");          // SendingTime
msg.with_value(56, "TESTSELL1");                      // TargetCompID
msg.with_value(98, "0");                              // EncryptMethod
msg.with_value(108, "60");                            // HeartBtInt

// Tags 8 (BeginString), 9 (BodyLength), 10 (CheckSum) are calculated automatically.

let bytes: Vec<u8> = msg.compile_message(); // SOH-delimited binary
let text: String = msg.to_string();         // pipe-delimited for debugging
// "8=FIX.4.4|9=75|35=A|34=1092|49=TESTBUY1|52=20180920-18:24:59.643|56=TESTSELL1|98=0|108=60|10=178|"

Parse an incoming message (zero-copy)

From binary (SOH \x01 delimiter):

use rust_fix::FixMessageReader;

let raw = b"8=FIX.4.4\x019=75\x0135=A\x0134=1092\x0149=TESTBUY1\x0156=TESTSELL1\x0198=0\x01108=60\x0110=162\x01";
let reader = FixMessageReader::from_bytes(raw);

From human-readable string (pipe | delimiter):

use rust_fix::FixMessageReader;

let text = "8=FIX.4.4|9=75|35=A|34=1092|49=TESTBUY1|56=TESTSELL1|98=0|108=60|10=162|";
let reader = FixMessageReader::from_str(text);

Validate checksum and access fields:

// Validate checksum (returns Err if invalid)
let reader = reader.check_payload().unwrap();

// Get single field
let msg_type = reader.get_message_type().unwrap(); // "A"
let sender = reader.get_value(49).unwrap();        // Ok(Some("TESTBUY1"))

// Get multiple values for a repeating tag
let values = reader.get_values(49).unwrap();       // Ok(vec!["TESTBUY1"])

// Iterate all tags
for item in reader.iter() {
    let item = item.unwrap();
    println!("tag {}={}", item.key.get_value(), item.value);
}

Parse into owned structure

Use FixMessageBuilder when you need to keep the parsed data beyond the input lifetime:

use rust_fix::FixMessageBuilder;

let raw = b"8=FIX.4.4\x019=75\x0135=A\x0134=1092\x0149=TESTBUY1\x0156=TESTSELL1\x0198=0\x01108=60\x0110=162\x01";

// Parse with checksum validation (second argument: true = validate, false = skip)
let msg = FixMessageBuilder::from_bytes(raw, true).unwrap();

// Access fields
let msg_type = msg.get_message_type();         // b"A"
let sender = msg.get_value_as_str(49);         // Some("TESTBUY1")
let raw_value = msg.get_value(49.into());      // Some(b"TESTBUY1")

// Iterate all values for a tag (useful for repeating groups)
for val in msg.get_values_as_str(49) {
    println!("{}", val);
}

// Reserialize
let bytes = msg.compile();
let text = msg.to_string();

Build from scratch:

use rust_fix::FixMessageBuilder;

let mut msg = FixMessageBuilder::new("FIX.4.4", "D"); // D = NewOrderSingle
msg.with_value(49, "SENDER");
msg.with_value(56, "TARGET");
msg.with_value(11, "order-123");

let bytes = msg.compile();

Error handling

All parsing operations return Result<T, FixSerializeError>:

Error Meaning
VersionTagNotFound Missing tag 8 (BeginString)
MessageTypeTagNotFound Missing tag 35 (MsgType)
CheckSumTagNotFound Missing tag 10, only when validation is enabled
InvalidCheckSum Tag 10 value doesn't match calculated checksum
BodyLenTagNotFound Missing tag 9 (BodyLength)
FixDelimiterNotFound No SOH/pipe delimiter found in input
InvalidFixItem Malformed tag (missing = separator)
InvalidFixKey Tag key is not a valid integer

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages