11#if DETWS_ENABLE_PROTOBUF
15void pb_writer_init(PbWriter *w, uint8_t *buf,
size_t cap)
23bool pb_write_varint(PbWriter *w, uint64_t v)
31 uint8_t b = (uint8_t)(v & 0x7F);
37 if (w->pos + n > w->cap)
42 memcpy(w->buf + w->pos, tmp, n);
47bool pb_write_tag(PbWriter *w, uint32_t field, uint8_t wire_type)
49 return pb_write_varint(w, ((uint64_t)field << 3) | (wire_type & 0x07));
53static bool pb_write_le(PbWriter *w, uint64_t v,
size_t n)
57 if (w->pos + n > w->cap)
62 for (
size_t i = 0; i < n; i++)
63 w->buf[w->pos++] = (uint8_t)(v >> (8 * i));
67bool pb_uint64(PbWriter *w, uint32_t field, uint64_t v)
69 return pb_write_tag(w, field, PB_WT_VARINT) && pb_write_varint(w, v);
72bool pb_int64(PbWriter *w, uint32_t field, int64_t v)
74 return pb_uint64(w, field, (uint64_t)v);
77bool pb_sint64(PbWriter *w, uint32_t field, int64_t v)
79 uint64_t zz = ((uint64_t)v << 1) ^ (uint64_t)(v >> 63);
80 return pb_uint64(w, field, zz);
83bool pb_bool(PbWriter *w, uint32_t field,
bool v)
85 return pb_uint64(w, field, v ? 1 : 0);
88bool pb_fixed32(PbWriter *w, uint32_t field, uint32_t v)
90 return pb_write_tag(w, field, PB_WT_I32) && pb_write_le(w, v, 4);
93bool pb_fixed64(PbWriter *w, uint32_t field, uint64_t v)
95 return pb_write_tag(w, field, PB_WT_I64) && pb_write_le(w, v, 8);
98bool pb_float(PbWriter *w, uint32_t field,
float v)
101 memcpy(&bits, &v, 4);
102 return pb_fixed32(w, field, bits);
105bool pb_double(PbWriter *w, uint32_t field,
double v)
108 memcpy(&bits, &v, 8);
109 return pb_fixed64(w, field, bits);
112bool pb_bytes(PbWriter *w, uint32_t field,
const uint8_t *data,
size_t len)
114 if (!pb_write_tag(w, field, PB_WT_LEN) || !pb_write_varint(w, len))
120 if (!data || w->pos + len > w->cap)
125 memcpy(w->buf + w->pos, data, len);
130bool pb_string(PbWriter *w, uint32_t field,
const char *s)
137 return pb_bytes(w, field, (
const uint8_t *)s, strnlen(s, w->cap + 1));
140size_t pb_writer_finish(PbWriter *w)
142 return w->error ? 0 : w->pos;
145bool pb_read_varint(
const uint8_t *buf,
size_t len,
size_t *pos, uint64_t *out)
147 if (!buf || !pos || !out)
152 for (
size_t b = 0; b < 10; b++)
156 uint8_t c = buf[i++];
157 v |= (uint64_t)(c & 0x7F) << shift;
169bool pb_read_field(
const uint8_t *buf,
size_t len,
size_t *pos, PbField *out)
171 if (!buf || !pos || !out || *pos >= len)
174 if (!pb_read_varint(buf, len, pos, &tag))
176 out->field_number = (uint32_t)(tag >> 3);
177 out->wire_type = (uint8_t)(tag & 0x07);
182 switch (out->wire_type)
185 return pb_read_varint(buf, len, pos, &out->value);
190 for (
size_t i = 0; i < 8; i++)
191 v |= (uint64_t)buf[*pos + i] << (8 * i);
200 for (
size_t i = 0; i < 4; i++)
201 v |= (uint32_t)buf[*pos + i] << (8 * i);
208 if (!pb_read_varint(buf, len, pos, &l))
212 out->data = buf + *pos;
213 out->len = (size_t)l;
222int64_t pb_zigzag64(uint64_t v)
224 return (int64_t)(v >> 1) ^ -(int64_t)(v & 1);
227int32_t pb_zigzag32(uint32_t v)
229 return (int32_t)(v >> 1) ^ -(int32_t)(v & 1);
232float pb_float_bits(uint32_t bits)
235 memcpy(&f, &bits, 4);
239double pb_double_bits(uint64_t bits)
242 memcpy(&d, &bits, 8);
Protocol Buffers wire codec (DETWS_ENABLE_PROTOBUF) - zero-heap streaming writer.