rsx-messages

The RSX wire records (Fill/BBO/Order*/…): fixed-layout #[repr(C, align(64))] structs with one CastRecord impl each, on top of rsx-cast. No runtime, no I/O.← All Crates

Description

rsx-messages Architecture

A library of fixed-layout wire records and one CastRecord impl per record. No runtime, no I/O, no threading — the records are plain #[repr(C, align(64))] structs that the rsx-cast transport moves as opaque bytes.

What a record is

Each record is a #[repr(C, align(64))] struct laid out so that:

  • The first field is seq: u64. CastRecord::seq returns it and set_seq writes it; the transport stamps the sequence number in place with no re-encode.
  • The size is a multiple of 64 bytes (64 or 128 here), reached with explicit _pad/_pad0/_pad1 fields. align(64) keeps a record on its own cache line(s).
  • Size and alignment are pinned by a compile-time assertion:

rust const _: () = assert!(mem::size_of::<FillRecord>() == 128); const _: () = assert!(mem::align_of::<FillRecord>() == 64);

A field edit that changes the layout breaks the build.

Price and Qty (from rsx-types) are #[repr(transparent)] over i64, so embedding them costs nothing and keeps the record byte-for-byte wire-stable.

The CastRecord contract

rsx-cast defines CastRecord with three methods:

fn seq(&self) -> u64;
fn set_seq(&mut self, seq: u64);
fn record_type() -> u16;

record_type() returns the crate's RECORD_* constant, which the transport writes into the 16-byte header's record_type field. A receiver dispatches on that field and reads the payload in place. The transport knows nothing about the struct beyond these three methods.

Type-space layout

Record-type discriminants (RECORD_*: u16) are the domain layer's namespace; rsx_cast::protocol owns the transport-level constants separately. Discriminants are contiguous except where reserved for records other tiles own: RECORD_ORDER_REQUEST (9) and RECORD_ORDER_RESPONSE (10) are held here so the numeric space stays coordinated across the gateway and risk crates, even though those structs are defined elsewhere.

Encode / decode

  • encode_<record> wraps rsx_cast::encode_record(record_type, as_bytes(record)) — it prepends the 16-byte header and returns an owned Vec<u8>. Allocating; used off the hot path (tests, tools). The hot path uses the transport's zero-copy framing (WalWriter::prepare / CastSender::send_framed) directly.
  • decode_<record> is generated by the decode_record! macro: a length check followed by ptr::read_unaligned into an owned copy of the struct, or None if the payload is too short. read_unaligned is used because a payload slice carries no alignment guarantee even though the struct wants 64.

Runtime

None. The records are unaware of which path (UDP, TCP, disk) carries them; producers and consumers in the wider exchange own the runtime and transport decisions.

Benchmarks

no benchmark report yet for this crate.

Comparisons

no external comparison yet.