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