protobuf-c estender a solução alternativa

protobuf-c infelizmente não é compatível com a diretiva extend , como:

message extendingmsg {

required
string name = 1;

extend msg
{
optional extendingmsg msg_ext
= 1000;
};
};

Mas há uma solução alternativa, ou seja, o membro base.unknown_fields da mensagem base. O campo desconhecido para uma mensagem é um campo delimitado por comprimento , então ele começa com o comprimento da carga útil codificado na codificação varint seguido pela própria carga útil – a mensagem de extensão.

Assim, você faz isso:
– descompacte o protobuf como o tipo de mensagem base (‘msg’ no exemplo acima)
– a mensagem de extensão (‘extendingmsg’ acima) será (provavelmente) o primeiro e único campo desconhecido.
– decodifique o varint de msg-> base.unknown_fields [0] , certifique-se de manter o controle do tamanho do varint em si (daí a var -parte de varint )
– agora pule o varint e decodifique a carga restante conforme sua tipo de mensagem (‘extendingmsg’ acima).

Ou em código:

int handle_protobuf_extendingmsg (unsigned char *buf, int len) {
msg
*m;
extendingmsg
*em;
int vlen;
uint64_t plen;

/* Unpack containign msg message. */
if (!(m = msg__unpack(NULL, len, buf)))
return -1;

if (m->base.n_unknown_fields < 1) {
msg__free_unpacked
(m, NULL);
return -1;
}

/* The message starts past the varint-encoded length. */
plen
= rd_varint_decode_u64(
m
->base.unknown_fields[0].data,
m
->base.unknown_fields[0].len, &vlen);
if (vlen <= 0) {
/* varint decode failed */
msg__free_unpacked
(m, NULL);
return -1;
}

/* Unpack the extendingmsg past the varint */
if (!(em =
extendingmsg__unpack
(NULL,
m
->base.unknown_fields[0].len-vlen,
m
->base.unknown_fields[0].data+vlen))) {
msg__free_unpacked
(m, NULL);
return -1;
}


/* em and e are now unpacked and ready to use
* as two separeate protobuf messages. */

printf
("name: %sn", em->name);


extendingmsg__free_unpacked
(em, NULL);
msg__free_unpacked
(m, NULL);
return 0;
}

O código acima utiliza o decodificador varint do librd, que pode ser encontrado aqui:
https://github.com/edenhill/librd