c++protocol-buffersnanopb

nanopb oneof - encoding problems


I am trying to encode a message using oneof - and the size does not seem ok. Looks like this is ignoring the oneof part - and not encoding it into the stream. The encoding functions all return "TRUE" - which means that they encoded as I requested, which means I encoded wrong... I am missing something very silly.

static auto encode(const pb_msgdesc_t *fields, const void *msg) -> std::vector<pb_byte_t>
{
    size_t size = 0;
    bool ok;
    ok = pb_get_encoded_size(&size, fields, msg);
    printf("pb_get_encoded_size=%d, Encoding data as %lx bytes\n", ok, size);
    auto buff = std::vector<pb_byte_t>(size);
    auto stream = pb_ostream_from_buffer(buff.data(), buff.size());
    ok = pb_encode(&stream, fields, msg);
    printf("pb_encode=%d, Encoding data as %lx bytes\n", ok, stream.bytes_written);
    return buff;
}

auto nano_pb_test() -> void
{
    std::vector<pb_byte_t> pb_res;
    {
        WifiCredResult2 wifi_result;
        wifi_result.ip = (int32_t)3232235920; // https://www.browserling.com/tools/ip-to-dec -> 192.168.1.144
        wifi_result.mac = { 6, { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35}};

        ToAppMessage2 toAppMessage2 = ToAppMessage2_init_zero;
        toAppMessage2.type = ToAppMessageType_CONNECT_WIFI_RESULT;
        toAppMessage2.result = ToAppResultType_NETWORK_IS_LOCAL_ONLY;
        toAppMessage2.esp_error = 0x7002;
        toAppMessage2.which_payload = WifiCredResult2_ip_tag;
        toAppMessage2.payload.wifi = wifi_result;
        pb_res = encode(ToAppMessage2_fields, &toAppMessage2);
    }
    {
        ToAppMessage2 toAppMessage3 = ToAppMessage2_init_zero;
        toAppMessage3.payload.wifi.ip = 12;
        pb_istream_t istream = pb_istream_from_buffer((const pb_byte_t *)pb_res.data(), pb_res.size());

        if (!pb_decode(&istream, ToAppMessage2_fields, &toAppMessage3)) {
            printf("nanopb failed parsing:\n");
        } else {
            printf("result = %d, esp: %x, ip=%d\n", toAppMessage3.result, toAppMessage3.esp_error, toAppMessage3.payload.wifi.ip);
        }
    }
}

The protobuff (parts of..)


enum ToAppMessageType {
...
}

enum ToAppResultType {
...
}

message Details {
    string project_id = 1;
    string url1   = 2;
    string url2    = 5;
}

message Result2 {
    int32 ip = 1;
    bytes mac = 2;
}

message ToAppMessage2 {
    ToAppMessageType type = 1;
    ToAppResultType result = 2;
    int32 error = 3;

    oneof payload {
        WifiCredResult2 wifi = 4;
        PairResult pair = 5;
    }
}

Options file:

WifiCredResult2.mac max_size:6

Solution

  • I think your problem is here:

    toAppMessage2.which_payload = WifiCredResult2_ip_tag;
    

    This would indicate that your payload oneof contains an item of type WifiCredResult2.ip, but there is no such item in that oneof so nothing gets encoded. It appears you want instead:

    toAppMessage2.which_payload = ToAppMessage2_wifi_tag;