mirror of
https://github.com/google/pebble.git
synced 2025-08-11 17:08:11 -04:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
22
third_party/nanopb/tests/oneof_callback/SConscript
vendored
Normal file
22
third_party/nanopb/tests/oneof_callback/SConscript
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Test decoder callback support inside oneofs.
|
||||
|
||||
Import('env')
|
||||
|
||||
env.NanopbProto('oneof')
|
||||
|
||||
enc = env.Program(['encode_oneof.c',
|
||||
'oneof.pb.c',
|
||||
'$COMMON/pb_encode.o',
|
||||
'$COMMON/pb_common.o'])
|
||||
|
||||
dec = env.Program(['decode_oneof.c',
|
||||
'oneof.pb.c',
|
||||
'$COMMON/pb_decode.o',
|
||||
'$COMMON/pb_common.o'])
|
||||
|
||||
for i in range(1,7):
|
||||
# Encode message, then decode with protoc and test program and compare.
|
||||
e = env.RunTest("message%d.pb" % i, enc, ARGS = [str(i)])
|
||||
d1 = env.Decode([e, "oneof.proto"], MESSAGE = "OneOfMessage")
|
||||
d2 = env.RunTest("message%d.txt" % i, [dec, e])
|
||||
env.Compare([d1, d2])
|
174
third_party/nanopb/tests/oneof_callback/decode_oneof.c
vendored
Normal file
174
third_party/nanopb/tests/oneof_callback/decode_oneof.c
vendored
Normal file
|
@ -0,0 +1,174 @@
|
|||
/* Decode a message using callbacks inside oneof fields */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pb_decode.h>
|
||||
#include <assert.h>
|
||||
#include "oneof.pb.h"
|
||||
#include "test_helpers.h"
|
||||
#include "unittests.h"
|
||||
|
||||
/* This is a nanopb-0.4 style global callback, that is referred by function name
|
||||
* and does not have to be bound separately to the message. It also allows defining
|
||||
* a custom data type for the field in the structure.
|
||||
*/
|
||||
bool SubMsg3_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field)
|
||||
{
|
||||
if (istream && field->tag == SubMsg3_strvalue_tag)
|
||||
{
|
||||
/* We could e.g. malloc some memory and assign it to our custom datatype
|
||||
* in the message structure here, accessible by field->pData. But in
|
||||
* this example we just print the string directly.
|
||||
*/
|
||||
|
||||
uint8_t buffer[64];
|
||||
int strlen = istream->bytes_left;
|
||||
|
||||
if (strlen > sizeof(buffer) - 1)
|
||||
return false;
|
||||
|
||||
buffer[strlen] = '\0';
|
||||
|
||||
if (!pb_read(istream, buffer, strlen))
|
||||
return false;
|
||||
|
||||
printf(" strvalue: \"%s\"\n", buffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The two callbacks below are traditional callbacks that use function pointers
|
||||
* defined in pb_callback_t.
|
||||
*/
|
||||
bool print_int32(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint64_t value;
|
||||
if (!pb_decode_varint(stream, &value))
|
||||
return false;
|
||||
|
||||
printf((char*)*arg, (int)value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool print_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint8_t buffer[64];
|
||||
int strlen = stream->bytes_left;
|
||||
|
||||
if (strlen > sizeof(buffer) - 1)
|
||||
return false;
|
||||
|
||||
buffer[strlen] = '\0';
|
||||
|
||||
if (!pb_read(stream, buffer, strlen))
|
||||
return false;
|
||||
|
||||
/* Print the string, in format comparable with protoc --decode.
|
||||
* Format comes from the arg defined in main().
|
||||
*/
|
||||
printf((char*)*arg, buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The callback below is a message-level callback which is called before each
|
||||
* submessage is encoded. It is used to set the pb_callback_t callbacks inside
|
||||
* the submessage. The reason we need this is that different submessages share
|
||||
* storage inside oneof union, and before we know the message type we can't set
|
||||
* the callbacks without overwriting each other.
|
||||
*/
|
||||
bool msg_callback(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
/* Print the prefix field before the submessages.
|
||||
* This also demonstrates how to access the top level message fields
|
||||
* from callbacks.
|
||||
*/
|
||||
OneOfMessage *topmsg = field->message;
|
||||
printf("prefix: %d\n", (int)topmsg->prefix);
|
||||
|
||||
if (field->tag == OneOfMessage_submsg1_tag)
|
||||
{
|
||||
SubMsg1 *msg = field->pData;
|
||||
printf("submsg1 {\n");
|
||||
msg->array.funcs.decode = print_int32;
|
||||
msg->array.arg = " array: %d\n";
|
||||
}
|
||||
else if (field->tag == OneOfMessage_submsg2_tag)
|
||||
{
|
||||
SubMsg2 *msg = field->pData;
|
||||
printf("submsg2 {\n");
|
||||
msg->strvalue.funcs.decode = print_string;
|
||||
msg->strvalue.arg = " strvalue: \"%s\"\n";
|
||||
}
|
||||
else if (field->tag == OneOfMessage_submsg3_tag)
|
||||
{
|
||||
/* Because SubMsg3 callback is bound by function name, we do not
|
||||
* need to initialize anything here. But we just print a string
|
||||
* to get protoc-equivalent formatted output from the testcase.
|
||||
*/
|
||||
printf("submsg3 {\n");
|
||||
}
|
||||
|
||||
/* Once we return true, pb_dec_submessage() will go on to decode the
|
||||
* submessage contents. But if we want, we can also decode it ourselves
|
||||
* above and leave stream->bytes_left at 0 value, inhibiting automatic
|
||||
* decoding.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
OneOfMessage msg = OneOfMessage_init_zero;
|
||||
pb_istream_t stream;
|
||||
size_t count;
|
||||
|
||||
SET_BINARY_MODE(stdin);
|
||||
count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
|
||||
if (!feof(stdin))
|
||||
{
|
||||
fprintf(stderr, "Message does not fit in buffer\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set up the cb_values callback, which will in turn set up the callbacks
|
||||
* for each oneof field once the field tag is known. */
|
||||
msg.cb_values.funcs.decode = msg_callback;
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
if (!pb_decode(&stream, OneOfMessage_fields, &msg))
|
||||
{
|
||||
fprintf(stderr, "Decoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This is just printing for the test case logic */
|
||||
if (msg.which_values == OneOfMessage_intvalue_tag)
|
||||
{
|
||||
printf("prefix: %d\n", (int)msg.prefix);
|
||||
printf("intvalue: %d\n", (int)msg.values.intvalue);
|
||||
}
|
||||
else if (msg.which_values == OneOfMessage_strvalue_tag)
|
||||
{
|
||||
printf("prefix: %d\n", (int)msg.prefix);
|
||||
printf("strvalue: \"%s\"\n", msg.values.strvalue);
|
||||
}
|
||||
else if (msg.which_values == OneOfMessage_submsg3_tag &&
|
||||
msg.values.submsg3.which_values == SubMsg3_intvalue_tag)
|
||||
{
|
||||
printf(" intvalue: %d\n", (int)msg.values.submsg3.values.intvalue);
|
||||
printf("}\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("}\n");
|
||||
}
|
||||
printf("suffix: %d\n", (int)msg.suffix);
|
||||
|
||||
assert(msg.prefix == 123);
|
||||
assert(msg.suffix == 321);
|
||||
|
||||
return 0;
|
||||
}
|
126
third_party/nanopb/tests/oneof_callback/encode_oneof.c
vendored
Normal file
126
third_party/nanopb/tests/oneof_callback/encode_oneof.c
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* Encode a message using callbacks inside oneof fields.
|
||||
* For encoding, callbacks inside oneofs require nothing special
|
||||
* so this is just normal callback usage.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pb_encode.h>
|
||||
#include "oneof.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
/* This is a nanopb-0.4 style global callback, that is referred by function name
|
||||
* and does not have to be bound separately to the message. It also allows defining
|
||||
* a custom data type for the field in the structure.
|
||||
*/
|
||||
bool SubMsg3_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field)
|
||||
{
|
||||
if (ostream && field->tag == SubMsg3_strvalue_tag)
|
||||
{
|
||||
/* Our custom data type is char* */
|
||||
const char *str = *(const char**)field->pData;
|
||||
|
||||
if (!pb_encode_tag_for_field(ostream, field))
|
||||
return false;
|
||||
|
||||
return pb_encode_string(ostream, (const uint8_t*)str, strlen(str));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The two callbacks below are traditional callbacks that use function pointers
|
||||
* defined in pb_callback_t.
|
||||
*/
|
||||
bool encode_int32_array(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
if (!pb_encode_varint(stream, i))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
const char *str = "mystring";
|
||||
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
return pb_encode_string(stream, (const uint8_t*)str, strlen(str));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
OneOfMessage msg = OneOfMessage_init_zero;
|
||||
pb_ostream_t stream;
|
||||
int option;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: encode_oneof [number]\n");
|
||||
return 1;
|
||||
}
|
||||
option = atoi(argv[1]);
|
||||
|
||||
/* Prefix and suffix are used to test that the union does not disturb
|
||||
* other fields in the same message. */
|
||||
msg.prefix = 123;
|
||||
|
||||
/* We encode one of the 'values' fields based on command line argument */
|
||||
if (option == 1)
|
||||
{
|
||||
msg.which_values = OneOfMessage_intvalue_tag;
|
||||
msg.values.intvalue = 999;
|
||||
}
|
||||
else if (option == 2)
|
||||
{
|
||||
msg.which_values = OneOfMessage_strvalue_tag;
|
||||
strcpy(msg.values.strvalue, "abcd");
|
||||
}
|
||||
else if (option == 3)
|
||||
{
|
||||
msg.which_values = OneOfMessage_submsg1_tag;
|
||||
msg.values.submsg1.array.funcs.encode = encode_int32_array;
|
||||
}
|
||||
else if (option == 4)
|
||||
{
|
||||
msg.which_values = OneOfMessage_submsg2_tag;
|
||||
msg.values.submsg2.strvalue.funcs.encode = encode_string;
|
||||
}
|
||||
else if (option == 5)
|
||||
{
|
||||
msg.which_values = OneOfMessage_submsg3_tag;
|
||||
msg.values.submsg3.which_values = SubMsg3_intvalue_tag;
|
||||
msg.values.submsg3.values.intvalue = 1234;
|
||||
}
|
||||
else if (option == 6)
|
||||
{
|
||||
msg.which_values = OneOfMessage_submsg3_tag;
|
||||
msg.values.submsg3.which_values = SubMsg3_strvalue_tag;
|
||||
msg.values.submsg3.values.strvalue = "efgh";
|
||||
}
|
||||
|
||||
msg.suffix = 321;
|
||||
|
||||
stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
if (pb_encode(&stream, OneOfMessage_fields, &msg))
|
||||
{
|
||||
SET_BINARY_MODE(stdout);
|
||||
fwrite(buffer, 1, stream.bytes_written, stdout);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
}
|
41
third_party/nanopb/tests/oneof_callback/oneof.proto
vendored
Normal file
41
third_party/nanopb/tests/oneof_callback/oneof.proto
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
syntax = "proto3";
|
||||
|
||||
import 'nanopb.proto';
|
||||
|
||||
// Repeated callback inside submessage inside oneof
|
||||
message SubMsg1
|
||||
{
|
||||
repeated int32 array = 1;
|
||||
}
|
||||
|
||||
// String callback inside submessage inside oneof
|
||||
message SubMsg2
|
||||
{
|
||||
string strvalue = 1;
|
||||
}
|
||||
|
||||
// String callback directly inside oneof
|
||||
message SubMsg3
|
||||
{
|
||||
oneof values
|
||||
{
|
||||
int32 intvalue = 1;
|
||||
string strvalue = 2 [(nanopb).callback_datatype = "const char*"];
|
||||
}
|
||||
}
|
||||
|
||||
message OneOfMessage
|
||||
{
|
||||
option (nanopb_msgopt).submsg_callback = true;
|
||||
|
||||
int32 prefix = 1;
|
||||
oneof values
|
||||
{
|
||||
int32 intvalue = 5;
|
||||
string strvalue = 6 [(nanopb).max_size = 8];
|
||||
SubMsg1 submsg1 = 7;
|
||||
SubMsg2 submsg2 = 8;
|
||||
SubMsg3 submsg3 = 9;
|
||||
}
|
||||
int32 suffix = 99;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue