/* 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 "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_field_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) { const pb_field_t *field; for (field = UnionMessage_fields; field->tag != 0; field++) { if (field->tag == tag && (field->type & PB_LTYPE_SUBMESSAGE)) { /* Found our field. */ return field->ptr; } } } /* Wasn't our field.. */ pb_skip_field(stream, wire_type); } return NULL; } bool decode_unionmessage_contents(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) { pb_istream_t substream; if (!pb_make_string_substream(stream, &substream)) return false; return pb_decode(&substream, fields, dest_struct); } 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_field_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("Decoding failed.\n"); return 1; } return 0; }