Skip to content

[Golang] <set> does not compile #1047

Open
Open
@szymonwieloch

Description

@szymonwieloch

Hi. Recently I generated golang code and discovered that it didn't compile. The problem seems quite severe - no <set> element can be correctly generated. But it's actually quite easy to fix.

Schema:

<set name="OrderFlags" encodingType="uint64">
<choice name="SomeVal">0</choice>
...
</set>

Generated code:

type OrderFlags [64]bool
type OrderFlagsChoiceValue uint8
type OrderFlagsChoiceValues struct{
    SomeVal OrderFlagsChoiceValue
...

var OrderFlagsChoice = OrderFlagsChoiceValues{uint64(0), uint64(1) ...}

Now, this has no chance of being compiled because uint64 cannot be converted into OrderFlagsChoiceValue since in golang those are different types. The last line therefore raises an error. I suspect that the intention was to generate something like this:

var OrderFlagsChoice = OrderFlagsChoiceValues{OrderFlagsChoiceValue(0), OrderFlagsChoiceValue(1) ...}

Or just the numbers as golang considers numbers to be "untyped".

Aside from the main issue: I have a question about the implementation. Since the generated code does not work anyway, could we replace it with something more efficient? If you have a look at the implementation of the Encode() and Decode() methods, you will quickly spot that the algorithm iterates 64 times over the array to generate just one set element. For a low level protocol such a SBE this operation seems to be way more costly than any other element of SBE. Instead you could just use standard binary operations.

Rough proposal:

type OrderFlags uint64
type OrderFlagsChoiceValues struct {
    SomeVal OrderFlags
    ....

var OrderFlagsChoice = OrderFlagsChoiceValues{
    SomeVal = 1 << 0,
    ...


// example use
msg.OrderFlags = proto.OrderFlagsChoice.SomeVal | proto.OrderFlagsChoice.SomeOtherVal

// check if set
if ((msg.OrderFlags & proto.OrderFlagsChoice.SomeVal) != 0){

Even move golangish version and probably a bit faster (but less consistent with other generated code):

type OrderFlags uint64
const OrderFlagsSomeVal OrderFlags = 1 << 0
....

msg.OrderFlags = proto.OrderFlagsSomeVal | proto.OrderFlagsSomeOtherVal

This way encoding and decoding becomes just a direct write of 8 bytes .

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions