Skip to content

Instantly share code, notes, and snippets.

@vpetrigo
Created August 22, 2019 09:57
Show Gist options
  • Save vpetrigo/df85bbb8197e3be76f644bb8290444c4 to your computer and use it in GitHub Desktop.
Save vpetrigo/df85bbb8197e3be76f644bb8290444c4 to your computer and use it in GitHub Desktop.
Pack repeated fields with Nanopb library
#include <pb_decode.h>
#include <pb_encode.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include "Test.pb.h"
bool str_encode(pb_ostream_t *stream, const pb_field_t *field,
void *const *arg) {
const char *str = *arg;
if (!pb_encode_tag_for_field(stream, field)) {
return false;
}
return pb_encode_string(stream, (unsigned char *)str, strlen(str));
}
struct repeated {
void **repeated_f;
int index;
size_t max_size;
};
bool req_encode(pb_ostream_t *stream, const pb_field_t *field,
void *const *arg) {
struct repeated *req = *arg;
while (req->index < req->max_size) {
SearchRequest *sreq = ((SearchRequest **)req->repeated_f)[req->index];
printf("%s: Try to encode: %s\n", __func__, sreq->query.arg);
++req->index;
if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) {
return false;
}
if (!pb_encode_submessage(stream, SearchRequest_fields, sreq)) {
return false;
}
}
return true;
}
int main(void) {
const char *str1 = "Hello";
const char *str2 = "World";
unsigned char buffer[128];
size_t message_length;
bool status;
Result result_msg = Result_init_default;
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof buffer);
SearchRequest first = {
.query = {.funcs = {.encode = str_encode}, .arg = str1}};
SearchRequest second = {
.query = {.funcs = {.encode = str_encode}, .arg = str2}};
SearchRequest *requests[] = {&first, &second};
struct repeated r1 = {.repeated_f = requests, .index = 0, .max_size = 2};
result_msg.requests.funcs.encode = req_encode;
result_msg.requests.arg = &r1;
status = pb_encode(&stream, Result_fields, &result_msg);
message_length = stream.bytes_written;
if (!status) {
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
return -1;
}
printf("Success: %zu written\n", message_length);
for (size_t i = 0; i < message_length; ++i) {
printf("%02hhx", buffer[i]);
}
puts("");
return 0;
}
syntax = "proto3";
message SearchRequest {
string query = 1;
}
message Result {
repeated SearchRequest requests = 1;
}
@vpetrigo
Copy link
Author

@ssevans87 would you tell whether snippet above was helpful?

@shockzort
Copy link

shockzort commented Apr 6, 2022

@vpetrigo Hello. I can tell, the snippet above was very helpful for me.
due to your example I was able to pack and unpack something more complex. Thanks!

@Sahat-fahim
Copy link

Thanks a lot for the snippet!!! it was very helpful for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment