FIX. Parser
(fix_message v0.1.0)
Copy Markdown
A recursive binary-matching FIX parser.
Provides two layers:
frame/1andparse_message/2— message framing for a byte stream: validates the BeginString(8)/BodyLength(9) structure and the CheckSum(10) trailer, and splits complete messages off the buffer.parse/2— tokenizes a complete message oftag=value<SOH>fields into{header, body, trailer}sections. Length-prefixed data fields (RawData, EncodedText, ...) are sliced byte-exactly, so their values may contain the SOH delimiter.
Which tags are length-prefixed data fields, and which belong to the
standard header and trailer, is determined by a FIX.Dictionary,
defaulting to FIX.Dictionary.FIX44. Pass a custom dictionary to handle
counterparty-defined data fields.
Summary
Functions
Splits one complete FIX message off the front of buffer.
Tokenizes FIX fields from binary into {header, body, trailer} sections.
Frames and tokenizes one complete FIX message off the front of buffer.
Types
Functions
@spec frame(binary()) :: {:ok, message :: binary(), rest :: binary()} | :incomplete | {:error, frame_error()}
Splits one complete FIX message off the front of buffer.
Validates that the message starts with BeginString(8) followed by BodyLength(9), that the full body and trailer are present, and that CheckSum(10) matches. The BeginString value itself is not restricted to a particular FIX version.
Returns:
{:ok, message, rest}—messageis the complete framed message (a sub-binary ofbuffer) andrestis whatever follows it.:incomplete—bufferis a valid prefix of a message; read more bytes.{:error, :garbled}—buffercannot be the start of a valid message.{:error, :checksum_mismatch}— well-framed, but CheckSum(10) is wrong.
Tokenizes FIX fields from binary into {header, body, trailer} sections.
Returns {:ok, {header, body, trailer}} when the entire input parses,
where each section is a list of {tag, value} tuples in wire order (tags
are integers, values are binaries), or {:error, :garbled} if any part of
the input cannot be consumed.
The split is positional and forward-only, driven by the dictionary's
header_tag?/1 and trailer_tag?/1: fields accumulate into the header
until the first non-header tag, then into the body until the first trailer
tag, then into the trailer. A header tag appearing after the body has
started stays in the body. Concatenating the sections reconstructs the
full field stream.
Data fields are length-prefixed by their companion field (e.g.
RawDataLength(95) precedes RawData(96)) and are sliced by the declared byte
count, so their values may contain SOH. A length field not followed by its
companion data field with exactly the declared number of bytes is garbled.
Both halves of a pair land in the section chosen by the length tag.
The companion pairs are defined by dictionary (see FIX.Dictionary).
@spec parse_message(binary(), module()) :: {:ok, sections(), rest :: binary()} | :incomplete | {:error, frame_error()}
Frames and tokenizes one complete FIX message off the front of buffer.
Combines frame/1 and parse/1: returns {:ok, sections, rest} for a
complete, checksum-valid message whose fields all parsed, where sections
is the {header, body, trailer} split (see parse/2) and rest is the
remainder of the buffer (any pipelined messages after this one).
Returns :incomplete when more bytes are needed, and {:error, reason}
otherwise. A message that frames correctly but contains unparseable fields
is {:error, :garbled}.