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