| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 | /* This program reads a message from stdin, detects its type and decodes it. */ #include <stdio.h>#include <string.h>#include <stdlib.h>#include <pb_decode.h>#include <pb_common.h>#include "unionproto.pb.h"/* This function reads manually the first tag from the stream and finds the * corresponding message type. It doesn't yet decode the actual message. * * Returns a pointer to the MsgType_fields array, as an identifier for the * message type. Returns null if the tag is of unknown type or an error occurs. */const pb_msgdesc_t* decode_unionmessage_type(pb_istream_t *stream){    pb_wire_type_t wire_type;    uint32_t tag;    bool eof;    while (pb_decode_tag(stream, &wire_type, &tag, &eof))    {        if (wire_type == PB_WT_STRING)        {            pb_field_iter_t iter;            if (pb_field_iter_begin(&iter, UnionMessage_fields, NULL) &&                pb_field_iter_find(&iter, tag))            {                /* Found our field. */                return iter.submsg_desc;            }        }                /* Wasn't our field.. */        pb_skip_field(stream, wire_type);    }        return NULL;}bool decode_unionmessage_contents(pb_istream_t *stream, const pb_msgdesc_t *messagetype, void *dest_struct){    pb_istream_t substream;    bool status;    if (!pb_make_string_substream(stream, &substream))        return false;        status = pb_decode(&substream, messagetype, dest_struct);    pb_close_string_substream(stream, &substream);    return status;}int main(){    /* Read the data into buffer */    uint8_t buffer[512];    size_t count = fread(buffer, 1, sizeof(buffer), stdin);    pb_istream_t stream = pb_istream_from_buffer(buffer, count);        const pb_msgdesc_t *type = decode_unionmessage_type(&stream);    bool status = false;        if (type == MsgType1_fields)    {        MsgType1 msg = {};        status = decode_unionmessage_contents(&stream, MsgType1_fields, &msg);        printf("Got MsgType1: %d\n", msg.value);    }    else if (type == MsgType2_fields)    {        MsgType2 msg = {};        status = decode_unionmessage_contents(&stream, MsgType2_fields, &msg);        printf("Got MsgType2: %s\n", msg.value ? "true" : "false");    }    else if (type == MsgType3_fields)    {        MsgType3 msg = {};        status = decode_unionmessage_contents(&stream, MsgType3_fields, &msg);        printf("Got MsgType3: %d %d\n", msg.value1, msg.value2);        }        if (!status)    {        printf("Decode failed: %s\n", PB_GET_ERROR(&stream));        return 1;    }        return 0;}
 |