Skip to content

Revisit hotfix-message design: asymmetric Part trait, unnecessary mutation, and per-field allocation #305

@davidsteiner

Description

@davidsteiner

Summary

Several design issues in hotfix-message affect correctness, API ergonomics, and performance.

Problems

Asymmetric get/set on Message

Message implements Part by delegating get_field_map() to the body, but overrides set() to route fields to the correct part (header/body/trailer) based on FieldLocation. This means message.get(SENDER_COMP_ID) returns Missing even when the field exists in the header, while message.set(SENDER_COMP_ID, "X") correctly routes to the header.

Part trait has too many responsibilities

Part combines field access, mutation, group management, and length calculation. The length calculation semantics differ between parts — Header skips BeginString/BodyLength, Trailer skips CheckSum, Body has no exclusions — but these differences are hidden behind the same interface.

encode() mutates the message

Message::encode() sets BodyLength and CheckSum on self as a side effect. Encoding a message shouldn't require &mut self, and encoding twice may produce unexpected results.

Per-field allocation during parsing

Every parsed field allocates a Vec<u8> via .to_vec(). For high-throughput FIX parsing, a zero-copy approach where fields borrow from the input buffer would avoid allocation on every field.

MessageBuilder naming

MessageBuilder is a parser/factory, not a builder. The name conflicts with the builder pattern and is confusing since actual message construction uses Message::new() + Part::set().

tag_from_bytes doesn't validate input

Non-digit bytes produce garbage results via silent arithmetic overflow rather than returning None.

tags.rs vs session_fields.rs

The same session-level fields (BeginString, BodyLength, MsgType, CheckSum) are defined in both tags.rs and re-exported from session_fields.rs/fixt11, with different modules importing from different sources.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions