objectcomputing / mFAST

A FAST (FIX Adapted for STreaming) encoder/decoder
http://objectcomputing.github.io/mFAST
BSD 3-Clause "New" or "Revised" License
224 stars 112 forks source link

`fast_encoder` & `fast_encoder_v2` gives different encoded result #126

Open g199209 opened 1 year ago

g199209 commented 1 year ago

Test template:

<?xml version="1.0" encoding="UTF-8"?>
<templates version="2.25" xmlns="http://www.fixprotocol.org/ns/template-definition"> 
  <template id="1" name="TestMessage">
    <string name="MessageType" id="1"><constant value="TestMsg"/></string>
    <int32 name="DataStatus" id="2" presence="optional"><default/></int32>
    <int32 name="TradeIndex" id="3"><increment/></int32> 
    <int32 name="TradeChannel" id="4"><copy/></int32>
  </template>
</templates>

Test program:

#include <iostream>
#include <string>

#include <mfast.h>
#include <mfast/coder/fast_decoder.h>
#include <mfast/coder/fast_encoder.h>
#include <mfast/coder/fast_encoder_v2.h>
#include "template/test.h"

using std::cout;
using std::endl;
using std::string;

void decode_print(const string& name, char *buf, size_t len) {
    const mfast::templates_description* descriptions[]{test::description()};
    mfast::fast_decoder decoder;
    decoder.include(descriptions);

    cout << "--------------------------------" << endl;
    cout << name << endl;
    cout << "raw data [" << len << "] : ";
    for (size_t i = 0; i < len; ++i) {
        uint8_t c = buf[i];
        printf("%02X ", c);
    }
    cout << endl;
    const char* first = buf;
    const char* last = first + len;
    while (first != last) {
        try {
            mfast::message_cref msg = decoder.decode(first, last, true);
            cout << msg.name() << endl;
            test::TestMessage_cref cmsg = static_cast<test::TestMessage_cref>(msg);
            cout << string(cmsg.get_MessageType().name()) << " : " << cmsg.get_MessageType().value() << endl;
            cout << string(cmsg.get_DataStatus().name()) << "  present: " << cmsg.get_DataStatus().present()
                 << ", absent: " << cmsg.get_DataStatus().absent() << endl;
            cout << string(cmsg.get_TradeIndex().name()) << " : " << cmsg.get_TradeIndex().value() << endl;
            cout << string(cmsg.get_TradeChannel().name()) << " : " << cmsg.get_TradeChannel().value() << endl;
        } catch (boost::exception& e) {
            cout << "decode failed!" << endl;
            break;
        }
    }
    cout << "--------------------------------" << endl;
}

int main()
{
    const mfast::templates_description* descriptions[]{test::description()};
    mfast::fast_encoder encoder;
    mfast::fast_encoder_v2 encoder_v2(test::description());

    encoder.include(descriptions);
    char* buf1 = (char*)::malloc(1024);
    char* buf2 = (char*)::malloc(1024);

    test::TestMessage msg;
    test::TestMessage_mref rmsg = msg.ref();
    rmsg.set_TradeIndex().as(123);
    rmsg.set_TradeChannel().as(456);

    size_t l1 = encoder.encode(msg.cref(), buf1, 1024, true);
    size_t l2 = encoder_v2.encode(msg.cref(), buf2, 1024, true);

    decode_print("fast_encoder", buf1, l1);
    decode_print("fast_encoder_v2", buf2, l2);

    ::free(buf1);
    ::free(buf2);
    return 0;
}

Running result:

--------------------------------
fast_encoder
raw data [5] : B0 00 FB 03 C8
decode failed!
--------------------------------
--------------------------------
fast_encoder_v2
raw data [5] : 98 00 FB 03 C8
TestMessage
MessageType : TestMsg
DataStatus  present: 0, absent: 1
TradeIndex : 123
TradeChannel : 456
--------------------------------

The encoded data stream is different, and fast_encoder gives the wrong result.

It seems fast_encoder do not handle optional field correctly.