0

Since protobuf does not support the uint16_t datatype, I have a field below describing what I have in place.

uint32_t fingerprints = 1 [packed=true];

To save space, I have a C++ program that packs together two uint16_t values and add them that way, here is an example:

uint16_t value1 = 100; // Arbitrary values
uint16_t value2 = 200;
protoObject.add_fingerprints((uint32_t)value1 << 16) +  value2;

To deserialize them, I do:

uint16_t value1 = protoObject->fingerprints(i) >> 16;
uint16_t value2 = protoObject->fingerprints(i) & 0x0000FFFF;

However, it seems like this does not produce the values I want, and the values after deserialization does not match the values before it. Is there something special protobuf does that prevents me from doing this?

Baiqing
  • 1,223
  • 2
  • 9
  • 21
  • Does your code work if you replace `protoObject->fingerprints(i)` with a pure `uint32_t`? – DazWilkin Aug 03 '22 at 22:49
  • Yes, I've tested the combine and split operations using pure uint32_t and uint16_t datatypes, it works just fine. – Baiqing Aug 03 '22 at 23:05
  • @for_stack's answer is spot and, and for good measure it's a bad idea to have something like you'd proposed. The .proto file is a contract / interface spec between two separate systems. Your extra packing of 2 uint16's into 1 unint32 is like a hidden clause that no one else knows about, until you tell them! Generally, it's better to just stick with the .proto. – bazza Aug 05 '22 at 19:26

1 Answers1

0

To save space, I have a C++ program that packs together two uint16_t values and add them that way

No bother to do that. Protobuf uses variable length encoding to serialize uint32_t, which will do 'pack' for you to save space, i.e. for an uint16_t number, protobuf will not encode it to 4 bytes, instead, it might encode it to less than 2 bytes, depends on the number.

for_stack
  • 21,012
  • 4
  • 35
  • 48