decode.c 2.6 KB

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