Table of contents

 

As described earlier, a FAST message templates are composed of template units. Template units are either template fields or sequences.
A sequence is a set of fields and is comprised of:

  1. A sequence length that represents the number if instances of this sequence follow.
  2. Field group repeating "sequence length" times, each beginning with its own PMap.

The decoding algorithm for a sequence follows:

Sequence decoding algorithm

Picture 3.15 - "Sequence decoding algorithm"

With the introduction of "sequence" concept, we need to extend the field decoding algorithm, as shown here.

Field decoding algorithm

Picture 3.16 - "Field decoding algorithm"

The following example shows an example implementation of the TemplateUnit interface for "sequence":

private TemplateField sequenceLength; 
private TemplateUnit[] templateFields;  
 
public int decode(byte[] encodedData, int offset, PresenceMap presenceMap, OutputMessage message) {
    offset = sequenceLength.decode(buffer, offset, presenceMap, message);
    if (sequenceLength.getFieldValue() != null) {
        int groupsCount = sequenceLength.getFieldValue();
        if (groupsCount > 0) {
		    message.createFieldsSequence(sequenceLength.getTagId(), groupsCount);
            for (int iter = 0; iter < groupsCount; iter++) {
                presenceMap = new PresenceMap();
                if (isPMapRequired) {
                    presenceMap.init(buffer, offset);
                    offset = presenceMap.getLastPMapBytePosition() + 1;
                }
                for (int i = 1; i < templateFields.length; i++) {
                    offset = templateFields[i].decode(buffer, offset, presenceMap, message);
                }
            }
        }
    } else {
        if (isMandatory) {
            throw new RuntimeException("A mandatory sequence is missing from the stream.");
        }
    }
    return offset; 
}
 
public void reset() {
    for (int i = 1; i < templateFields.length; i++) {
        templateFields[i].reset();
    }
}

Note:

In the above code, boolean variable isPMapRequired is true if any template field in the sequence requires a PMap bit. According to FAST, if no PMap bits are required (i.e., all fields are will always be present in the encoded message or are mandatory constants), then no PMap will precede the field groups so an empty PMap will be used.

The method isPMapRequired() can be implemented with the following code snippet:

isPMapRequired = false; 
for (TemplateField field : templateFields) {
    if (field.isPMapBitExist()) {
        isPMapRequired = true;
        break;
    }
}

Sequence decoding example:


Let's consider a small message that has the following template

   <template name="SampleTemplate_2" id="2" dictionary="2"
        xmlns="http://www.fixprotocol.org/ns/fast/td/1.1">
        <string name="MessageType" id="35">
                <constant value="X" />
        </constant></string>
        <sequence name="MDEntries">
                <length name="NoMDEntries" id="268"></length>
                <string name="TradingSessionID" id="336">
                        <default value="2" />
                </default></string>
                <uInt32 name="MDUpdateAction" id="279">
                        <copy value="1" />
                </copy></uint32>
        </sequence>
    </template>


Our input FAST message: 0xC0 0xA3 0x81 0xA0 0x80 = 11000000 10100011 10000001 10100000 10000000
The following table shows complete decoding of this message:

Decoding of message which contains sequence

Picture 3.17 - "Decoding of message which contains sequence"

After collecting our fields the output message will be: 35=X|268=1|336=2|279=0