Home | History | Annotate | Download | only in using_union_messages
      1 /* This program reads a message from stdin, detects its type and decodes it.
      2  */
      3 
      4 #include <stdio.h>
      5 #include <string.h>
      6 #include <stdlib.h>
      7 
      8 #include <pb_decode.h>
      9 #include "unionproto.pb.h"
     10 
     11 /* This function reads manually the first tag from the stream and finds the
     12  * corresponding message type. It doesn't yet decode the actual message.
     13  *
     14  * Returns a pointer to the MsgType_fields array, as an identifier for the
     15  * message type. Returns null if the tag is of unknown type or an error occurs.
     16  */
     17 const pb_field_t* decode_unionmessage_type(pb_istream_t *stream)
     18 {
     19     pb_wire_type_t wire_type;
     20     uint32_t tag;
     21     bool eof;
     22 
     23     while (pb_decode_tag(stream, &wire_type, &tag, &eof))
     24     {
     25         if (wire_type == PB_WT_STRING)
     26         {
     27             const pb_field_t *field;
     28             for (field = UnionMessage_fields; field->tag != 0; field++)
     29             {
     30                 if (field->tag == tag && (field->type & PB_LTYPE_SUBMESSAGE))
     31                 {
     32                     /* Found our field. */
     33                     return field->ptr;
     34                 }
     35             }
     36         }
     37 
     38         /* Wasn't our field.. */
     39         pb_skip_field(stream, wire_type);
     40     }
     41 
     42     return NULL;
     43 }
     44 
     45 bool decode_unionmessage_contents(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
     46 {
     47     pb_istream_t substream;
     48     bool status;
     49     if (!pb_make_string_substream(stream, &substream))
     50         return false;
     51 
     52     status = pb_decode(&substream, fields, dest_struct);
     53     pb_close_string_substream(stream, &substream);
     54     return status;
     55 }
     56 
     57 int main()
     58 {
     59     /* Read the data into buffer */
     60     uint8_t buffer[512];
     61     size_t count = fread(buffer, 1, sizeof(buffer), stdin);
     62     pb_istream_t stream = pb_istream_from_buffer(buffer, count);
     63 
     64     const pb_field_t *type = decode_unionmessage_type(&stream);
     65     bool status = false;
     66 
     67     if (type == MsgType1_fields)
     68     {
     69         MsgType1 msg = {};
     70         status = decode_unionmessage_contents(&stream, MsgType1_fields, &msg);
     71         printf("Got MsgType1: %d\n", msg.value);
     72     }
     73     else if (type == MsgType2_fields)
     74     {
     75         MsgType2 msg = {};
     76         status = decode_unionmessage_contents(&stream, MsgType2_fields, &msg);
     77         printf("Got MsgType2: %s\n", msg.value ? "true" : "false");
     78     }
     79     else if (type == MsgType3_fields)
     80     {
     81         MsgType3 msg = {};
     82         status = decode_unionmessage_contents(&stream, MsgType3_fields, &msg);
     83         printf("Got MsgType3: %d %d\n", msg.value1, msg.value2);
     84     }
     85 
     86     if (!status)
     87     {
     88         printf("Decode failed: %s\n", PB_GET_ERROR(&stream));
     89         return 1;
     90     }
     91 
     92     return 0;
     93 }
     94 
     95 
     96 
     97