Reputation: 311
I'm using nanopb and have so far been more than pleased with it, but have run into an issue: It seems to fail when encoding/decoding nested repeated messages.
This is a simple example of a proto that will fail:
import "nanopb.proto";
package tester;
message Proto1 {
message DoubleNestor {
bool worky = 1;
}
message Nestor {
bool working = 1;
repeated DoubleNestor doubleNestor = 2 [(nanopb).max_count = 4];
}
uint32 status_code = 1;
repeated Nestor nestor = 2 [(nanopb).max_count = 2];
}
The generated structs look perfect, but running this code on the compiled proto will fail on the last line with a core dump:
uint8_t buffer[1000];
size_t message_length;
bool status;
tester_Proto1 tmp = tester_Proto1_init_zero;
tmp.status_code = 1;
tmp.nestor[0].working = true;
tmp.nestor[0].doubleNestor[3].worky = true;
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
status = pb_encode(&stream, tester_Proto1_fields, &tmp);
message_length = stream.bytes_written;
if (!status) {
printf("FAILED encoding");
return 1;
}
tester_Proto1 dec = tester_Proto1_init_zero;
/* Create a stream that reads from the buffer. */
pb_istream_t stream2 = pb_istream_from_buffer(buffer, message_length);
/* Now we are ready to decode the message. */
status = pb_decode(&stream2, tester_Proto1_fields, &dec);
/* Check for errors... */
if (!status)
{
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}
assert(tmp.status_code == dec.status_code);
assert(tmp.nestor[0].doubleNestor[3].worky == dec.nestor[0].doubleNestor[3].worky);
I've tested the same thing without the DoubleNestor, and that's working just fine. Am I doing something wrong, or is this an actual issue with nanopb?
Upvotes: 2
Views: 95
Reputation: 311
This turned out to be me misusing nanopg.
It needs to be manually specified how many repeated messages the struct has.
So in the above, it would work adding a tmp.nestor_count = 2
for the outer repeated message and tmp.nestor[i].doubleNestor[j].nestor_count = 4
for the inner. So if we ignore the inner doubleNestor, the full correct usage would be:
uint8_t buffer[1000];
size_t message_length;
bool status;
tester_Proto1 tmp = tester_Proto1_init_zero;
tmp.status_code = 1;
tmp.nestor_count = 2;
tmp.nestor[0].working = true;
tmp.nestor[1].working = true;
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
status = pb_encode(&stream, tester_Proto1_fields, &tmp);
message_length = stream.bytes_written;
if (!status) {
return 1;
}
tester_Proto1 dec = tester_Proto1_init_zero;
pb_istream_t stream2 = pb_istream_from_buffer(buffer, message_length);
/* Now we are ready to decode the message. */
status = pb_decode(&stream2, tester_Proto1_fields, &dec);
/* Check for errors... */
if (!status)
{
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}
assert(tmp.status_code == dec.status_code);
assert(tmp.nestor_count == dec.nestor_count);
assert(tmp.nestor[0].working == dec.nestor[0].working);
```
Upvotes: 1