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 13static 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 19static 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 25static 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 31static 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 37static 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 43static 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 50static 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 57static 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 71static 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 85static 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 99static 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 113static 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 127static 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 143static 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 161static 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 176int 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