Home | History | Annotate | Download | only in alltypes_callback
      1 /* Attempts to test all the datatypes supported by ProtoBuf when used as callback fields.
      2  * Note that normally there would be no reason to use callback fields for this,
      3  * because each encoder defined here only gives a single field.
      4  */
      5 
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <pb_encode.h>
     10 #include "alltypes.pb.h"
     11 #include "test_helpers.h"
     12 
     13 static bool write_varint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     14 {
     15     return pb_encode_tag_for_field(stream, field) &&
     16            pb_encode_varint(stream, (long)*arg);
     17 }
     18 
     19 static bool write_svarint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     20 {
     21     return pb_encode_tag_for_field(stream, field) &&
     22            pb_encode_svarint(stream, (long)*arg);
     23 }
     24 
     25 static bool write_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     26 {
     27     return pb_encode_tag_for_field(stream, field) &&
     28            pb_encode_fixed32(stream, *arg);
     29 }
     30 
     31 static bool write_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     32 {
     33     return pb_encode_tag_for_field(stream, field) &&
     34            pb_encode_fixed64(stream, *arg);
     35 }
     36 
     37 static bool write_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     38 {
     39     return pb_encode_tag_for_field(stream, field) &&
     40            pb_encode_string(stream, *arg, strlen(*arg));
     41 }
     42 
     43 static bool write_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     44 {
     45 
     46     return pb_encode_tag_for_field(stream, field) &&
     47            pb_encode_submessage(stream, SubMessage_fields, *arg);
     48 }
     49 
     50 static bool write_emptymsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     51 {
     52     EmptyMessage emptymsg = {0};
     53     return pb_encode_tag_for_field(stream, field) &&
     54            pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg);
     55 }
     56 
     57 static bool write_repeated_varint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     58 {
     59     return pb_encode_tag_for_field(stream, field) &&
     60            pb_encode_varint(stream, 0) &&
     61            pb_encode_tag_for_field(stream, field) &&
     62            pb_encode_varint(stream, 0) &&
     63            pb_encode_tag_for_field(stream, field) &&
     64            pb_encode_varint(stream, 0) &&
     65            pb_encode_tag_for_field(stream, field) &&
     66            pb_encode_varint(stream, 0) &&
     67            pb_encode_tag_for_field(stream, field) &&
     68            pb_encode_varint(stream, (long)*arg);
     69 }
     70 
     71 static bool write_repeated_svarint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     72 {
     73     return pb_encode_tag_for_field(stream, field) &&
     74            pb_encode_svarint(stream, 0) &&
     75            pb_encode_tag_for_field(stream, field) &&
     76            pb_encode_svarint(stream, 0) &&
     77            pb_encode_tag_for_field(stream, field) &&
     78            pb_encode_svarint(stream, 0) &&
     79            pb_encode_tag_for_field(stream, field) &&
     80            pb_encode_svarint(stream, 0) &&
     81            pb_encode_tag_for_field(stream, field) &&
     82            pb_encode_svarint(stream, (long)*arg);
     83 }
     84 
     85 static bool write_repeated_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
     86 {
     87     uint32_t dummy = 0;
     88 
     89     /* Make it a packed field */
     90     return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
     91            pb_encode_varint(stream, 5 * 4) && /* Number of bytes */
     92            pb_encode_fixed32(stream, &dummy) &&
     93            pb_encode_fixed32(stream, &dummy) &&
     94            pb_encode_fixed32(stream, &dummy) &&
     95            pb_encode_fixed32(stream, &dummy) &&
     96            pb_encode_fixed32(stream, *arg);
     97 }
     98 
     99 static bool write_repeated_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
    100 {
    101     uint64_t dummy = 0;
    102 
    103     /* Make it a packed field */
    104     return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
    105            pb_encode_varint(stream, 5 * 8) && /* Number of bytes */
    106            pb_encode_fixed64(stream, &dummy) &&
    107            pb_encode_fixed64(stream, &dummy) &&
    108            pb_encode_fixed64(stream, &dummy) &&
    109            pb_encode_fixed64(stream, &dummy) &&
    110            pb_encode_fixed64(stream, *arg);
    111 }
    112 
    113 static bool write_repeated_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
    114 {
    115     return pb_encode_tag_for_field(stream, field) &&
    116            pb_encode_string(stream, 0, 0) &&
    117            pb_encode_tag_for_field(stream, field) &&
    118            pb_encode_string(stream, 0, 0) &&
    119            pb_encode_tag_for_field(stream, field) &&
    120            pb_encode_string(stream, 0, 0) &&
    121            pb_encode_tag_for_field(stream, field) &&
    122            pb_encode_string(stream, 0, 0) &&
    123            pb_encode_tag_for_field(stream, field) &&
    124            pb_encode_string(stream, *arg, strlen(*arg));
    125 }
    126 
    127 static bool write_repeated_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
    128 {
    129     SubMessage dummy = {""};
    130 
    131     return pb_encode_tag_for_field(stream, field) &&
    132            pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
    133            pb_encode_tag_for_field(stream, field) &&
    134            pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
    135            pb_encode_tag_for_field(stream, field) &&
    136            pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
    137            pb_encode_tag_for_field(stream, field) &&
    138            pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
    139            pb_encode_tag_for_field(stream, field) &&
    140            pb_encode_submessage(stream, SubMessage_fields, *arg);
    141 }
    142 
    143 static bool write_limits(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
    144 {
    145     Limits limits = {0};
    146     limits.int32_min  = INT32_MIN;
    147     limits.int32_max  = INT32_MAX;
    148     limits.uint32_min = 0;
    149     limits.uint32_max = UINT32_MAX;
    150     limits.int64_min  = INT64_MIN;
    151     limits.int64_max  = INT64_MAX;
    152     limits.uint64_min = 0;
    153     limits.uint64_max = UINT64_MAX;
    154     limits.enum_min   = HugeEnum_Negative;
    155     limits.enum_max   = HugeEnum_Positive;
    156 
    157     return pb_encode_tag_for_field(stream, field) &&
    158            pb_encode_submessage(stream, Limits_fields, &limits);
    159 }
    160 
    161 static bool write_repeated_emptymsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
    162 {
    163     EmptyMessage emptymsg = {0};
    164     return pb_encode_tag_for_field(stream, field) &&
    165            pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
    166            pb_encode_tag_for_field(stream, field) &&
    167            pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
    168            pb_encode_tag_for_field(stream, field) &&
    169            pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
    170            pb_encode_tag_for_field(stream, field) &&
    171            pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
    172            pb_encode_tag_for_field(stream, field) &&
    173            pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg);
    174 }
    175 
    176 int main(int argc, char **argv)
    177 {
    178     int mode = (argc > 1) ? atoi(argv[1]) : 0;
    179 
    180     /* Values for use from callbacks through pointers. */
    181     uint32_t    req_fixed32     = 1008;
    182     int32_t     req_sfixed32    = -1009;
    183     float       req_float       = 1010.0f;
    184     uint64_t    req_fixed64     = 1011;
    185     int64_t     req_sfixed64    = -1012;
    186     double      req_double      = 1013.0;
    187     SubMessage  req_submsg      = {"1016", 1016};
    188 
    189     uint32_t    rep_fixed32     = 2008;
    190     int32_t     rep_sfixed32    = -2009;
    191     float       rep_float       = 2010.0f;
    192     uint64_t    rep_fixed64     = 2011;
    193     int64_t     rep_sfixed64    = -2012;
    194     double      rep_double      = 2013.0;
    195     SubMessage  rep_submsg      = {"2016", 2016, true, 2016};
    196 
    197     uint32_t    opt_fixed32     = 3048;
    198     int32_t     opt_sfixed32    = 3049;
    199     float       opt_float       = 3050.0f;
    200     uint64_t    opt_fixed64     = 3051;
    201     int64_t     opt_sfixed64    = 3052;
    202     double      opt_double      = 3053.0f;
    203     SubMessage  opt_submsg      = {"3056", 3056};
    204 
    205     /* Bind callbacks for required fields */
    206     AllTypes alltypes = {{{0}}};
    207 
    208     alltypes.req_int32.funcs.encode = &write_varint;
    209     alltypes.req_int32.arg = (void*)-1001;
    210 
    211     alltypes.req_int64.funcs.encode = &write_varint;
    212     alltypes.req_int64.arg = (void*)-1002;
    213 
    214     alltypes.req_uint32.funcs.encode = &write_varint;
    215     alltypes.req_uint32.arg = (void*)1003;
    216 
    217     alltypes.req_uint32.funcs.encode = &write_varint;
    218     alltypes.req_uint32.arg = (void*)1003;
    219 
    220     alltypes.req_uint64.funcs.encode = &write_varint;
    221     alltypes.req_uint64.arg = (void*)1004;
    222 
    223     alltypes.req_sint32.funcs.encode = &write_svarint;
    224     alltypes.req_sint32.arg = (void*)-1005;
    225 
    226     alltypes.req_sint64.funcs.encode = &write_svarint;
    227     alltypes.req_sint64.arg = (void*)-1006;
    228 
    229     alltypes.req_bool.funcs.encode = &write_varint;
    230     alltypes.req_bool.arg = (void*)true;
    231 
    232     alltypes.req_fixed32.funcs.encode = &write_fixed32;
    233     alltypes.req_fixed32.arg = &req_fixed32;
    234 
    235     alltypes.req_sfixed32.funcs.encode = &write_fixed32;
    236     alltypes.req_sfixed32.arg = &req_sfixed32;
    237 
    238     alltypes.req_float.funcs.encode = &write_fixed32;
    239     alltypes.req_float.arg = &req_float;
    240 
    241     alltypes.req_fixed64.funcs.encode = &write_fixed64;
    242     alltypes.req_fixed64.arg = &req_fixed64;
    243 
    244     alltypes.req_sfixed64.funcs.encode = &write_fixed64;
    245     alltypes.req_sfixed64.arg = &req_sfixed64;
    246 
    247     alltypes.req_double.funcs.encode = &write_fixed64;
    248     alltypes.req_double.arg = &req_double;
    249 
    250     alltypes.req_string.funcs.encode = &write_string;
    251     alltypes.req_string.arg = "1014";
    252 
    253     alltypes.req_bytes.funcs.encode = &write_string;
    254     alltypes.req_bytes.arg = "1015";
    255 
    256     alltypes.req_submsg.funcs.encode = &write_submsg;
    257     alltypes.req_submsg.arg = &req_submsg;
    258 
    259     alltypes.req_enum.funcs.encode = &write_varint;
    260     alltypes.req_enum.arg = (void*)MyEnum_Truth;
    261 
    262     alltypes.req_emptymsg.funcs.encode = &write_emptymsg;
    263 
    264     /* Bind callbacks for repeated fields */
    265     alltypes.rep_int32.funcs.encode = &write_repeated_varint;
    266     alltypes.rep_int32.arg = (void*)-2001;
    267 
    268     alltypes.rep_int64.funcs.encode = &write_repeated_varint;
    269     alltypes.rep_int64.arg = (void*)-2002;
    270 
    271     alltypes.rep_uint32.funcs.encode = &write_repeated_varint;
    272     alltypes.rep_uint32.arg = (void*)2003;
    273 
    274     alltypes.rep_uint64.funcs.encode = &write_repeated_varint;
    275     alltypes.rep_uint64.arg = (void*)2004;
    276 
    277     alltypes.rep_sint32.funcs.encode = &write_repeated_svarint;
    278     alltypes.rep_sint32.arg = (void*)-2005;
    279 
    280     alltypes.rep_sint64.funcs.encode = &write_repeated_svarint;
    281     alltypes.rep_sint64.arg = (void*)-2006;
    282 
    283     alltypes.rep_bool.funcs.encode = &write_repeated_varint;
    284     alltypes.rep_bool.arg = (void*)true;
    285 
    286     alltypes.rep_fixed32.funcs.encode = &write_repeated_fixed32;
    287     alltypes.rep_fixed32.arg = &rep_fixed32;
    288 
    289     alltypes.rep_sfixed32.funcs.encode = &write_repeated_fixed32;
    290     alltypes.rep_sfixed32.arg = &rep_sfixed32;
    291 
    292     alltypes.rep_float.funcs.encode = &write_repeated_fixed32;
    293     alltypes.rep_float.arg = &rep_float;
    294 
    295     alltypes.rep_fixed64.funcs.encode = &write_repeated_fixed64;
    296     alltypes.rep_fixed64.arg = &rep_fixed64;
    297 
    298     alltypes.rep_sfixed64.funcs.encode = &write_repeated_fixed64;
    299     alltypes.rep_sfixed64.arg = &rep_sfixed64;
    300 
    301     alltypes.rep_double.funcs.encode = &write_repeated_fixed64;
    302     alltypes.rep_double.arg = &rep_double;
    303 
    304     alltypes.rep_string.funcs.encode = &write_repeated_string;
    305     alltypes.rep_string.arg = "2014";
    306 
    307     alltypes.rep_bytes.funcs.encode = &write_repeated_string;
    308     alltypes.rep_bytes.arg = "2015";
    309 
    310     alltypes.rep_submsg.funcs.encode = &write_repeated_submsg;
    311     alltypes.rep_submsg.arg = &rep_submsg;
    312 
    313     alltypes.rep_enum.funcs.encode = &write_repeated_varint;
    314     alltypes.rep_enum.arg = (void*)MyEnum_Truth;
    315 
    316     alltypes.rep_emptymsg.funcs.encode = &write_repeated_emptymsg;
    317 
    318     alltypes.req_limits.funcs.encode = &write_limits;
    319 
    320     /* Bind callbacks for optional fields */
    321     if (mode != 0)
    322     {
    323         alltypes.opt_int32.funcs.encode = &write_varint;
    324         alltypes.opt_int32.arg = (void*)3041;
    325 
    326         alltypes.opt_int64.funcs.encode = &write_varint;
    327         alltypes.opt_int64.arg = (void*)3042;
    328 
    329         alltypes.opt_uint32.funcs.encode = &write_varint;
    330         alltypes.opt_uint32.arg = (void*)3043;
    331 
    332         alltypes.opt_uint64.funcs.encode = &write_varint;
    333         alltypes.opt_uint64.arg = (void*)3044;
    334 
    335         alltypes.opt_sint32.funcs.encode = &write_svarint;
    336         alltypes.opt_sint32.arg = (void*)3045;
    337 
    338         alltypes.opt_sint64.funcs.encode = &write_svarint;
    339         alltypes.opt_sint64.arg = (void*)3046;
    340 
    341         alltypes.opt_bool.funcs.encode = &write_varint;
    342         alltypes.opt_bool.arg = (void*)true;
    343 
    344         alltypes.opt_fixed32.funcs.encode = &write_fixed32;
    345         alltypes.opt_fixed32.arg = &opt_fixed32;
    346 
    347         alltypes.opt_sfixed32.funcs.encode = &write_fixed32;
    348         alltypes.opt_sfixed32.arg = &opt_sfixed32;
    349 
    350         alltypes.opt_float.funcs.encode = &write_fixed32;
    351         alltypes.opt_float.arg = &opt_float;
    352 
    353         alltypes.opt_fixed64.funcs.encode = &write_fixed64;
    354         alltypes.opt_fixed64.arg = &opt_fixed64;
    355 
    356         alltypes.opt_sfixed64.funcs.encode = &write_fixed64;
    357         alltypes.opt_sfixed64.arg = &opt_sfixed64;
    358 
    359         alltypes.opt_double.funcs.encode = &write_fixed64;
    360         alltypes.opt_double.arg = &opt_double;
    361 
    362         alltypes.opt_string.funcs.encode = &write_string;
    363         alltypes.opt_string.arg = "3054";
    364 
    365         alltypes.opt_bytes.funcs.encode = &write_string;
    366         alltypes.opt_bytes.arg = "3055";
    367 
    368         alltypes.opt_submsg.funcs.encode = &write_submsg;
    369         alltypes.opt_submsg.arg = &opt_submsg;
    370 
    371         alltypes.opt_enum.funcs.encode = &write_varint;
    372         alltypes.opt_enum.arg = (void*)MyEnum_Truth;
    373 
    374         alltypes.opt_emptymsg.funcs.encode = &write_emptymsg;
    375     }
    376 
    377     alltypes.end.funcs.encode = &write_varint;
    378     alltypes.end.arg = (void*)1099;
    379 
    380     {
    381         uint8_t buffer[2048];
    382         pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
    383 
    384         /* Now encode it and check if we succeeded. */
    385         if (pb_encode(&stream, AllTypes_fields, &alltypes))
    386         {
    387             SET_BINARY_MODE(stdout);
    388             fwrite(buffer, 1, stream.bytes_written, stdout);
    389             return 0; /* Success */
    390         }
    391         else
    392         {
    393             fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream));
    394             return 1; /* Failure */
    395         }
    396     }
    397 }
    398