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