Module serial::protobuf
Protocol Buffers wire format (proto3 binary encoding, https://protobuf.dev/programming-guides/encoding/).
This is a wire-format primitive library, not a .proto-file IDL
compiler (SafeC has no field-name/field-number reflection to drive code
generation from a schema — see std/serial/value.h's top comment on the
same limitation for JSON). Making a struct protobuf-serializable means
writing 'to_proto()'/'from_proto()' methods by hand that call these
primitives with the field numbers your .proto schema assigns:
// .proto: message Point { int32 x = 1; int32 y = 2; }
struct Point { int x; int y; };
struct String Point::to_proto() const {
struct String out = String::new();
pb_write_int64_field(&out, 1, (long long)self.x);
pb_write_int64_field(&out, 2, (long long)self.y);
return out;
}
struct Point Point::from_proto(const unsigned char* data, unsigned long len, int* ok) {
struct Point p;
p.x = 0; p.y = 0;
struct PbReader r = PbReader::new(data);
int good = 1;
while (r.has_more()) {
int field; int wireType;
if (!r.read_tag(&field, &wireType)) { good = 0; break; }
if (field == 1 && wireType == PB_WIRE_VARINT) {
long long v; r.read_int64(&v); p.x = (int)v;
} else if (field == 2 && wireType == PB_WIRE_VARINT) {
long long v; r.read_int64(&v); p.y = (int)v;
} else if (!r.skip_field(wireType)) { good = 0; break; }
}
if (ok != (int*)0) { *ok = good; }
return p;
}
Interoperates with real protobuf implementations in other languages —
the wire format itself (varint, tags, zigzag, length-delimited,
fixed32/fixed64) is exactly what protoc-generated code produces, field
numbers and wire types are the only thing that has to match by hand
since there's no shared .proto schema driving both sides here.
Structs
| PbReader |
Functions
| pb_write_varint | |
| pb_write_tag | |
| pb_write_int64_field | int32/int64: plain varint of the value's bit pattern (protobuf's own quirk: a negative int32 is sign-extended to 64 bits before varint encoding, so it always takes the full 10 bytes on the wire — this matches protoc's own behavior, not a bug). |
| pb_write_uint64_field | |
| pb_write_sint64_field | sint32/sint64: zigzag-encoded varint (efficient for small negative values, unlike plain int64 above). |
| pb_write_bool_field | |
| pb_write_double_field | |
| pb_write_float_field | |
| pb_write_string_field | Length-delimited: string, bytes, or an embedded/nested message's own already-encoded bytes (encode the submessage with its own to_proto() first, then pass the result here). |
| pb_write_bytes_field |
Macros
| PB_WIRE_VARINT | int32/int64/uint32/uint64/sint32/sint64/bool/enum |
| PB_WIRE_FIXED64 | fixed64/sfixed64/double |
| PB_WIRE_LEN | string/bytes/embedded messages/packed repeated |
| PB_WIRE_FIXED32 | fixed32/sfixed32/float |