Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 87 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,88 @@
# trafix
# Project Structure

A Rust-based implementation of the Financial Information eXchange (FIX) engine featuring 2 subcrates: trafix-codec: Low-level library for high-performance parsing, encoding, and validation of FIX messages. trafix-engine: Full-featured FIX engine with session management, transports, and persistence built on top of trafix-codec.
This project is organized as a multirepo, consisting of multiple underlying crates, some of which are:

- **trafix** — an umbrella crate wrapping the 2 below.
- **trafix-codec** — a low-level library for high-performance parsing, encoding, and validation of FIX messages.
- **trafix-engine** — a full-featured FIX engine with session management, transports, and persistence built on top of `trafix-codec`.

## trafix-codec

**trafix-codec** is the foundation crate: it provides control over FIX messages manipulation.

### Key Features

- **Message creation**: Version-agnostic FIX message creation using a type-safe builder.
- Type-safe builder for `Message`.
- Allows custom fields.
- Prevents construction of invalid `Message`s.

- **Message decoding**: Version-agnostic FIX message decoding with a focus on correctness.
- SOH-based frame parsing (`tag=value\x01`)
- Support for FIX session-level messages
- Support for message validation

- **Message encoding**: Deterministic FIX message serialization with automatic framing.
- Correct handling of `BeginString (8)`, `BodyLength (9)`, and `CheckSum (10)`
- Supports arbitrary field order while enforcing FIX wire rules
- Efficient buffer-based encoding using (`Bytes` / `BytesMut`)

---

### Example: full usage

```rust
use trafix_codec::message::{
Message,
field::{
Field,
value::{begin_string::BeginString, msg_type::MsgType},
},
};

fn main() {
// Create the FIX message builder
let builder = Message::builder(BeginString::FIX44, MsgType::Logout);

// Create a custom field (to be added in header)
let custom_header_field = Field::Custom {
tag: 22,
value: b"custom_header_field".to_vec(),
};

// Create a custom field (to be added in body)
let custom_body_field1 = Field::Custom {
tag: 40000,
value: b"custom_body_field1".to_vec(),
};

// Create a custom field (to be added in body)
let custom_body_field2 = Field::Custom {
tag: 50000,
value: b"custom_body_field2".to_vec(),
};

// build the message after adding the needed fields.
let message = builder
.with_header(custom_header_field)
.with_field(custom_body_field1)
.with_field(custom_body_field2)
.build();

// encode the message into bytes
let encoded_message = message.encode();
println!("{:?}", encoded_message);

// decoding example; decoding and encoding a message results in the same bytes output.

// Raw FIX message
let input = "8=FIX.4.4\x019=148\x0135=A\x0134=1080\x0149=TESTBUY1\x0152=20180920-18:14:19.508\x0156=TESTSELL1\x0111=636730640278898634\x0115=USD\x0121=2\x0138=7000\x0140=1\x0154=1\x0155=MSFT\x0160=20180920-18:14:19.492\x0110=089\x01";

// decode the input
let message2 = Message::decode(input).expect("Input is valid");

// encode the message into bytes
let encoded_message2 = message2.encode();
println!("{:?}", encoded_message2);
}
```