17ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* This program reads a message from stdin, detects its type and decodes it.
27ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen */
37ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
47ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <stdio.h>
57ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <string.h>
67ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <stdlib.h>
77ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
87ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <pb_decode.h>
97ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include "unionproto.pb.h"
107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* This function reads manually the first tag from the stream and finds the
127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * corresponding message type. It doesn't yet decode the actual message.
137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen *
147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * Returns a pointer to the MsgType_fields array, as an identifier for the
157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * message type. Returns null if the tag is of unknown type or an error occurs.
167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen */
177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenconst pb_field_t* decode_unionmessage_type(pb_istream_t *stream)
187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{
197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    pb_wire_type_t wire_type;
207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    uint32_t tag;
217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    bool eof;
227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    while (pb_decode_tag(stream, &wire_type, &tag, &eof))
247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    {
257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        if (wire_type == PB_WT_STRING)
267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        {
277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen            const pb_field_t *field;
287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen            for (field = UnionMessage_fields; field->tag != 0; field++)
297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen            {
307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen                if (field->tag == tag && (field->type & PB_LTYPE_SUBMESSAGE))
317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen                {
327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen                    /* Found our field. */
337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen                    return field->ptr;
347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen                }
357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen            }
367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        }
377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        /* Wasn't our field.. */
397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        pb_skip_field(stream, wire_type);
407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    }
417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    return NULL;
437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen}
447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool decode_unionmessage_contents(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{
477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    pb_istream_t substream;
487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    bool status;
497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    if (!pb_make_string_substream(stream, &substream))
507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        return false;
517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    status = pb_decode(&substream, fields, dest_struct);
537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    pb_close_string_substream(stream, &substream);
547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    return status;
557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen}
567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenint main()
587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{
597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    /* Read the data into buffer */
607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    uint8_t buffer[512];
617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    size_t count = fread(buffer, 1, sizeof(buffer), stdin);
627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    pb_istream_t stream = pb_istream_from_buffer(buffer, count);
637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    const pb_field_t *type = decode_unionmessage_type(&stream);
657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    bool status = false;
667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    if (type == MsgType1_fields)
687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    {
697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        MsgType1 msg = {};
707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        status = decode_unionmessage_contents(&stream, MsgType1_fields, &msg);
717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        printf("Got MsgType1: %d\n", msg.value);
727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    }
737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    else if (type == MsgType2_fields)
747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    {
757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        MsgType2 msg = {};
767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        status = decode_unionmessage_contents(&stream, MsgType2_fields, &msg);
777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        printf("Got MsgType2: %s\n", msg.value ? "true" : "false");
787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    }
797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    else if (type == MsgType3_fields)
807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    {
817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        MsgType3 msg = {};
827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        status = decode_unionmessage_contents(&stream, MsgType3_fields, &msg);
837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        printf("Got MsgType3: %d %d\n", msg.value1, msg.value2);
847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    }
857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    if (!status)
877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    {
887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        printf("Decode failed: %s\n", PB_GET_ERROR(&stream));
897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        return 1;
907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    }
917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    return 0;
937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen}
947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
97