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