1 /*
2 ** upb::Encoder
3 **
4 ** Since we are implementing pure handlers (ie. without any out-of-band access
5 ** to pre-computed lengths), we have to buffer all submessages before we can
6 ** emit even their first byte.
7 **
8 ** Not knowing the size of submessages also means we can't write a perfect
9 ** zero-copy implementation, even with buffering. Lengths are stored as
10 ** varints, which means that we don't know how many bytes to reserve for the
11 ** length until we know what the length is.
12 **
13 ** This leaves us with three main choices:
14 **
15 ** 1. buffer all submessage data in a temporary buffer, then copy it exactly
16 ** once into the output buffer.
17 **
18 ** 2. attempt to buffer data directly into the output buffer, estimating how
19 ** many bytes each length will take. When our guesses are wrong, use
20 ** memmove() to grow or shrink the allotted space.
21 **
22 ** 3. buffer directly into the output buffer, allocating a max length
23 ** ahead-of-time for each submessage length. If we overallocated, we waste
24 ** space, but no memcpy() or memmove() is required. This approach requires
25 ** defining a maximum size for submessages and rejecting submessages that
26 ** exceed that size.
27 **
28 ** (2) and (3) have the potential to have better performance, but they are more
29 ** complicated and subtle to implement:
30 **
31 ** (3) requires making an arbitrary choice of the maximum message size; it
32 ** wastes space when submessages are shorter than this and fails
33 ** completely when they are longer. This makes it more finicky and
34 ** requires configuration based on the input. It also makes it impossible
35 ** to perfectly match the output of reference encoders that always use the
36 ** optimal amount of space for each length.
37 **
38 ** (2) requires guessing the the size upfront, and if multiple lengths are
39 ** guessed wrong the minimum required number of memmove() operations may
40 ** be complicated to compute correctly. Implemented properly, it may have
41 ** a useful amortized or average cost, but more investigation is required
42 ** to determine this and what the optimal algorithm is to achieve it.
43 **
44 ** (1) makes you always pay for exactly one copy, but its implementation is
45 ** the simplest and its performance is predictable.
46 **
47 ** So for now, we implement (1) only. If we wish to optimize later, we should
48 ** be able to do it without affecting users.
49 **
50 ** The strategy is to buffer the segments of data that do *not* depend on
51 ** unknown lengths in one buffer, and keep a separate buffer of segment pointers
52 ** and lengths. When the top-level submessage ends, we can go beginning to end,
53 ** alternating the writing of lengths with memcpy() of the rest of the data.
54 ** At the top level though, no buffering is required.
55 */
56
57 #include "upb/pb/encoder.h"
58 #include "upb/pb/varint.int.h"
59
60 #include "upb/port_def.inc"
61
62 /* The output buffer is divided into segments; a segment is a string of data
63 * that is "ready to go" -- it does not need any varint lengths inserted into
64 * the middle. The seams between segments are where varints will be inserted
65 * once they are known.
66 *
67 * We also use the concept of a "run", which is a range of encoded bytes that
68 * occur at a single submessage level. Every segment contains one or more runs.
69 *
70 * A segment can span messages. Consider:
71 *
72 * .--Submessage lengths---------.
73 * | | |
74 * | V V
75 * V | |--------------- | |-----------------
76 * Submessages: | |-----------------------------------------------
77 * Top-level msg: ------------------------------------------------------------
78 *
79 * Segments: ----- ------------------- -----------------
80 * Runs: *---- *--------------*--- *----------------
81 * (* marks the start)
82 *
83 * Note that the top-level menssage is not in any segment because it does not
84 * have any length preceding it.
85 *
86 * A segment is only interrupted when another length needs to be inserted. So
87 * observe how the second segment spans both the inner submessage and part of
88 * the next enclosing message. */
89 typedef struct {
90 uint32_t msglen; /* The length to varint-encode before this segment. */
91 uint32_t seglen; /* Length of the segment. */
92 } upb_pb_encoder_segment;
93
94 struct upb_pb_encoder {
95 upb_arena *arena;
96
97 /* Our input and output. */
98 upb_sink input_;
99 upb_bytessink output_;
100
101 /* The "subclosure" -- used as the inner closure as part of the bytessink
102 * protocol. */
103 void *subc;
104
105 /* The output buffer and limit, and our current write position. "buf"
106 * initially points to "initbuf", but is dynamically allocated if we need to
107 * grow beyond the initial size. */
108 char *buf, *ptr, *limit;
109
110 /* The beginning of the current run, or undefined if we are at the top
111 * level. */
112 char *runbegin;
113
114 /* The list of segments we are accumulating. */
115 upb_pb_encoder_segment *segbuf, *segptr, *seglimit;
116
117 /* The stack of enclosing submessages. Each entry in the stack points to the
118 * segment where this submessage's length is being accumulated. */
119 int *stack, *top, *stacklimit;
120
121 /* Depth of startmsg/endmsg calls. */
122 int depth;
123 };
124
125 /* low-level buffering ********************************************************/
126
127 /* Low-level functions for interacting with the output buffer. */
128
129 /* TODO(haberman): handle pushback */
putbuf(upb_pb_encoder * e,const char * buf,size_t len)130 static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
131 size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
132 UPB_ASSERT(n == len);
133 }
134
top(upb_pb_encoder * e)135 static upb_pb_encoder_segment *top(upb_pb_encoder *e) {
136 return &e->segbuf[*e->top];
137 }
138
139 /* Call to ensure that at least "bytes" bytes are available for writing at
140 * e->ptr. Returns false if the bytes could not be allocated. */
reserve(upb_pb_encoder * e,size_t bytes)141 static bool reserve(upb_pb_encoder *e, size_t bytes) {
142 if ((size_t)(e->limit - e->ptr) < bytes) {
143 /* Grow buffer. */
144 char *new_buf;
145 size_t needed = bytes + (e->ptr - e->buf);
146 size_t old_size = e->limit - e->buf;
147
148 size_t new_size = old_size;
149
150 while (new_size < needed) {
151 new_size *= 2;
152 }
153
154 new_buf = upb_arena_realloc(e->arena, e->buf, old_size, new_size);
155
156 if (new_buf == NULL) {
157 return false;
158 }
159
160 e->ptr = new_buf + (e->ptr - e->buf);
161 e->runbegin = new_buf + (e->runbegin - e->buf);
162 e->limit = new_buf + new_size;
163 e->buf = new_buf;
164 }
165
166 return true;
167 }
168
169 /* Call when "bytes" bytes have been writte at e->ptr. The caller *must* have
170 * previously called reserve() with at least this many bytes. */
encoder_advance(upb_pb_encoder * e,size_t bytes)171 static void encoder_advance(upb_pb_encoder *e, size_t bytes) {
172 UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes);
173 e->ptr += bytes;
174 }
175
176 /* Call when all of the bytes for a handler have been written. Flushes the
177 * bytes if possible and necessary, returning false if this failed. */
commit(upb_pb_encoder * e)178 static bool commit(upb_pb_encoder *e) {
179 if (!e->top) {
180 /* We aren't inside a delimited region. Flush our accumulated bytes to
181 * the output.
182 *
183 * TODO(haberman): in the future we may want to delay flushing for
184 * efficiency reasons. */
185 putbuf(e, e->buf, e->ptr - e->buf);
186 e->ptr = e->buf;
187 }
188
189 return true;
190 }
191
192 /* Writes the given bytes to the buffer, handling reserve/advance. */
encode_bytesval(upb_pb_encoder * e,const void * data,size_t len)193 static bool encode_bytesval(upb_pb_encoder *e, const void *data, size_t len) {
194 if (!reserve(e, len)) {
195 return false;
196 }
197
198 memcpy(e->ptr, data, len);
199 encoder_advance(e, len);
200 return true;
201 }
202
203 /* Finish the current run by adding the run totals to the segment and message
204 * length. */
accumulate(upb_pb_encoder * e)205 static void accumulate(upb_pb_encoder *e) {
206 size_t run_len;
207 UPB_ASSERT(e->ptr >= e->runbegin);
208 run_len = e->ptr - e->runbegin;
209 e->segptr->seglen += run_len;
210 top(e)->msglen += run_len;
211 e->runbegin = e->ptr;
212 }
213
214 /* Call to indicate the start of delimited region for which the full length is
215 * not yet known. All data will be buffered until the length is known.
216 * Delimited regions may be nested; their lengths will all be tracked properly. */
start_delim(upb_pb_encoder * e)217 static bool start_delim(upb_pb_encoder *e) {
218 if (e->top) {
219 /* We are already buffering, advance to the next segment and push it on the
220 * stack. */
221 accumulate(e);
222
223 if (++e->top == e->stacklimit) {
224 /* TODO(haberman): grow stack? */
225 return false;
226 }
227
228 if (++e->segptr == e->seglimit) {
229 /* Grow segment buffer. */
230 size_t old_size =
231 (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
232 size_t new_size = old_size * 2;
233 upb_pb_encoder_segment *new_buf =
234 upb_arena_realloc(e->arena, e->segbuf, old_size, new_size);
235
236 if (new_buf == NULL) {
237 return false;
238 }
239
240 e->segptr = new_buf + (e->segptr - e->segbuf);
241 e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment));
242 e->segbuf = new_buf;
243 }
244 } else {
245 /* We were previously at the top level, start buffering. */
246 e->segptr = e->segbuf;
247 e->top = e->stack;
248 e->runbegin = e->ptr;
249 }
250
251 *e->top = (int)(e->segptr - e->segbuf);
252 e->segptr->seglen = 0;
253 e->segptr->msglen = 0;
254
255 return true;
256 }
257
258 /* Call to indicate the end of a delimited region. We now know the length of
259 * the delimited region. If we are not nested inside any other delimited
260 * regions, we can now emit all of the buffered data we accumulated. */
end_delim(upb_pb_encoder * e)261 static bool end_delim(upb_pb_encoder *e) {
262 size_t msglen;
263 accumulate(e);
264 msglen = top(e)->msglen;
265
266 if (e->top == e->stack) {
267 /* All lengths are now available, emit all buffered data. */
268 char buf[UPB_PB_VARINT_MAX_LEN];
269 upb_pb_encoder_segment *s;
270 const char *ptr = e->buf;
271 for (s = e->segbuf; s <= e->segptr; s++) {
272 size_t lenbytes = upb_vencode64(s->msglen, buf);
273 putbuf(e, buf, lenbytes);
274 putbuf(e, ptr, s->seglen);
275 ptr += s->seglen;
276 }
277
278 e->ptr = e->buf;
279 e->top = NULL;
280 } else {
281 /* Need to keep buffering; propagate length info into enclosing
282 * submessages. */
283 --e->top;
284 top(e)->msglen += msglen + upb_varint_size(msglen);
285 }
286
287 return true;
288 }
289
290
291 /* tag_t **********************************************************************/
292
293 /* A precomputed (pre-encoded) tag and length. */
294
295 typedef struct {
296 uint8_t bytes;
297 char tag[7];
298 } tag_t;
299
300 /* Allocates a new tag for this field, and sets it in these handlerattr. */
new_tag(upb_handlers * h,const upb_fielddef * f,upb_wiretype_t wt,upb_handlerattr * attr)301 static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
302 upb_handlerattr *attr) {
303 uint32_t n = upb_fielddef_number(f);
304
305 tag_t *tag = upb_gmalloc(sizeof(tag_t));
306 tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
307
308 attr->handler_data = tag;
309 upb_handlers_addcleanup(h, tag, upb_gfree);
310 }
311
encode_tagval(upb_pb_encoder * e,const tag_t * tag)312 static bool encode_tagval(upb_pb_encoder *e, const tag_t *tag) {
313 return encode_bytesval(e, tag->tag, tag->bytes);
314 }
315
316
317 /* encoding of wire types *****************************************************/
318
doencode_fixed64(upb_pb_encoder * e,uint64_t val)319 static bool doencode_fixed64(upb_pb_encoder *e, uint64_t val) {
320 /* TODO(haberman): byte-swap for big endian. */
321 return encode_bytesval(e, &val, sizeof(uint64_t));
322 }
323
doencode_fixed32(upb_pb_encoder * e,uint32_t val)324 static bool doencode_fixed32(upb_pb_encoder *e, uint32_t val) {
325 /* TODO(haberman): byte-swap for big endian. */
326 return encode_bytesval(e, &val, sizeof(uint32_t));
327 }
328
doencode_varint(upb_pb_encoder * e,uint64_t val)329 static bool doencode_varint(upb_pb_encoder *e, uint64_t val) {
330 if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) {
331 return false;
332 }
333
334 encoder_advance(e, upb_vencode64(val, e->ptr));
335 return true;
336 }
337
dbl2uint64(double d)338 static uint64_t dbl2uint64(double d) {
339 uint64_t ret;
340 memcpy(&ret, &d, sizeof(uint64_t));
341 return ret;
342 }
343
flt2uint32(float d)344 static uint32_t flt2uint32(float d) {
345 uint32_t ret;
346 memcpy(&ret, &d, sizeof(uint32_t));
347 return ret;
348 }
349
350
351 /* encoding of proto types ****************************************************/
352
startmsg(void * c,const void * hd)353 static bool startmsg(void *c, const void *hd) {
354 upb_pb_encoder *e = c;
355 UPB_UNUSED(hd);
356 if (e->depth++ == 0) {
357 upb_bytessink_start(e->output_, 0, &e->subc);
358 }
359 return true;
360 }
361
endmsg(void * c,const void * hd,upb_status * status)362 static bool endmsg(void *c, const void *hd, upb_status *status) {
363 upb_pb_encoder *e = c;
364 UPB_UNUSED(hd);
365 UPB_UNUSED(status);
366 if (--e->depth == 0) {
367 upb_bytessink_end(e->output_);
368 }
369 return true;
370 }
371
encode_startdelimfield(void * c,const void * hd)372 static void *encode_startdelimfield(void *c, const void *hd) {
373 bool ok = encode_tagval(c, hd) && commit(c) && start_delim(c);
374 return ok ? c : UPB_BREAK;
375 }
376
encode_unknown(void * c,const void * hd,const char * buf,size_t len)377 static bool encode_unknown(void *c, const void *hd, const char *buf,
378 size_t len) {
379 UPB_UNUSED(hd);
380 return encode_bytesval(c, buf, len) && commit(c);
381 }
382
encode_enddelimfield(void * c,const void * hd)383 static bool encode_enddelimfield(void *c, const void *hd) {
384 UPB_UNUSED(hd);
385 return end_delim(c);
386 }
387
encode_startgroup(void * c,const void * hd)388 static void *encode_startgroup(void *c, const void *hd) {
389 return (encode_tagval(c, hd) && commit(c)) ? c : UPB_BREAK;
390 }
391
encode_endgroup(void * c,const void * hd)392 static bool encode_endgroup(void *c, const void *hd) {
393 return encode_tagval(c, hd) && commit(c);
394 }
395
encode_startstr(void * c,const void * hd,size_t size_hint)396 static void *encode_startstr(void *c, const void *hd, size_t size_hint) {
397 UPB_UNUSED(size_hint);
398 return encode_startdelimfield(c, hd);
399 }
400
encode_strbuf(void * c,const void * hd,const char * buf,size_t len,const upb_bufhandle * h)401 static size_t encode_strbuf(void *c, const void *hd, const char *buf,
402 size_t len, const upb_bufhandle *h) {
403 UPB_UNUSED(hd);
404 UPB_UNUSED(h);
405 return encode_bytesval(c, buf, len) ? len : 0;
406 }
407
408 #define T(type, ctype, convert, encode) \
409 static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \
410 return encode_tagval(e, hd) && encode(e, (convert)(val)) && commit(e); \
411 } \
412 static bool encode_packed_##type(void *e, const void *hd, ctype val) { \
413 UPB_UNUSED(hd); \
414 return encode(e, (convert)(val)); \
415 }
416
T(double,double,dbl2uint64,doencode_fixed64)417 T(double, double, dbl2uint64, doencode_fixed64)
418 T(float, float, flt2uint32, doencode_fixed32)
419 T(int64, int64_t, uint64_t, doencode_varint)
420 T(int32, int32_t, int64_t, doencode_varint)
421 T(fixed64, uint64_t, uint64_t, doencode_fixed64)
422 T(fixed32, uint32_t, uint32_t, doencode_fixed32)
423 T(bool, bool, bool, doencode_varint)
424 T(uint32, uint32_t, uint32_t, doencode_varint)
425 T(uint64, uint64_t, uint64_t, doencode_varint)
426 T(enum, int32_t, uint32_t, doencode_varint)
427 T(sfixed32, int32_t, uint32_t, doencode_fixed32)
428 T(sfixed64, int64_t, uint64_t, doencode_fixed64)
429 T(sint32, int32_t, upb_zzenc_32, doencode_varint)
430 T(sint64, int64_t, upb_zzenc_64, doencode_varint)
431
432 #undef T
433
434
435 /* code to build the handlers *************************************************/
436
437 #include <stdio.h>
438 static void newhandlers_callback(const void *closure, upb_handlers *h) {
439 const upb_msgdef *m;
440 int i, n;
441
442 UPB_UNUSED(closure);
443
444 upb_handlers_setstartmsg(h, startmsg, NULL);
445 upb_handlers_setendmsg(h, endmsg, NULL);
446 upb_handlers_setunknown(h, encode_unknown, NULL);
447
448 m = upb_handlers_msgdef(h);
449 n = upb_msgdef_fieldcount(m);
450 for(i = 0; i < n; i++) {
451 const upb_fielddef *f = upb_msgdef_field(m, i);
452 bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
453 upb_fielddef_packed(f);
454 upb_handlerattr attr = UPB_HANDLERATTR_INIT;
455 upb_wiretype_t wt =
456 packed ? UPB_WIRE_TYPE_DELIMITED
457 : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
458
459 /* Pre-encode the tag for this field. */
460 new_tag(h, f, wt, &attr);
461
462 if (packed) {
463 upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr);
464 upb_handlers_setendseq(h, f, encode_enddelimfield, &attr);
465 }
466
467 #define T(upper, lower, upbtype) \
468 case UPB_DESCRIPTOR_TYPE_##upper: \
469 if (packed) { \
470 upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \
471 } else { \
472 upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \
473 } \
474 break;
475
476 switch (upb_fielddef_descriptortype(f)) {
477 T(DOUBLE, double, double);
478 T(FLOAT, float, float);
479 T(INT64, int64, int64);
480 T(INT32, int32, int32);
481 T(FIXED64, fixed64, uint64);
482 T(FIXED32, fixed32, uint32);
483 T(BOOL, bool, bool);
484 T(UINT32, uint32, uint32);
485 T(UINT64, uint64, uint64);
486 T(ENUM, enum, int32);
487 T(SFIXED32, sfixed32, int32);
488 T(SFIXED64, sfixed64, int64);
489 T(SINT32, sint32, int32);
490 T(SINT64, sint64, int64);
491 case UPB_DESCRIPTOR_TYPE_STRING:
492 case UPB_DESCRIPTOR_TYPE_BYTES:
493 upb_handlers_setstartstr(h, f, encode_startstr, &attr);
494 upb_handlers_setendstr(h, f, encode_enddelimfield, &attr);
495 upb_handlers_setstring(h, f, encode_strbuf, &attr);
496 break;
497 case UPB_DESCRIPTOR_TYPE_MESSAGE:
498 upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr);
499 upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr);
500 break;
501 case UPB_DESCRIPTOR_TYPE_GROUP: {
502 /* Endgroup takes a different tag (wire_type = END_GROUP). */
503 upb_handlerattr attr2 = UPB_HANDLERATTR_INIT;
504 new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2);
505
506 upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr);
507 upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2);
508
509 break;
510 }
511 }
512
513 #undef T
514 }
515 }
516
upb_pb_encoder_reset(upb_pb_encoder * e)517 void upb_pb_encoder_reset(upb_pb_encoder *e) {
518 e->segptr = NULL;
519 e->top = NULL;
520 e->depth = 0;
521 }
522
523
524 /* public API *****************************************************************/
525
upb_pb_encoder_newcache(void)526 upb_handlercache *upb_pb_encoder_newcache(void) {
527 return upb_handlercache_new(newhandlers_callback, NULL);
528 }
529
upb_pb_encoder_create(upb_arena * arena,const upb_handlers * h,upb_bytessink output)530 upb_pb_encoder *upb_pb_encoder_create(upb_arena *arena, const upb_handlers *h,
531 upb_bytessink output) {
532 const size_t initial_bufsize = 256;
533 const size_t initial_segbufsize = 16;
534 /* TODO(haberman): make this configurable. */
535 const size_t stack_size = 64;
536
537 upb_pb_encoder *e = upb_arena_malloc(arena, sizeof(upb_pb_encoder));
538 if (!e) return NULL;
539
540 e->buf = upb_arena_malloc(arena, initial_bufsize);
541 e->segbuf = upb_arena_malloc(arena, initial_segbufsize * sizeof(*e->segbuf));
542 e->stack = upb_arena_malloc(arena, stack_size * sizeof(*e->stack));
543
544 if (!e->buf || !e->segbuf || !e->stack) {
545 return NULL;
546 }
547
548 e->limit = e->buf + initial_bufsize;
549 e->seglimit = e->segbuf + initial_segbufsize;
550 e->stacklimit = e->stack + stack_size;
551
552 upb_pb_encoder_reset(e);
553 upb_sink_reset(&e->input_, h, e);
554
555 e->arena = arena;
556 e->output_ = output;
557 e->subc = output.closure;
558 e->ptr = e->buf;
559
560 return e;
561 }
562
upb_pb_encoder_input(upb_pb_encoder * e)563 upb_sink upb_pb_encoder_input(upb_pb_encoder *e) { return e->input_; }
564