Create a message descriptor type.
This replaces the sentinel at the end of the pb_field_t array for each message type. git-svn-id: https://svn.kapsi.fi/jpa/nanopb-dev@1007 e3a754e5-d11d-0410-8d38-ebb782a927b9
This commit is contained in:
committed by
Petteri Aimonen
parent
dcf43a6416
commit
43b8e20744
@@ -74,7 +74,7 @@ This is the way to get the size of the message without storing it anywhere::
|
||||
|
||||
Person myperson = ...;
|
||||
pb_ostream_t sizestream = {0};
|
||||
pb_encode(&sizestream, Person_fields, &myperson);
|
||||
pb_encode(&sizestream, Person_msg, &myperson);
|
||||
printf("Encoded size is %d\n", sizestream.bytes_written);
|
||||
|
||||
**Example 2:**
|
||||
@@ -221,10 +221,10 @@ This callback reads multiple integers and prints them::
|
||||
return true;
|
||||
}
|
||||
|
||||
Field description array
|
||||
=======================
|
||||
Message descriptor
|
||||
==================
|
||||
|
||||
For using the *pb_encode* and *pb_decode* functions, you need an array of pb_field_t constants describing the structure you wish to encode. This description is usually autogenerated from .proto file.
|
||||
For using the *pb_encode* and *pb_decode* functions, you need a message descriptor describing the structure you wish to encode. This description is usually autogenerated from .proto file.
|
||||
|
||||
For example this submessage in the Person.proto file::
|
||||
|
||||
@@ -235,20 +235,27 @@ For example this submessage in the Person.proto file::
|
||||
}
|
||||
}
|
||||
|
||||
generates this field description array for the structure *Person_PhoneNumber*::
|
||||
generates these declarations and definitions for the structure *Person_PhoneNumber*::
|
||||
|
||||
typedef PB_MSG_STRUCT(2) Person_PhoneNumber_msg_t;
|
||||
extern const Person_PhoneNumber_msg_t Person_PhoneNumber_real_msg;
|
||||
#define Person_PhoneNumber_msg ((const pb_message_t*)&Person_PhoneNumber_real_msg)
|
||||
|
||||
const Person_PhoneNumber_msg_t Person_PhoneNumber_real_msg = {
|
||||
2,
|
||||
{
|
||||
|
||||
const pb_field_t Person_PhoneNumber_fields[3] = {
|
||||
{1, PB_HTYPE_REQUIRED | PB_LTYPE_STRING,
|
||||
offsetof(Person_PhoneNumber, number), 0,
|
||||
pb_membersize(Person_PhoneNumber, number), 0, 0},
|
||||
|
||||
{2, PB_HTYPE_OPTIONAL | PB_LTYPE_VARINT,
|
||||
pb_delta(Person_PhoneNumber, type, number),
|
||||
pb_delta_end(Person_PhoneNumber, type, number),
|
||||
pb_delta(Person_PhoneNumber, has_type, type),
|
||||
pb_membersize(Person_PhoneNumber, type), 0,
|
||||
&Person_PhoneNumber_type_default},
|
||||
|
||||
PB_LAST_FIELD
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ So a typical project might include these files:
|
||||
- pb_encode.h and pb_encode.c (needed for encoding messages)
|
||||
2) Protocol description (you can have many):
|
||||
- person.proto (just an example)
|
||||
- person.pb.c (autogenerated, contains initializers for const arrays)
|
||||
- person.pb.c (autogenerated, contains initializers for message descriptors)
|
||||
- person.pb.h (autogenerated, contains type declarations)
|
||||
|
||||
Features and limitations
|
||||
@@ -74,14 +74,16 @@ You should now have in *message.pb.h*::
|
||||
int32_t value;
|
||||
} Example;
|
||||
|
||||
extern const pb_field_t Example_fields[2];
|
||||
typedef PB_MSG_STRUCT(1) Example_msg_t;
|
||||
extern const Example_msg_t Example_real_msg;
|
||||
#define Example_msg ((const pb_message_t*)&Example_real_msg)
|
||||
|
||||
Now in your main program do this to encode a message::
|
||||
|
||||
Example mymessage = {42};
|
||||
uint8_t buffer[10];
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
pb_encode(&stream, Example_fields, &mymessage);
|
||||
pb_encode(&stream, Example_msg, &mymessage);
|
||||
|
||||
After that, buffer will contain the encoded message.
|
||||
The number of bytes in the message is stored in *stream.bytes_written*.
|
||||
|
||||
@@ -140,14 +140,14 @@ pb_encode
|
||||
---------
|
||||
Encodes the contents of a structure as a protocol buffers message and writes it to output stream. ::
|
||||
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_message_t *msg, const void *src_struct);
|
||||
|
||||
:stream: Output stream to write to.
|
||||
:fields: A field description array, usually autogenerated.
|
||||
:msg: A message descriptor, usually autogenerated.
|
||||
:src_struct: Pointer to the data that will be serialized.
|
||||
:returns: True on success, false on IO error, on detectable errors in field description, or if a field encoder returns false.
|
||||
|
||||
Normally pb_encode simply walks through the fields description array and serializes each field in turn. However, submessages must be serialized twice: first to calculate their size and then to actually write them to output. This causes some constraints for callback fields, which must return the same data on every call.
|
||||
Normally pb_encode simply walks through the fields description array inside the message descriptor and serializes each field in turn. However, submessages must be serialized twice: first to calculate their size and then to actually write them to output. This causes some constraints for callback fields, which must return the same data on every call.
|
||||
|
||||
pb_encode_varint
|
||||
----------------
|
||||
@@ -289,7 +289,7 @@ Field encoder for PB_LTYPE_SUBMESSAGE. Calls `pb_encode`_ to perform the actual
|
||||
bool pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
|
||||
:stream: Output stream to write to.
|
||||
:field: Field description structure. The *ptr* field must be a pointer to a field description array for the submessage.
|
||||
:field: Field description structure. The *ptr* field must be a pointer to a valid *pb_message_t* descriptor for the submessage.
|
||||
:src: Pointer to the structure where submessage data is.
|
||||
:returns: True on success, false on IO errors, pb_encode errors or if submessage size changes between calls.
|
||||
|
||||
@@ -355,10 +355,10 @@ pb_decode
|
||||
---------
|
||||
Read and decode all fields of a structure. Reads until EOF on input stream. ::
|
||||
|
||||
bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
bool pb_decode(pb_istream_t *stream, const pb_message_t *msg, void *dest_struct);
|
||||
|
||||
:stream: Input stream to read from.
|
||||
:fields: A field description array. Usually autogenerated.
|
||||
:msg: A message descriptor. Usually autogenerated.
|
||||
:dest_struct: Pointer to structure where data will be stored.
|
||||
:returns: True on success, false on IO error, on detectable errors in field description, if a field encoder returns false or if a required field is missing.
|
||||
|
||||
@@ -459,5 +459,5 @@ Field decoder for PB_LTYPE_SUBMESSAGE. Calls `pb_decode`_ to perform the actual
|
||||
:dest: Pointer to the destination structure.
|
||||
:returns: True on success, false on IO error or if `pb_decode`_ fails.
|
||||
|
||||
The *field->ptr* should be a pointer to *pb_field_t* array describing the submessage.
|
||||
The *field->ptr* should be a pointer to *pb_message_t* describing the submessage.
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ bool printfile_callback(pb_istream_t *stream, const pb_field_t *field, void *arg
|
||||
{
|
||||
FileInfo fileinfo;
|
||||
|
||||
if (!pb_decode(stream, FileInfo_fields, &fileinfo))
|
||||
if (!pb_decode(stream, FileInfo_msg, &fileinfo))
|
||||
return false;
|
||||
|
||||
printf("%-10lld %s\n", fileinfo.inode, fileinfo.name);
|
||||
@@ -59,7 +59,7 @@ bool listdir(int fd, char *path)
|
||||
strcpy(request.path, path);
|
||||
}
|
||||
|
||||
if (!pb_encode(&output, ListFilesRequest_fields, &request))
|
||||
if (!pb_encode(&output, ListFilesRequest_msg, &request))
|
||||
{
|
||||
fprintf(stderr, "Encoding failed.\n");
|
||||
return false;
|
||||
@@ -70,7 +70,7 @@ bool listdir(int fd, char *path)
|
||||
|
||||
response.file.funcs.decode = &printfile_callback;
|
||||
|
||||
if (!pb_decode(&input, ListFilesResponse_fields, &response))
|
||||
if (!pb_decode(&input, ListFilesResponse_msg, &response))
|
||||
{
|
||||
fprintf(stderr, "Decoding failed.\n");
|
||||
return false;
|
||||
|
||||
@@ -53,7 +53,7 @@ void handle_connection(int connfd)
|
||||
pb_ostream_t output = pb_ostream_from_socket(connfd);
|
||||
DIR *directory;
|
||||
|
||||
if (!pb_decode(&input, ListFilesRequest_fields, &request))
|
||||
if (!pb_decode(&input, ListFilesRequest_msg, &request))
|
||||
{
|
||||
printf("Decoding failed.\n");
|
||||
return;
|
||||
@@ -78,7 +78,7 @@ void handle_connection(int connfd)
|
||||
response.file.arg = directory;
|
||||
}
|
||||
|
||||
if (!pb_encode(&output, ListFilesResponse_fields, &response))
|
||||
if (!pb_encode(&output, ListFilesResponse_msg, &response))
|
||||
{
|
||||
printf("Encoding failed.\n");
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ class Field:
|
||||
result += ' 0,'
|
||||
|
||||
if self.ltype == 'PB_LTYPE_SUBMESSAGE':
|
||||
result += '\n &%s_fields}' % self.submsgname
|
||||
result += '\n %s_msg}' % self.submsgname
|
||||
elif self.default is None or self.htype == 'PB_HTYPE_CALLBACK':
|
||||
result += ' 0}'
|
||||
else:
|
||||
@@ -268,20 +268,24 @@ class Message:
|
||||
result += default + '\n'
|
||||
return result
|
||||
|
||||
def fields_declaration(self):
|
||||
result = 'extern const pb_field_t %s_fields[%d];' % (self.name, len(self.fields) + 1)
|
||||
def message_declaration(self):
|
||||
result = 'typedef PB_MSG_STRUCT(%d) %s_msg_t;\n' % (len(self.fields), self.name)
|
||||
result += 'extern const %s_msg_t %s_real_msg;\n' % (self.name, self.name)
|
||||
result += '#define %s_msg ((const pb_message_t*)&%s_real_msg)\n' % (self.name, self.name)
|
||||
return result
|
||||
|
||||
def fields_definition(self):
|
||||
result = 'const pb_field_t %s_fields[%d] = {\n' % (self.name, len(self.fields) + 1)
|
||||
def message_definition(self):
|
||||
result = 'const %s_msg_t %s_real_msg = {\n' % (self.name, self.name)
|
||||
result += ' %d,\n' % len(self.fields)
|
||||
|
||||
result += ' {\n\n'
|
||||
prev = None
|
||||
for field in self.ordered_fields:
|
||||
result += field.pb_field_t(prev)
|
||||
result += ',\n\n'
|
||||
prev = field.name
|
||||
|
||||
result += ' PB_LAST_FIELD\n};'
|
||||
result += ' }\n};'
|
||||
return result
|
||||
|
||||
def iterate_messages(desc, names = Names()):
|
||||
@@ -378,7 +382,7 @@ def generate_header(headername, enums, messages):
|
||||
|
||||
yield '/* Struct field encoding specification for nanopb */\n'
|
||||
for msg in messages:
|
||||
yield msg.fields_declaration() + '\n'
|
||||
yield msg.message_declaration() + '\n'
|
||||
|
||||
yield '\n#endif\n'
|
||||
|
||||
@@ -394,7 +398,7 @@ def generate_source(headername, enums, messages):
|
||||
yield '\n\n'
|
||||
|
||||
for msg in messages:
|
||||
yield msg.fields_definition() + '\n\n'
|
||||
yield msg.message_definition() + '\n\n'
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
13
pb.h
13
pb.h
@@ -112,6 +112,19 @@ typedef struct {
|
||||
uint8_t bytes[1];
|
||||
} pb_bytes_array_t;
|
||||
|
||||
/* This macro is define the type of a structure for a message with N
|
||||
* fields.
|
||||
*/
|
||||
#define PB_MSG_STRUCT(N) struct { \
|
||||
unsigned int field_count; \
|
||||
pb_field_t fields[N]; \
|
||||
}
|
||||
|
||||
/* This is the visible type for generated message structures.
|
||||
* The actual number of fields at the end will vary by message type.
|
||||
*/
|
||||
typedef PB_MSG_STRUCT(1) pb_message_t;
|
||||
|
||||
/* This structure is used for giving the callback function.
|
||||
* It is stored in the message structure and filled in by the method that
|
||||
* calls pb_decode.
|
||||
|
||||
31
pb_decode.c
31
pb_decode.c
@@ -185,7 +185,7 @@ static bool checkreturn make_string_substream(pb_istream_t *stream, pb_istream_t
|
||||
|
||||
/* Iterator for pb_field_t list */
|
||||
typedef struct {
|
||||
const pb_field_t *start;
|
||||
const pb_message_t *msg;
|
||||
const pb_field_t *current;
|
||||
int field_index;
|
||||
void *dest_struct;
|
||||
@@ -193,9 +193,10 @@ typedef struct {
|
||||
void *pSize;
|
||||
} pb_field_iterator_t;
|
||||
|
||||
static void pb_field_init(pb_field_iterator_t *iter, const pb_field_t *fields, void *dest_struct)
|
||||
static void pb_field_init(pb_field_iterator_t *iter, const pb_message_t *msg, void *dest_struct)
|
||||
{
|
||||
iter->start = iter->current = fields;
|
||||
iter->msg = msg;
|
||||
iter->current = msg->fields;
|
||||
iter->field_index = 0;
|
||||
iter->pData = (char*)dest_struct + iter->current->data_offset;
|
||||
iter->pSize = (char*)iter->pData + iter->current->size_offset;
|
||||
@@ -212,9 +213,9 @@ static bool pb_field_next(pb_field_iterator_t *iter)
|
||||
|
||||
iter->current++;
|
||||
iter->field_index++;
|
||||
if (iter->current->tag == 0)
|
||||
if (iter->field_index >= iter->msg->field_count)
|
||||
{
|
||||
iter->current = iter->start;
|
||||
iter->current = &iter->msg->fields[0];
|
||||
iter->field_index = 0;
|
||||
iter->pData = iter->dest_struct;
|
||||
prev_size = 0;
|
||||
@@ -334,15 +335,15 @@ static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_t
|
||||
}
|
||||
|
||||
/* Initialize message fields to default values, recursively */
|
||||
static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct)
|
||||
static void pb_message_set_to_defaults(const pb_message_t *msg, void *dest_struct)
|
||||
{
|
||||
pb_field_iterator_t iter;
|
||||
pb_field_init(&iter, fields, dest_struct);
|
||||
pb_field_init(&iter, msg, dest_struct);
|
||||
|
||||
/* Initialize size/has fields and apply default values */
|
||||
do
|
||||
{
|
||||
if (iter.current->tag == 0)
|
||||
if (iter.field_index >= msg->field_count)
|
||||
continue;
|
||||
|
||||
/* Initialize the size field for optional/repeated fields to 0. */
|
||||
@@ -380,15 +381,15 @@ static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_str
|
||||
* Decode all fields *
|
||||
*********************/
|
||||
|
||||
bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
|
||||
bool checkreturn pb_decode(pb_istream_t *stream, const pb_message_t *msg, void *dest_struct)
|
||||
{
|
||||
uint32_t fields_seen = 0; /* Used to check for required fields */
|
||||
pb_field_iterator_t iter;
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
pb_message_set_to_defaults(fields, dest_struct);
|
||||
pb_message_set_to_defaults(msg, dest_struct);
|
||||
|
||||
pb_field_init(&iter, fields, dest_struct);
|
||||
pb_field_init(&iter, msg, dest_struct);
|
||||
|
||||
while (stream->bytes_left)
|
||||
{
|
||||
@@ -424,9 +425,9 @@ bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void
|
||||
}
|
||||
|
||||
/* Check that all required fields (mod 31) were present. */
|
||||
for (i = 0; fields[i].tag != 0; i++)
|
||||
for (i = 0; i < msg->field_count; i++)
|
||||
{
|
||||
if (PB_HTYPE(fields[i].type) == PB_HTYPE_REQUIRED &&
|
||||
if (PB_HTYPE(msg->fields[i].type) == PB_HTYPE_REQUIRED &&
|
||||
!(fields_seen & (1 << (i & 31))))
|
||||
{
|
||||
return false;
|
||||
@@ -537,7 +538,7 @@ bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field
|
||||
if (field->ptr == NULL)
|
||||
return false;
|
||||
|
||||
status = pb_decode(&substream, (pb_field_t*)field->ptr, dest);
|
||||
status = pb_decode(&substream, (const pb_message_t*)field->ptr, dest);
|
||||
stream->state = substream.state;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@ bool pb_read(pb_istream_t *stream, uint8_t *buf, size_t count);
|
||||
|
||||
/* Decode from stream to destination struct.
|
||||
* Returns true on success, false on any failure.
|
||||
* The actual struct pointed to by dest must match the description in fields.
|
||||
* The actual struct pointed to by dest must match the description in msg.
|
||||
*/
|
||||
bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
bool pb_decode(pb_istream_t *stream, const pb_message_t *msg, void *dest_struct);
|
||||
|
||||
/* --- Helper functions ---
|
||||
* You may want to use these from your caller or callbacks.
|
||||
|
||||
13
pb_encode.c
13
pb_encode.c
@@ -140,15 +140,16 @@ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *fie
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
|
||||
bool checkreturn pb_encode(pb_ostream_t *stream, const pb_message_t *msg, const void *src_struct)
|
||||
{
|
||||
const pb_field_t *field = fields;
|
||||
const void *pData = src_struct;
|
||||
const void *pSize;
|
||||
unsigned int i;
|
||||
size_t prev_size = 0;
|
||||
|
||||
while (field->tag != 0)
|
||||
for (i = 0; i < msg->field_count; i++)
|
||||
{
|
||||
const pb_field_t *field = &msg->fields[i];
|
||||
pb_encoder_t func = PB_ENCODERS[PB_LTYPE(field->type)];
|
||||
pData = (const char*)pData + prev_size + field->data_offset;
|
||||
pSize = (const char*)pData + field->size_offset;
|
||||
@@ -193,8 +194,6 @@ bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], cons
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
field++;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -352,7 +351,7 @@ bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field
|
||||
if (field->ptr == NULL)
|
||||
return false;
|
||||
|
||||
if (!pb_encode(&substream, (pb_field_t*)field->ptr, src))
|
||||
if (!pb_encode(&substream, (const pb_message_t*)field->ptr, src))
|
||||
return false;
|
||||
|
||||
size = substream.bytes_written;
|
||||
@@ -373,7 +372,7 @@ bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field
|
||||
substream.max_size = size;
|
||||
substream.bytes_written = 0;
|
||||
|
||||
status = pb_encode(&substream, (pb_field_t*)field->ptr, src);
|
||||
status = pb_encode(&substream, (const pb_message_t*)field->ptr, src);
|
||||
|
||||
stream->bytes_written += substream.bytes_written;
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ bool pb_write(pb_ostream_t *stream, const uint8_t *buf, size_t count);
|
||||
|
||||
/* Encode struct to given output stream.
|
||||
* Returns true on success, false on any failure.
|
||||
* The actual struct pointed to by src_struct must match the description in fields.
|
||||
* The actual struct pointed to by src_struct must match the description in msg.
|
||||
* All required fields in the struct are assumed to have been filled in.
|
||||
*/
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_message_t *msg, const void *src_struct);
|
||||
|
||||
/* --- Helper functions ---
|
||||
* You may want to use these from your caller or callbacks.
|
||||
|
||||
@@ -193,13 +193,13 @@ int main()
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode with repeated int32 field")
|
||||
TEST((s = S(""), pb_decode(&s, IntegerArray_fields, &dest) && dest.data_count == 0))
|
||||
TEST((s = S("\x08\x01\x08\x02"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
TEST((s = S(""), pb_decode(&s, IntegerArray_msg, &dest) && dest.data_count == 0))
|
||||
TEST((s = S("\x08\x01\x08\x02"), pb_decode(&s, IntegerArray_msg, &dest)
|
||||
&& dest.data_count == 2 && dest.data[0] == 1 && dest.data[1] == 2))
|
||||
s = S("\x08\x01\x08\x02\x08\x03\x08\x04\x08\x05\x08\x06\x08\x07\x08\x08\x08\x09\x08\x0A");
|
||||
TEST(pb_decode(&s, IntegerArray_fields, &dest) && dest.data_count == 10 && dest.data[9] == 10)
|
||||
TEST(pb_decode(&s, IntegerArray_msg, &dest) && dest.data_count == 10 && dest.data[9] == 10)
|
||||
s = S("\x08\x01\x08\x02\x08\x03\x08\x04\x08\x05\x08\x06\x08\x07\x08\x08\x08\x09\x08\x0A\x08\x0B");
|
||||
TEST(!pb_decode(&s, IntegerArray_fields, &dest))
|
||||
TEST(!pb_decode(&s, IntegerArray_msg, &dest))
|
||||
}
|
||||
|
||||
{
|
||||
@@ -207,17 +207,17 @@ int main()
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode with packed int32 field")
|
||||
TEST((s = S("\x0A\x00"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
TEST((s = S("\x0A\x00"), pb_decode(&s, IntegerArray_msg, &dest)
|
||||
&& dest.data_count == 0))
|
||||
TEST((s = S("\x0A\x01\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
TEST((s = S("\x0A\x01\x01"), pb_decode(&s, IntegerArray_msg, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
TEST((s = S("\x0A\x0A\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
TEST((s = S("\x0A\x0A\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A"), pb_decode(&s, IntegerArray_msg, &dest)
|
||||
&& dest.data_count == 10 && dest.data[0] == 1 && dest.data[9] == 10))
|
||||
TEST((s = S("\x0A\x0B\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x0A\x0B\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B"), !pb_decode(&s, IntegerArray_msg, &dest)))
|
||||
|
||||
/* Test invalid wire data */
|
||||
TEST((s = S("\x0A\xFF"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x0A\x01"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x0A\xFF"), !pb_decode(&s, IntegerArray_msg, &dest)))
|
||||
TEST((s = S("\x0A\x01"), !pb_decode(&s, IntegerArray_msg, &dest)))
|
||||
}
|
||||
|
||||
{
|
||||
@@ -225,14 +225,14 @@ int main()
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode with unknown fields")
|
||||
TEST((s = S("\x18\x0F\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
TEST((s = S("\x18\x0F\x08\x01"), pb_decode(&s, IntegerArray_msg, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
TEST((s = S("\x19\x00\x00\x00\x00\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
TEST((s = S("\x19\x00\x00\x00\x00\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_msg, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
TEST((s = S("\x1A\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
TEST((s = S("\x1A\x00\x08\x01"), pb_decode(&s, IntegerArray_msg, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
TEST((s = S("\x1B\x08\x01"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x1D\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
TEST((s = S("\x1B\x08\x01"), !pb_decode(&s, IntegerArray_msg, &dest)))
|
||||
TEST((s = S("\x1D\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_msg, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
}
|
||||
|
||||
@@ -246,25 +246,25 @@ int main()
|
||||
COMMENT("Testing pb_decode with callbacks")
|
||||
/* Single varint */
|
||||
ref.size = 1; ref.bytes[0] = 0x55;
|
||||
TEST((s = S("\x08\x55"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
TEST((s = S("\x08\x55"), pb_decode(&s, CallbackArray_msg, &dest)))
|
||||
/* Packed varint */
|
||||
ref.size = 3; ref.bytes[0] = ref.bytes[1] = ref.bytes[2] = 0x55;
|
||||
TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_msg, &dest)))
|
||||
/* Packed varint with loop */
|
||||
ref.size = 1; ref.bytes[0] = 0x55;
|
||||
TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_msg, &dest)))
|
||||
/* Single fixed32 */
|
||||
ref.size = 4; ref.bytes[0] = ref.bytes[1] = ref.bytes[2] = ref.bytes[3] = 0xAA;
|
||||
TEST((s = S("\x0D\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
TEST((s = S("\x0D\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_msg, &dest)))
|
||||
/* Single fixed64 */
|
||||
ref.size = 8; memset(ref.bytes, 0xAA, 8);
|
||||
TEST((s = S("\x09\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
TEST((s = S("\x09\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_msg, &dest)))
|
||||
/* Unsupported field type */
|
||||
TEST((s = S("\x0B\x00"), !pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
TEST((s = S("\x0B\x00"), !pb_decode(&s, CallbackArray_msg, &dest)))
|
||||
|
||||
/* Just make sure that our test function works */
|
||||
ref.size = 1; ref.bytes[0] = 0x56;
|
||||
TEST((s = S("\x08\x55"), !pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
TEST((s = S("\x08\x55"), !pb_decode(&s, CallbackArray_msg, &dest)))
|
||||
}
|
||||
|
||||
{
|
||||
@@ -272,11 +272,11 @@ int main()
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode message termination")
|
||||
TEST((s = S(""), pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x00"), pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x08\x01\x00"), pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x08"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S(""), pb_decode(&s, IntegerArray_msg, &dest)))
|
||||
TEST((s = S("\x00"), pb_decode(&s, IntegerArray_msg, &dest)))
|
||||
TEST((s = S("\x08\x01"), pb_decode(&s, IntegerArray_msg, &dest)))
|
||||
TEST((s = S("\x08\x01\x00"), pb_decode(&s, IntegerArray_msg, &dest)))
|
||||
TEST((s = S("\x08"), !pb_decode(&s, IntegerArray_msg, &dest)))
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
|
||||
@@ -196,13 +196,13 @@ int main()
|
||||
|
||||
COMMENT("Test pb_encode with int32 array")
|
||||
|
||||
TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), "\x0A\x05\x01\x02\x03\x04\x05"))
|
||||
TEST(WRITES(pb_encode(&s, IntegerArray_msg, &msg), "\x0A\x05\x01\x02\x03\x04\x05"))
|
||||
|
||||
msg.data_count = 0;
|
||||
TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), ""))
|
||||
TEST(WRITES(pb_encode(&s, IntegerArray_msg, &msg), ""))
|
||||
|
||||
msg.data_count = 10;
|
||||
TEST(!pb_encode(&s, IntegerArray_fields, &msg))
|
||||
TEST(!pb_encode(&s, IntegerArray_msg, &msg))
|
||||
}
|
||||
|
||||
{
|
||||
@@ -212,14 +212,14 @@ int main()
|
||||
|
||||
COMMENT("Test pb_encode with float array")
|
||||
|
||||
TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg),
|
||||
TEST(WRITES(pb_encode(&s, FloatArray_msg, &msg),
|
||||
"\x0A\x04\x00\x00\xc6\x42"))
|
||||
|
||||
msg.data_count = 0;
|
||||
TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg), ""))
|
||||
TEST(WRITES(pb_encode(&s, FloatArray_msg, &msg), ""))
|
||||
|
||||
msg.data_count = 3;
|
||||
TEST(!pb_encode(&s, FloatArray_fields, &msg))
|
||||
TEST(!pb_encode(&s, FloatArray_msg, &msg))
|
||||
}
|
||||
|
||||
{
|
||||
@@ -230,7 +230,7 @@ int main()
|
||||
msg.data.funcs.encode = &fieldcallback;
|
||||
|
||||
COMMENT("Test pb_encode with callback field.")
|
||||
TEST(WRITES(pb_encode(&s, CallbackArray_fields, &msg), "\x08\x55"))
|
||||
TEST(WRITES(pb_encode(&s, CallbackArray_msg, &msg), "\x08\x55"))
|
||||
}
|
||||
|
||||
{
|
||||
@@ -239,7 +239,7 @@ int main()
|
||||
IntegerContainer msg = {{5, {1,2,3,4,5}}};
|
||||
|
||||
COMMENT("Test pb_encode with packed array in a submessage.")
|
||||
TEST(WRITES(pb_encode(&s, IntegerContainer_fields, &msg),
|
||||
TEST(WRITES(pb_encode(&s, IntegerContainer_msg, &msg),
|
||||
"\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"))
|
||||
}
|
||||
|
||||
@@ -254,8 +254,8 @@ int main()
|
||||
msg2.submsg.submsg.data.funcs.encode = &fieldcallback;
|
||||
|
||||
COMMENT("Test pb_encode with callback field in a submessage.")
|
||||
TEST(WRITES(pb_encode(&s, CallbackContainer_fields, &msg), "\x0A\x02\x08\x55"))
|
||||
TEST(WRITES(pb_encode(&s, CallbackContainerContainer_fields, &msg2),
|
||||
TEST(WRITES(pb_encode(&s, CallbackContainer_msg, &msg), "\x0A\x02\x08\x55"))
|
||||
TEST(WRITES(pb_encode(&s, CallbackContainerContainer_msg, &msg2),
|
||||
"\x0A\x04\x0A\x02\x08\x55"))
|
||||
|
||||
/* Misbehaving callback: varying output between calls */
|
||||
@@ -264,9 +264,9 @@ int main()
|
||||
msg2.submsg.submsg.data.funcs.encode = &crazyfieldcallback;
|
||||
msg2.submsg.submsg.data.arg = &state;
|
||||
|
||||
TEST(!pb_encode(&s, CallbackContainer_fields, &msg))
|
||||
TEST(!pb_encode(&s, CallbackContainer_msg, &msg))
|
||||
state = 1;
|
||||
TEST(!pb_encode(&s, CallbackContainerContainer_fields, &msg2))
|
||||
TEST(!pb_encode(&s, CallbackContainerContainer_msg, &msg2))
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
|
||||
@@ -17,7 +17,7 @@ bool print_person(pb_istream_t *stream)
|
||||
int i;
|
||||
Person person;
|
||||
|
||||
if (!pb_decode(stream, Person_fields, &person))
|
||||
if (!pb_decode(stream, Person_msg, &person))
|
||||
return false;
|
||||
|
||||
/* Now the decoding is done, rest is just to print stuff out. */
|
||||
|
||||
@@ -84,8 +84,8 @@ int main()
|
||||
testmessage.fixed64value.funcs.decode = &print_fixed64;
|
||||
testmessage.fixed64value.arg = "fixed64value: %lld\n";
|
||||
|
||||
if (!pb_decode(&stream, TestMessage_fields, &testmessage))
|
||||
if (!pb_decode(&stream, TestMessage_msg, &testmessage))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ int main()
|
||||
pb_ostream_t stream = {&streamcallback, stdout, SIZE_MAX, 0};
|
||||
|
||||
/* Now encode it and check if we succeeded. */
|
||||
if (pb_encode(&stream, Person_fields, &person))
|
||||
if (pb_encode(&stream, Person_msg, &person))
|
||||
return 0; /* Success */
|
||||
else
|
||||
return 1; /* Failure */
|
||||
|
||||
@@ -58,7 +58,7 @@ int main()
|
||||
testmessage.submsg.fixed32value.funcs.encode = &encode_fixed32;
|
||||
testmessage.submsg.fixed64value.funcs.encode = &encode_fixed64;
|
||||
|
||||
if (!pb_encode(&stream, TestMessage_fields, &testmessage))
|
||||
if (!pb_encode(&stream, TestMessage_msg, &testmessage))
|
||||
return 1;
|
||||
|
||||
if (fwrite(buffer, stream.bytes_written, 1, stdout) != 1)
|
||||
|
||||
Reference in New Issue
Block a user