17ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Decoding testcase for callback fields.
27ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * Run e.g. ./test_encode_callbacks | ./test_decode_callbacks
37ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen */
47ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
57ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <stdio.h>
67ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <pb_decode.h>
77ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include "callbacks.pb.h"
87ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include "test_helpers.h"
97ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool print_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{
127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    uint8_t buffer[1024] = {0};
137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    /* We could read block-by-block to avoid the large buffer... */
157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    if (stream->bytes_left > sizeof(buffer) - 1)
167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        return false;
177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    if (!pb_read(stream, buffer, stream->bytes_left))
197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        return false;
207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    /* Print the string, in format comparable with protoc --decode.
227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen     * Format comes from the arg defined in main().
237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen     */
247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    printf((char*)*arg, buffer);
257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    return true;
267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen}
277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool print_int32(pb_istream_t *stream, const pb_field_t *field, void **arg)
297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{
307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    uint64_t value;
317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    if (!pb_decode_varint(stream, &value))
327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        return false;
337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    printf((char*)*arg, (long)value);
357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    return true;
367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen}
377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool print_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{
407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    uint32_t value;
417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    if (!pb_decode_fixed32(stream, &value))
427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        return false;
437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    printf((char*)*arg, (long)value);
457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    return true;
467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen}
477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool print_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{
507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    uint64_t value;
517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    if (!pb_decode_fixed64(stream, &value))
527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        return false;
537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    printf((char*)*arg, (long)value);
557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    return true;
567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen}
577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenint main()
597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{
607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    uint8_t buffer[1024];
617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    size_t length;
627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    pb_istream_t stream;
637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    /* Note: empty initializer list initializes the struct with all-0.
647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen     * This is recommended so that unused callbacks are set to NULL instead
657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen     * of crashing at runtime.
667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen     */
677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    TestMessage testmessage = {{{NULL}}};
687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    SET_BINARY_MODE(stdin);
707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    length = fread(buffer, 1, 1024, stdin);
717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    stream = pb_istream_from_buffer(buffer, length);
727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.submsg.stringvalue.funcs.decode = &print_string;
747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.submsg.stringvalue.arg = "submsg {\n  stringvalue: \"%s\"\n";
757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.submsg.int32value.funcs.decode = &print_int32;
767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.submsg.int32value.arg = "  int32value: %ld\n";
777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.submsg.fixed32value.funcs.decode = &print_fixed32;
787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.submsg.fixed32value.arg = "  fixed32value: %ld\n";
797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.submsg.fixed64value.funcs.decode = &print_fixed64;
807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.submsg.fixed64value.arg = "  fixed64value: %ld\n}\n";
817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.stringvalue.funcs.decode = &print_string;
837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.stringvalue.arg = "stringvalue: \"%s\"\n";
847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.int32value.funcs.decode = &print_int32;
857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.int32value.arg = "int32value: %ld\n";
867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.fixed32value.funcs.decode = &print_fixed32;
877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.fixed32value.arg = "fixed32value: %ld\n";
887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.fixed64value.funcs.decode = &print_fixed64;
897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.fixed64value.arg = "fixed64value: %ld\n";
907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.repeatedstring.funcs.decode = &print_string;
917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    testmessage.repeatedstring.arg = "repeatedstring: \"%s\"\n";
927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    if (!pb_decode(&stream, TestMessage_fields, &testmessage))
947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen        return 1;
957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen
967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen    return 0;
977ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen}
98