Reputation: 962
I have a somewhat deeply nested .proto. Message is a union, Update is a member of that union (ignoring the others for the sake of this question), Update contains a repeated Config (added just once for simplicity), Config contains actual data (ints here for simplicity).
message Message {
message Config {
int64 job = 1;
int64 job2 = 2;
}
message Update {
repeated Config jobs = 1;
}
oneof message {
Update update = 1;
}
}
Right now I'm just trying to encode and decode (useless, but just to get it working). It seems to encode/decode okay, doesn't throw any errors. But whatever I put in as data to my job and job2, it always spits back a zero on the other end.
void main(void)
{
/* This is the buffer where we will store our message. */
uint8_t buffer[128];
size_t message_length;
bool status;
/* Encode our message */
{
/* Create a stream that will write to our buffer. */
pb_ostream_t ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
/* Fill in the message */
Message_Config my_job_config_struct =
{
.job = 345,
.job2 = 988,
};
/* Configure it as a union, add the encode func for the repeated field encoding */
Message message = {
.which_message = Message_update_tag,
.my_message.update = {
.jobs = {
.arg = &my_job_config_struct,
.funcs.encode = &encode_Config,
},
}
};
/* Now we are ready to encode the message! */
status = pb_encode(&ostream, Message_fields, &message);
message_length = ostream.bytes_written;
/* Then just check for any errors.. */
if (!status)
{
printf("\nEncoding failed: %s\n", PB_GET_ERROR(&ostream));
return 1;
}
}
printf("~~~~~~~~~~~~~~~~Done Encoding");
/* Now we could transmit the message over network, store it in a file or
* wrap it to a pigeon's leg.
*/
/* But because we are lazy, we will just decode it immediately. */
{
/* Create a stream that reads from the buffer. */
pb_istream_t istream = pb_istream_from_buffer(buffer, message_length);
/* Find out the union type */
const pb_msgdesc_t *type = decode_Update_type(&istream);
/* Now we are ready to decode the message. */
if (type == Message_ConfigUpdate_fields)
{
Message_ConfigUpdate msg = Message_ConfigUpdate_init_zero;
msg.jobs.funcs.decode = &decode_Config;
status = decode_Update_contents(&istream, Message_ConfigUpdate_fields, &msg);
}
else
{
LOG_ERR("Sad :( no type match");
}
/* Check for errors... */
if (!status)
{
LOG_ERR("Decoding failed: %s\n", PB_GET_ERROR(&istream));
return 1;
}
}
return 0;
}
bool encode_Config(pb_ostream_t *stream, const pb_field_t *field, void *const *arg)
{
/* Cast the args back to config type */
struct Message_Config *update_submessage =
(struct Message_Config *)(*arg);
if (!pb_encode_tag_for_field(stream, field))
{
return false;
}
/* Encode the struct as a submessage */
/* If we were repeating this field we'd loop here and encode multiple times */
bool ret = pb_encode_submessage(stream,
Message_Config_fields, &update_submessage);
return ret;
}
const pb_msgdesc_t* decode_Update_type(pb_istream_t *stream)
{
pb_wire_type_t wire_type;
uint32_t tag;
bool eof;
while (pb_decode_tag(stream, &wire_type, &tag, &eof))
{
if (wire_type == PB_WT_STRING)
{
pb_field_iter_t iter;
if (pb_field_iter_begin(&iter, Message_fields, NULL) &&
pb_field_iter_find(&iter, tag))
{
/* Found our field. */
return iter.submsg_desc;
}
}
/* Wasn't our field.. */
pb_skip_field(stream, wire_type);
}
return NULL;
}
bool decode_Update_contents(pb_istream_t *stream, const pb_msgdesc_t *messagetype, void *dest_struct)
{
bool status = true;
pb_istream_t substream;
if (!pb_make_string_substream(stream, &substream))
{return false;}
/* messagetype = Message_ConfigUpdate_fields, dest_struct = type Message_ConfigUpdate*/
status &= pb_decode(&substream, messagetype, dest_struct);
pb_close_string_substream(stream, &substream);
return status;
}
bool decode_Config(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
Message_Config config_struct = Message_Config_init_zero;
bool ret = pb_decode(&stream, Message_Config_fields, &config_struct);
printf("job: %i", config_struct.job);
printf("job2: %i", config_struct.job2);
return ret;
}
Based on what I put into the ints in this example, I expect them to print out with job = 345, job2 = 988, but this is the actual output I get
00> I: ~~~~~~~~~~~~~~~~Done Encoding
00> I: job: 0
00> I: job2: 0
I've tried making the field not repeated and changing the encode/decode calls accordingly, and the ints pass through just fine. There seems to be something wrong with either my encoding or my decoding of the repeated submessage and I haven't been able to narrow it down. Any hints from a second pair eyes would be greatly appreciated.
Upvotes: 1
Views: 140