Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: third_party/protobuf/ruby/ext/google/protobuf_c/encode_decode.c

Issue 1322483002: Revert https://codereview.chromium.org/1291903002 (protobuf roll). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2014 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #include "protobuf.h"
32
33 // This function is equivalent to rb_str_cat(), but unlike the real
34 // rb_str_cat(), it doesn't leak memory in some versions of Ruby.
35 // For more information, see:
36 // https://bugs.ruby-lang.org/issues/11328
37 VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) {
38 size_t oldlen = RSTRING_LEN(rb_str);
39 rb_str_modify_expand(rb_str, len);
40 char *p = RSTRING_PTR(rb_str);
41 memcpy(p + oldlen, str, len);
42 rb_str_set_len(rb_str, oldlen + len);
43 }
44
45 // -----------------------------------------------------------------------------
46 // Parsing.
47 // -----------------------------------------------------------------------------
48
49 #define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
50
51 // Creates a handlerdata that simply contains the offset for this field.
52 static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
53 size_t* hd_ofs = ALLOC(size_t);
54 *hd_ofs = ofs;
55 upb_handlers_addcleanup(h, hd_ofs, free);
56 return hd_ofs;
57 }
58
59 typedef struct {
60 size_t ofs;
61 const upb_msgdef *md;
62 } submsg_handlerdata_t;
63
64 // Creates a handlerdata that contains offset and submessage type information.
65 static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
66 const upb_fielddef* f) {
67 submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
68 hd->ofs = ofs;
69 hd->md = upb_fielddef_msgsubdef(f);
70 upb_handlers_addcleanup(h, hd, free);
71 return hd;
72 }
73
74 typedef struct {
75 size_t ofs; // union data slot
76 size_t case_ofs; // oneof_case field
77 uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
78 const upb_msgdef *md; // msgdef, for oneof submessage handler
79 } oneof_handlerdata_t;
80
81 static const void *newoneofhandlerdata(upb_handlers *h,
82 uint32_t ofs,
83 uint32_t case_ofs,
84 const upb_fielddef *f) {
85 oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t);
86 hd->ofs = ofs;
87 hd->case_ofs = case_ofs;
88 // We reuse the field tag number as a oneof union discriminant tag. Note that
89 // we don't expose these numbers to the user, so the only requirement is that
90 // we have some unique ID for each union case/possibility. The field tag
91 // numbers are already present and are easy to use so there's no reason to
92 // create a separate ID space. In addition, using the field tag number here
93 // lets us easily look up the field in the oneof accessor.
94 hd->oneof_case_num = upb_fielddef_number(f);
95 if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) {
96 hd->md = upb_fielddef_msgsubdef(f);
97 } else {
98 hd->md = NULL;
99 }
100 upb_handlers_addcleanup(h, hd, free);
101 return hd;
102 }
103
104 // A handler that starts a repeated field. Gets the Repeated*Field instance for
105 // this field (such an instance always exists even in an empty message).
106 static void *startseq_handler(void* closure, const void* hd) {
107 MessageHeader* msg = closure;
108 const size_t *ofs = hd;
109 return (void*)DEREF(msg, *ofs, VALUE);
110 }
111
112 // Handlers that append primitive values to a repeated field.
113 #define DEFINE_APPEND_HANDLER(type, ctype) \
114 static bool append##type##_handler(void *closure, const void *hd, \
115 ctype val) { \
116 VALUE ary = (VALUE)closure; \
117 RepeatedField_push_native(ary, &val); \
118 return true; \
119 }
120
121 DEFINE_APPEND_HANDLER(bool, bool)
122 DEFINE_APPEND_HANDLER(int32, int32_t)
123 DEFINE_APPEND_HANDLER(uint32, uint32_t)
124 DEFINE_APPEND_HANDLER(float, float)
125 DEFINE_APPEND_HANDLER(int64, int64_t)
126 DEFINE_APPEND_HANDLER(uint64, uint64_t)
127 DEFINE_APPEND_HANDLER(double, double)
128
129 // Appends a string to a repeated field.
130 static void* appendstr_handler(void *closure,
131 const void *hd,
132 size_t size_hint) {
133 VALUE ary = (VALUE)closure;
134 VALUE str = rb_str_new2("");
135 rb_enc_associate(str, kRubyStringUtf8Encoding);
136 RepeatedField_push(ary, str);
137 return (void*)str;
138 }
139
140 // Appends a 'bytes' string to a repeated field.
141 static void* appendbytes_handler(void *closure,
142 const void *hd,
143 size_t size_hint) {
144 VALUE ary = (VALUE)closure;
145 VALUE str = rb_str_new2("");
146 rb_enc_associate(str, kRubyString8bitEncoding);
147 RepeatedField_push(ary, str);
148 return (void*)str;
149 }
150
151 // Sets a non-repeated string field in a message.
152 static void* str_handler(void *closure,
153 const void *hd,
154 size_t size_hint) {
155 MessageHeader* msg = closure;
156 const size_t *ofs = hd;
157 VALUE str = rb_str_new2("");
158 rb_enc_associate(str, kRubyStringUtf8Encoding);
159 DEREF(msg, *ofs, VALUE) = str;
160 return (void*)str;
161 }
162
163 // Sets a non-repeated 'bytes' field in a message.
164 static void* bytes_handler(void *closure,
165 const void *hd,
166 size_t size_hint) {
167 MessageHeader* msg = closure;
168 const size_t *ofs = hd;
169 VALUE str = rb_str_new2("");
170 rb_enc_associate(str, kRubyString8bitEncoding);
171 DEREF(msg, *ofs, VALUE) = str;
172 return (void*)str;
173 }
174
175 static size_t stringdata_handler(void* closure, const void* hd,
176 const char* str, size_t len,
177 const upb_bufhandle* handle) {
178 VALUE rb_str = (VALUE)closure;
179 noleak_rb_str_cat(rb_str, str, len);
180 return len;
181 }
182
183 // Appends a submessage to a repeated field (a regular Ruby array for now).
184 static void *appendsubmsg_handler(void *closure, const void *hd) {
185 VALUE ary = (VALUE)closure;
186 const submsg_handlerdata_t *submsgdata = hd;
187 VALUE subdesc =
188 get_def_obj((void*)submsgdata->md);
189 VALUE subklass = Descriptor_msgclass(subdesc);
190
191 VALUE submsg_rb = rb_class_new_instance(0, NULL, subklass);
192 RepeatedField_push(ary, submsg_rb);
193
194 MessageHeader* submsg;
195 TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
196 return submsg;
197 }
198
199 // Sets a non-repeated submessage field in a message.
200 static void *submsg_handler(void *closure, const void *hd) {
201 MessageHeader* msg = closure;
202 const submsg_handlerdata_t* submsgdata = hd;
203 VALUE subdesc =
204 get_def_obj((void*)submsgdata->md);
205 VALUE subklass = Descriptor_msgclass(subdesc);
206
207 if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
208 DEREF(msg, submsgdata->ofs, VALUE) =
209 rb_class_new_instance(0, NULL, subklass);
210 }
211
212 VALUE submsg_rb = DEREF(msg, submsgdata->ofs, VALUE);
213 MessageHeader* submsg;
214 TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
215 return submsg;
216 }
217
218 // Handler data for startmap/endmap handlers.
219 typedef struct {
220 size_t ofs;
221 upb_fieldtype_t key_field_type;
222 upb_fieldtype_t value_field_type;
223
224 // We know that we can hold this reference because the handlerdata has the
225 // same lifetime as the upb_handlers struct, and the upb_handlers struct holds
226 // a reference to the upb_msgdef, which in turn has references to its subdefs.
227 const upb_def* value_field_subdef;
228 } map_handlerdata_t;
229
230 // Temporary frame for map parsing: at the beginning of a map entry message, a
231 // submsg handler allocates a frame to hold (i) a reference to the Map object
232 // into which this message will be inserted and (ii) storage slots to
233 // temporarily hold the key and value for this map entry until the end of the
234 // submessage. When the submessage ends, another handler is called to insert the
235 // value into the map.
236 typedef struct {
237 VALUE map;
238 char key_storage[NATIVE_SLOT_MAX_SIZE];
239 char value_storage[NATIVE_SLOT_MAX_SIZE];
240 } map_parse_frame_t;
241
242 // Handler to begin a map entry: allocates a temporary frame. This is the
243 // 'startsubmsg' handler on the msgdef that contains the map field.
244 static void *startmapentry_handler(void *closure, const void *hd) {
245 MessageHeader* msg = closure;
246 const map_handlerdata_t* mapdata = hd;
247 VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
248
249 map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
250 frame->map = map_rb;
251
252 native_slot_init(mapdata->key_field_type, &frame->key_storage);
253 native_slot_init(mapdata->value_field_type, &frame->value_storage);
254
255 return frame;
256 }
257
258 // Handler to end a map entry: inserts the value defined during the message into
259 // the map. This is the 'endmsg' handler on the map entry msgdef.
260 static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
261 map_parse_frame_t* frame = closure;
262 const map_handlerdata_t* mapdata = hd;
263
264 VALUE key = native_slot_get(
265 mapdata->key_field_type, Qnil,
266 &frame->key_storage);
267
268 VALUE value_field_typeclass = Qnil;
269 if (mapdata->value_field_type == UPB_TYPE_MESSAGE ||
270 mapdata->value_field_type == UPB_TYPE_ENUM) {
271 value_field_typeclass = get_def_obj(mapdata->value_field_subdef);
272 }
273
274 VALUE value = native_slot_get(
275 mapdata->value_field_type, value_field_typeclass,
276 &frame->value_storage);
277
278 Map_index_set(frame->map, key, value);
279 free(frame);
280
281 return true;
282 }
283
284 // Allocates a new map_handlerdata_t given the map entry message definition. If
285 // the offset of the field within the parent message is also given, that is
286 // added to the handler data as well. Note that this is called *twice* per map
287 // field: once in the parent message handler setup when setting the startsubmsg
288 // handler and once in the map entry message handler setup when setting the
289 // key/value and endmsg handlers. The reason is that there is no easy way to
290 // pass the handlerdata down to the sub-message handler setup.
291 static map_handlerdata_t* new_map_handlerdata(
292 size_t ofs,
293 const upb_msgdef* mapentry_def,
294 Descriptor* desc) {
295
296 map_handlerdata_t* hd = ALLOC(map_handlerdata_t);
297 hd->ofs = ofs;
298 const upb_fielddef* key_field = upb_msgdef_itof(mapentry_def,
299 MAP_KEY_FIELD);
300 assert(key_field != NULL);
301 hd->key_field_type = upb_fielddef_type(key_field);
302 const upb_fielddef* value_field = upb_msgdef_itof(mapentry_def,
303 MAP_VALUE_FIELD);
304 assert(value_field != NULL);
305 hd->value_field_type = upb_fielddef_type(value_field);
306 hd->value_field_subdef = upb_fielddef_subdef(value_field);
307
308 return hd;
309 }
310
311 // Handlers that set primitive values in oneofs.
312 #define DEFINE_ONEOF_HANDLER(type, ctype) \
313 static bool oneof##type##_handler(void *closure, const void *hd, \
314 ctype val) { \
315 const oneof_handlerdata_t *oneofdata = hd; \
316 DEREF(closure, oneofdata->case_ofs, uint32_t) = \
317 oneofdata->oneof_case_num; \
318 DEREF(closure, oneofdata->ofs, ctype) = val; \
319 return true; \
320 }
321
322 DEFINE_ONEOF_HANDLER(bool, bool)
323 DEFINE_ONEOF_HANDLER(int32, int32_t)
324 DEFINE_ONEOF_HANDLER(uint32, uint32_t)
325 DEFINE_ONEOF_HANDLER(float, float)
326 DEFINE_ONEOF_HANDLER(int64, int64_t)
327 DEFINE_ONEOF_HANDLER(uint64, uint64_t)
328 DEFINE_ONEOF_HANDLER(double, double)
329
330 #undef DEFINE_ONEOF_HANDLER
331
332 // Handlers for strings in a oneof.
333 static void *oneofstr_handler(void *closure,
334 const void *hd,
335 size_t size_hint) {
336 MessageHeader* msg = closure;
337 const oneof_handlerdata_t *oneofdata = hd;
338 VALUE str = rb_str_new2("");
339 rb_enc_associate(str, kRubyStringUtf8Encoding);
340 DEREF(msg, oneofdata->case_ofs, uint32_t) =
341 oneofdata->oneof_case_num;
342 DEREF(msg, oneofdata->ofs, VALUE) = str;
343 return (void*)str;
344 }
345
346 static void *oneofbytes_handler(void *closure,
347 const void *hd,
348 size_t size_hint) {
349 MessageHeader* msg = closure;
350 const oneof_handlerdata_t *oneofdata = hd;
351 VALUE str = rb_str_new2("");
352 rb_enc_associate(str, kRubyString8bitEncoding);
353 DEREF(msg, oneofdata->case_ofs, uint32_t) =
354 oneofdata->oneof_case_num;
355 DEREF(msg, oneofdata->ofs, VALUE) = str;
356 return (void*)str;
357 }
358
359 // Handler for a submessage field in a oneof.
360 static void *oneofsubmsg_handler(void *closure,
361 const void *hd) {
362 MessageHeader* msg = closure;
363 const oneof_handlerdata_t *oneofdata = hd;
364 uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
365
366 VALUE subdesc =
367 get_def_obj((void*)oneofdata->md);
368 VALUE subklass = Descriptor_msgclass(subdesc);
369
370 if (oldcase != oneofdata->oneof_case_num ||
371 DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
372 DEREF(msg, oneofdata->ofs, VALUE) =
373 rb_class_new_instance(0, NULL, subklass);
374 }
375 // Set the oneof case *after* allocating the new class instance -- otherwise,
376 // if the Ruby GC is invoked as part of a call into the VM, it might invoke
377 // our mark routines, and our mark routines might see the case value
378 // indicating a VALUE is present and expect a valid VALUE. See comment in
379 // layout_set() for more detail: basically, the change to the value and the
380 // case must be atomic w.r.t. the Ruby VM.
381 DEREF(msg, oneofdata->case_ofs, uint32_t) =
382 oneofdata->oneof_case_num;
383
384 VALUE submsg_rb = DEREF(msg, oneofdata->ofs, VALUE);
385 MessageHeader* submsg;
386 TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
387 return submsg;
388 }
389
390 // Set up handlers for a repeated field.
391 static void add_handlers_for_repeated_field(upb_handlers *h,
392 const upb_fielddef *f,
393 size_t offset) {
394 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
395 upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
396 upb_handlers_setstartseq(h, f, startseq_handler, &attr);
397 upb_handlerattr_uninit(&attr);
398
399 switch (upb_fielddef_type(f)) {
400
401 #define SET_HANDLER(utype, ltype) \
402 case utype: \
403 upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
404 break;
405
406 SET_HANDLER(UPB_TYPE_BOOL, bool);
407 SET_HANDLER(UPB_TYPE_INT32, int32);
408 SET_HANDLER(UPB_TYPE_UINT32, uint32);
409 SET_HANDLER(UPB_TYPE_ENUM, int32);
410 SET_HANDLER(UPB_TYPE_FLOAT, float);
411 SET_HANDLER(UPB_TYPE_INT64, int64);
412 SET_HANDLER(UPB_TYPE_UINT64, uint64);
413 SET_HANDLER(UPB_TYPE_DOUBLE, double);
414
415 #undef SET_HANDLER
416
417 case UPB_TYPE_STRING:
418 case UPB_TYPE_BYTES: {
419 bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
420 upb_handlers_setstartstr(h, f, is_bytes ?
421 appendbytes_handler : appendstr_handler,
422 NULL);
423 upb_handlers_setstring(h, f, stringdata_handler, NULL);
424 break;
425 }
426 case UPB_TYPE_MESSAGE: {
427 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
428 upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f));
429 upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
430 upb_handlerattr_uninit(&attr);
431 break;
432 }
433 }
434 }
435
436 // Set up handlers for a singular field.
437 static void add_handlers_for_singular_field(upb_handlers *h,
438 const upb_fielddef *f,
439 size_t offset) {
440 switch (upb_fielddef_type(f)) {
441 case UPB_TYPE_BOOL:
442 case UPB_TYPE_INT32:
443 case UPB_TYPE_UINT32:
444 case UPB_TYPE_ENUM:
445 case UPB_TYPE_FLOAT:
446 case UPB_TYPE_INT64:
447 case UPB_TYPE_UINT64:
448 case UPB_TYPE_DOUBLE:
449 upb_shim_set(h, f, offset, -1);
450 break;
451 case UPB_TYPE_STRING:
452 case UPB_TYPE_BYTES: {
453 bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
454 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
455 upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
456 upb_handlers_setstartstr(h, f,
457 is_bytes ? bytes_handler : str_handler,
458 &attr);
459 upb_handlers_setstring(h, f, stringdata_handler, &attr);
460 upb_handlerattr_uninit(&attr);
461 break;
462 }
463 case UPB_TYPE_MESSAGE: {
464 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
465 upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, offset, f));
466 upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
467 upb_handlerattr_uninit(&attr);
468 break;
469 }
470 }
471 }
472
473 // Adds handlers to a map field.
474 static void add_handlers_for_mapfield(upb_handlers* h,
475 const upb_fielddef* fielddef,
476 size_t offset,
477 Descriptor* desc) {
478 const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
479 map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
480 upb_handlers_addcleanup(h, hd, free);
481 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
482 upb_handlerattr_sethandlerdata(&attr, hd);
483 upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr);
484 upb_handlerattr_uninit(&attr);
485 }
486
487 // Adds handlers to a map-entry msgdef.
488 static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
489 upb_handlers* h,
490 Descriptor* desc) {
491 const upb_fielddef* key_field = map_entry_key(msgdef);
492 const upb_fielddef* value_field = map_entry_value(msgdef);
493 map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
494 upb_handlers_addcleanup(h, hd, free);
495 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
496 upb_handlerattr_sethandlerdata(&attr, hd);
497 upb_handlers_setendmsg(h, endmap_handler, &attr);
498
499 add_handlers_for_singular_field(
500 h, key_field,
501 offsetof(map_parse_frame_t, key_storage));
502 add_handlers_for_singular_field(
503 h, value_field,
504 offsetof(map_parse_frame_t, value_storage));
505 }
506
507 // Set up handlers for a oneof field.
508 static void add_handlers_for_oneof_field(upb_handlers *h,
509 const upb_fielddef *f,
510 size_t offset,
511 size_t oneof_case_offset) {
512
513 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
514 upb_handlerattr_sethandlerdata(
515 &attr, newoneofhandlerdata(h, offset, oneof_case_offset, f));
516
517 switch (upb_fielddef_type(f)) {
518
519 #define SET_HANDLER(utype, ltype) \
520 case utype: \
521 upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
522 break;
523
524 SET_HANDLER(UPB_TYPE_BOOL, bool);
525 SET_HANDLER(UPB_TYPE_INT32, int32);
526 SET_HANDLER(UPB_TYPE_UINT32, uint32);
527 SET_HANDLER(UPB_TYPE_ENUM, int32);
528 SET_HANDLER(UPB_TYPE_FLOAT, float);
529 SET_HANDLER(UPB_TYPE_INT64, int64);
530 SET_HANDLER(UPB_TYPE_UINT64, uint64);
531 SET_HANDLER(UPB_TYPE_DOUBLE, double);
532
533 #undef SET_HANDLER
534
535 case UPB_TYPE_STRING:
536 case UPB_TYPE_BYTES: {
537 bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
538 upb_handlers_setstartstr(h, f, is_bytes ?
539 oneofbytes_handler : oneofstr_handler,
540 &attr);
541 upb_handlers_setstring(h, f, stringdata_handler, NULL);
542 break;
543 }
544 case UPB_TYPE_MESSAGE: {
545 upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
546 break;
547 }
548 }
549
550 upb_handlerattr_uninit(&attr);
551 }
552
553
554 static void add_handlers_for_message(const void *closure, upb_handlers *h) {
555 const upb_msgdef* msgdef = upb_handlers_msgdef(h);
556 Descriptor* desc = ruby_to_Descriptor(get_def_obj((void*)msgdef));
557
558 // If this is a mapentry message type, set up a special set of handlers and
559 // bail out of the normal (user-defined) message type handling.
560 if (upb_msgdef_mapentry(msgdef)) {
561 add_handlers_for_mapentry(msgdef, h, desc);
562 return;
563 }
564
565 // Ensure layout exists. We may be invoked to create handlers for a given
566 // message if we are included as a submsg of another message type before our
567 // class is actually built, so to work around this, we just create the layout
568 // (and handlers, in the class-building function) on-demand.
569 if (desc->layout == NULL) {
570 desc->layout = create_layout(desc->msgdef);
571 }
572
573 upb_msg_field_iter i;
574 for (upb_msg_field_begin(&i, desc->msgdef);
575 !upb_msg_field_done(&i);
576 upb_msg_field_next(&i)) {
577 const upb_fielddef *f = upb_msg_iter_field(&i);
578 size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset +
579 sizeof(MessageHeader);
580
581 if (upb_fielddef_containingoneof(f)) {
582 size_t oneof_case_offset =
583 desc->layout->fields[upb_fielddef_index(f)].case_offset +
584 sizeof(MessageHeader);
585 add_handlers_for_oneof_field(h, f, offset, oneof_case_offset);
586 } else if (is_map_field(f)) {
587 add_handlers_for_mapfield(h, f, offset, desc);
588 } else if (upb_fielddef_isseq(f)) {
589 add_handlers_for_repeated_field(h, f, offset);
590 } else {
591 add_handlers_for_singular_field(h, f, offset);
592 }
593 }
594 }
595
596 // Creates upb handlers for populating a message.
597 static const upb_handlers *new_fill_handlers(Descriptor* desc,
598 const void* owner) {
599 // TODO(cfallin, haberman): once upb gets a caching/memoization layer for
600 // handlers, reuse subdef handlers so that e.g. if we already parse
601 // B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to
602 // parse A-with-field-of-type-B-with-field-of-type-C.
603 return upb_handlers_newfrozen(desc->msgdef, owner,
604 add_handlers_for_message, NULL);
605 }
606
607 // Constructs the handlers for filling a message's data into an in-memory
608 // object.
609 const upb_handlers* get_fill_handlers(Descriptor* desc) {
610 if (!desc->fill_handlers) {
611 desc->fill_handlers =
612 new_fill_handlers(desc, &desc->fill_handlers);
613 }
614 return desc->fill_handlers;
615 }
616
617 // Constructs the upb decoder method for parsing messages of this type.
618 // This is called from the message class creation code.
619 const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor* desc,
620 const void* owner) {
621 const upb_handlers* handlers = get_fill_handlers(desc);
622 upb_pbdecodermethodopts opts;
623 upb_pbdecodermethodopts_init(&opts, handlers);
624
625 const upb_pbdecodermethod *ret = upb_pbdecodermethod_new(&opts, owner);
626 return ret;
627 }
628
629 static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
630 if (desc->fill_method == NULL) {
631 desc->fill_method = new_fillmsg_decodermethod(
632 desc, &desc->fill_method);
633 }
634 return desc->fill_method;
635 }
636
637
638 // Stack-allocated context during an encode/decode operation. Contains the upb
639 // environment and its stack-based allocator, an initial buffer for allocations
640 // to avoid malloc() when possible, and a template for Ruby exception messages
641 // if any error occurs.
642 #define STACK_ENV_STACKBYTES 4096
643 typedef struct {
644 upb_env env;
645 upb_seededalloc alloc;
646 const char* ruby_error_template;
647 char allocbuf[STACK_ENV_STACKBYTES];
648 } stackenv;
649
650 static void stackenv_init(stackenv* se, const char* errmsg);
651 static void stackenv_uninit(stackenv* se);
652
653 // Callback invoked by upb if any error occurs during parsing or serialization.
654 static bool env_error_func(void* ud, const upb_status* status) {
655 stackenv* se = ud;
656 // Free the env -- rb_raise will longjmp up the stack past the encode/decode
657 // function so it would not otherwise have been freed.
658 stackenv_uninit(se);
659
660 // TODO(haberman): have a way to verify that this is actually a parse error,
661 // instead of just throwing "parse error" unconditionally.
662 rb_raise(cParseError, se->ruby_error_template, upb_status_errmsg(status));
663 // Never reached: rb_raise() always longjmp()s up the stack, past all of our
664 // code, back to Ruby.
665 return false;
666 }
667
668 static void stackenv_init(stackenv* se, const char* errmsg) {
669 se->ruby_error_template = errmsg;
670 upb_env_init(&se->env);
671 upb_seededalloc_init(&se->alloc, &se->allocbuf, STACK_ENV_STACKBYTES);
672 upb_env_setallocfunc(
673 &se->env, upb_seededalloc_getallocfunc(&se->alloc), &se->alloc);
674 upb_env_seterrorfunc(&se->env, env_error_func, se);
675 }
676
677 static void stackenv_uninit(stackenv* se) {
678 upb_env_uninit(&se->env);
679 upb_seededalloc_uninit(&se->alloc);
680 }
681
682 /*
683 * call-seq:
684 * MessageClass.decode(data) => message
685 *
686 * Decodes the given data (as a string containing bytes in protocol buffers wire
687 * format) under the interpretration given by this message class's definition
688 * and returns a message object with the corresponding field values.
689 */
690 VALUE Message_decode(VALUE klass, VALUE data) {
691 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
692 Descriptor* desc = ruby_to_Descriptor(descriptor);
693 VALUE msgklass = Descriptor_msgclass(descriptor);
694
695 if (TYPE(data) != T_STRING) {
696 rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
697 }
698
699 VALUE msg_rb = rb_class_new_instance(0, NULL, msgklass);
700 MessageHeader* msg;
701 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
702
703 const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
704 const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
705 stackenv se;
706 stackenv_init(&se, "Error occurred during parsing: %s");
707
708 upb_sink sink;
709 upb_sink_reset(&sink, h, msg);
710 upb_pbdecoder* decoder =
711 upb_pbdecoder_create(&se.env, method, &sink);
712 upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
713 upb_pbdecoder_input(decoder));
714
715 stackenv_uninit(&se);
716
717 return msg_rb;
718 }
719
720 /*
721 * call-seq:
722 * MessageClass.decode_json(data) => message
723 *
724 * Decodes the given data (as a string containing bytes in protocol buffers wire
725 * format) under the interpretration given by this message class's definition
726 * and returns a message object with the corresponding field values.
727 */
728 VALUE Message_decode_json(VALUE klass, VALUE data) {
729 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
730 Descriptor* desc = ruby_to_Descriptor(descriptor);
731 VALUE msgklass = Descriptor_msgclass(descriptor);
732
733 if (TYPE(data) != T_STRING) {
734 rb_raise(rb_eArgError, "Expected string for JSON data.");
735 }
736 // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
737 // convert, because string handlers pass data directly to message string
738 // fields.
739
740 VALUE msg_rb = rb_class_new_instance(0, NULL, msgklass);
741 MessageHeader* msg;
742 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
743
744 stackenv se;
745 stackenv_init(&se, "Error occurred during parsing: %s");
746
747 upb_sink sink;
748 upb_sink_reset(&sink, get_fill_handlers(desc), msg);
749 upb_json_parser* parser = upb_json_parser_create(&se.env, &sink);
750 upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
751 upb_json_parser_input(parser));
752
753 stackenv_uninit(&se);
754
755 return msg_rb;
756 }
757
758 // -----------------------------------------------------------------------------
759 // Serializing.
760 // -----------------------------------------------------------------------------
761 //
762 // The code below also comes from upb's prototype Ruby binding, developed by
763 // haberman@.
764
765 /* stringsink *****************************************************************/
766
767 // This should probably be factored into a common upb component.
768
769 typedef struct {
770 upb_byteshandler handler;
771 upb_bytessink sink;
772 char *ptr;
773 size_t len, size;
774 } stringsink;
775
776 static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
777 stringsink *sink = _sink;
778 sink->len = 0;
779 return sink;
780 }
781
782 static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
783 size_t len, const upb_bufhandle *handle) {
784 UPB_UNUSED(hd);
785 UPB_UNUSED(handle);
786
787 stringsink *sink = _sink;
788 size_t new_size = sink->size;
789
790 while (sink->len + len > new_size) {
791 new_size *= 2;
792 }
793
794 if (new_size != sink->size) {
795 sink->ptr = realloc(sink->ptr, new_size);
796 sink->size = new_size;
797 }
798
799 memcpy(sink->ptr + sink->len, ptr, len);
800 sink->len += len;
801
802 return len;
803 }
804
805 void stringsink_init(stringsink *sink) {
806 upb_byteshandler_init(&sink->handler);
807 upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
808 upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
809
810 upb_bytessink_reset(&sink->sink, &sink->handler, sink);
811
812 sink->size = 32;
813 sink->ptr = malloc(sink->size);
814 sink->len = 0;
815 }
816
817 void stringsink_uninit(stringsink *sink) {
818 free(sink->ptr);
819 }
820
821 /* msgvisitor *****************************************************************/
822
823 // TODO: If/when we support proto2 semantics in addition to the current proto3
824 // semantics, which means that we have true field presence, we will want to
825 // modify msgvisitor so that it emits all present fields rather than all
826 // non-default-value fields.
827 //
828 // Likewise, when implementing JSON serialization, we may need to have a
829 // 'verbose' mode that outputs all fields and a 'concise' mode that outputs only
830 // those with non-default values.
831
832 static void putmsg(VALUE msg, const Descriptor* desc,
833 upb_sink *sink, int depth);
834
835 static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
836 upb_selector_t ret;
837 bool ok = upb_handlers_getselector(f, type, &ret);
838 UPB_ASSERT_VAR(ok, ok);
839 return ret;
840 }
841
842 static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) {
843 if (str == Qnil) return;
844
845 assert(BUILTIN_TYPE(str) == RUBY_T_STRING);
846 upb_sink subsink;
847
848 // Ensure that the string has the correct encoding. We also check at field-set
849 // time, but the user may have mutated the string object since then.
850 native_slot_validate_string_encoding(upb_fielddef_type(f), str);
851
852 upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str),
853 &subsink);
854 upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str),
855 RSTRING_LEN(str), NULL);
856 upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
857 }
858
859 static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
860 int depth) {
861 if (submsg == Qnil) return;
862
863 upb_sink subsink;
864 VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
865 Descriptor* subdesc = ruby_to_Descriptor(descriptor);
866
867 upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
868 putmsg(submsg, subdesc, &subsink, depth + 1);
869 upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
870 }
871
872 static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
873 int depth) {
874 if (ary == Qnil) return;
875
876 upb_sink subsink;
877
878 upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
879
880 upb_fieldtype_t type = upb_fielddef_type(f);
881 upb_selector_t sel = 0;
882 if (upb_fielddef_isprimitive(f)) {
883 sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
884 }
885
886 int size = NUM2INT(RepeatedField_length(ary));
887 for (int i = 0; i < size; i++) {
888 void* memory = RepeatedField_index_native(ary, i);
889 switch (type) {
890 #define T(upbtypeconst, upbtype, ctype) \
891 case upbtypeconst: \
892 upb_sink_put##upbtype(&subsink, sel, *((ctype *)memory)); \
893 break;
894
895 T(UPB_TYPE_FLOAT, float, float)
896 T(UPB_TYPE_DOUBLE, double, double)
897 T(UPB_TYPE_BOOL, bool, int8_t)
898 case UPB_TYPE_ENUM:
899 T(UPB_TYPE_INT32, int32, int32_t)
900 T(UPB_TYPE_UINT32, uint32, uint32_t)
901 T(UPB_TYPE_INT64, int64, int64_t)
902 T(UPB_TYPE_UINT64, uint64, uint64_t)
903
904 case UPB_TYPE_STRING:
905 case UPB_TYPE_BYTES:
906 putstr(*((VALUE *)memory), f, &subsink);
907 break;
908 case UPB_TYPE_MESSAGE:
909 putsubmsg(*((VALUE *)memory), f, &subsink, depth);
910 break;
911
912 #undef T
913
914 }
915 }
916 upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
917 }
918
919 static void put_ruby_value(VALUE value,
920 const upb_fielddef *f,
921 VALUE type_class,
922 int depth,
923 upb_sink *sink) {
924 upb_selector_t sel = 0;
925 if (upb_fielddef_isprimitive(f)) {
926 sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
927 }
928
929 switch (upb_fielddef_type(f)) {
930 case UPB_TYPE_INT32:
931 upb_sink_putint32(sink, sel, NUM2INT(value));
932 break;
933 case UPB_TYPE_INT64:
934 upb_sink_putint64(sink, sel, NUM2LL(value));
935 break;
936 case UPB_TYPE_UINT32:
937 upb_sink_putuint32(sink, sel, NUM2UINT(value));
938 break;
939 case UPB_TYPE_UINT64:
940 upb_sink_putuint64(sink, sel, NUM2ULL(value));
941 break;
942 case UPB_TYPE_FLOAT:
943 upb_sink_putfloat(sink, sel, NUM2DBL(value));
944 break;
945 case UPB_TYPE_DOUBLE:
946 upb_sink_putdouble(sink, sel, NUM2DBL(value));
947 break;
948 case UPB_TYPE_ENUM: {
949 if (TYPE(value) == T_SYMBOL) {
950 value = rb_funcall(type_class, rb_intern("resolve"), 1, value);
951 }
952 upb_sink_putint32(sink, sel, NUM2INT(value));
953 break;
954 }
955 case UPB_TYPE_BOOL:
956 upb_sink_putbool(sink, sel, value == Qtrue);
957 break;
958 case UPB_TYPE_STRING:
959 case UPB_TYPE_BYTES:
960 putstr(value, f, sink);
961 break;
962 case UPB_TYPE_MESSAGE:
963 putsubmsg(value, f, sink, depth);
964 }
965 }
966
967 static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
968 int depth) {
969 if (map == Qnil) return;
970 Map* self = ruby_to_Map(map);
971
972 upb_sink subsink;
973
974 upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
975
976 assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
977 const upb_fielddef* key_field = map_field_key(f);
978 const upb_fielddef* value_field = map_field_value(f);
979
980 Map_iter it;
981 for (Map_begin(map, &it); !Map_done(&it); Map_next(&it)) {
982 VALUE key = Map_iter_key(&it);
983 VALUE value = Map_iter_value(&it);
984
985 upb_sink entry_sink;
986 upb_sink_startsubmsg(&subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
987 &entry_sink);
988 upb_sink_startmsg(&entry_sink);
989
990 put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink);
991 put_ruby_value(value, value_field, self->value_type_class, depth + 1,
992 &entry_sink);
993
994 upb_status status;
995 upb_sink_endmsg(&entry_sink, &status);
996 upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
997 }
998
999 upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
1000 }
1001
1002 static void putmsg(VALUE msg_rb, const Descriptor* desc,
1003 upb_sink *sink, int depth) {
1004 upb_sink_startmsg(sink);
1005
1006 // Protect against cycles (possible because users may freely reassign message
1007 // and repeated fields) by imposing a maximum recursion depth.
1008 if (depth > ENCODE_MAX_NESTING) {
1009 rb_raise(rb_eRuntimeError,
1010 "Maximum recursion depth exceeded during encoding.");
1011 }
1012
1013 MessageHeader* msg;
1014 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1015
1016 upb_msg_field_iter i;
1017 for (upb_msg_field_begin(&i, desc->msgdef);
1018 !upb_msg_field_done(&i);
1019 upb_msg_field_next(&i)) {
1020 upb_fielddef *f = upb_msg_iter_field(&i);
1021 uint32_t offset =
1022 desc->layout->fields[upb_fielddef_index(f)].offset +
1023 sizeof(MessageHeader);
1024
1025 if (upb_fielddef_containingoneof(f)) {
1026 uint32_t oneof_case_offset =
1027 desc->layout->fields[upb_fielddef_index(f)].case_offset +
1028 sizeof(MessageHeader);
1029 // For a oneof, check that this field is actually present -- skip all the
1030 // below if not.
1031 if (DEREF(msg, oneof_case_offset, uint32_t) !=
1032 upb_fielddef_number(f)) {
1033 continue;
1034 }
1035 // Otherwise, fall through to the appropriate singular-field handler
1036 // below.
1037 }
1038
1039 if (is_map_field(f)) {
1040 VALUE map = DEREF(msg, offset, VALUE);
1041 if (map != Qnil) {
1042 putmap(map, f, sink, depth);
1043 }
1044 } else if (upb_fielddef_isseq(f)) {
1045 VALUE ary = DEREF(msg, offset, VALUE);
1046 if (ary != Qnil) {
1047 putary(ary, f, sink, depth);
1048 }
1049 } else if (upb_fielddef_isstring(f)) {
1050 VALUE str = DEREF(msg, offset, VALUE);
1051 if (RSTRING_LEN(str) > 0) {
1052 putstr(str, f, sink);
1053 }
1054 } else if (upb_fielddef_issubmsg(f)) {
1055 putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth);
1056 } else {
1057 upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
1058
1059 #define T(upbtypeconst, upbtype, ctype, default_value) \
1060 case upbtypeconst: { \
1061 ctype value = DEREF(msg, offset, ctype); \
1062 if (value != default_value) { \
1063 upb_sink_put##upbtype(sink, sel, value); \
1064 } \
1065 } \
1066 break;
1067
1068 switch (upb_fielddef_type(f)) {
1069 T(UPB_TYPE_FLOAT, float, float, 0.0)
1070 T(UPB_TYPE_DOUBLE, double, double, 0.0)
1071 T(UPB_TYPE_BOOL, bool, uint8_t, 0)
1072 case UPB_TYPE_ENUM:
1073 T(UPB_TYPE_INT32, int32, int32_t, 0)
1074 T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
1075 T(UPB_TYPE_INT64, int64, int64_t, 0)
1076 T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
1077
1078 case UPB_TYPE_STRING:
1079 case UPB_TYPE_BYTES:
1080 case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error.");
1081 }
1082
1083 #undef T
1084
1085 }
1086 }
1087
1088 upb_status status;
1089 upb_sink_endmsg(sink, &status);
1090 }
1091
1092 static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
1093 if (desc->pb_serialize_handlers == NULL) {
1094 desc->pb_serialize_handlers =
1095 upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers);
1096 }
1097 return desc->pb_serialize_handlers;
1098 }
1099
1100 static const upb_handlers* msgdef_json_serialize_handlers(Descriptor* desc) {
1101 if (desc->json_serialize_handlers == NULL) {
1102 desc->json_serialize_handlers =
1103 upb_json_printer_newhandlers(
1104 desc->msgdef, &desc->json_serialize_handlers);
1105 }
1106 return desc->json_serialize_handlers;
1107 }
1108
1109 /*
1110 * call-seq:
1111 * MessageClass.encode(msg) => bytes
1112 *
1113 * Encodes the given message object to its serialized form in protocol buffers
1114 * wire format.
1115 */
1116 VALUE Message_encode(VALUE klass, VALUE msg_rb) {
1117 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
1118 Descriptor* desc = ruby_to_Descriptor(descriptor);
1119
1120 stringsink sink;
1121 stringsink_init(&sink);
1122
1123 const upb_handlers* serialize_handlers =
1124 msgdef_pb_serialize_handlers(desc);
1125
1126 stackenv se;
1127 stackenv_init(&se, "Error occurred during encoding: %s");
1128 upb_pb_encoder* encoder =
1129 upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink);
1130
1131 putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0);
1132
1133 VALUE ret = rb_str_new(sink.ptr, sink.len);
1134
1135 stackenv_uninit(&se);
1136 stringsink_uninit(&sink);
1137
1138 return ret;
1139 }
1140
1141 /*
1142 * call-seq:
1143 * MessageClass.encode_json(msg) => json_string
1144 *
1145 * Encodes the given message object into its serialized JSON representation.
1146 */
1147 VALUE Message_encode_json(VALUE klass, VALUE msg_rb) {
1148 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
1149 Descriptor* desc = ruby_to_Descriptor(descriptor);
1150
1151 stringsink sink;
1152 stringsink_init(&sink);
1153
1154 const upb_handlers* serialize_handlers =
1155 msgdef_json_serialize_handlers(desc);
1156
1157 stackenv se;
1158 stackenv_init(&se, "Error occurred during encoding: %s");
1159 upb_json_printer* printer =
1160 upb_json_printer_create(&se.env, serialize_handlers, &sink.sink);
1161
1162 putmsg(msg_rb, desc, upb_json_printer_input(printer), 0);
1163
1164 VALUE ret = rb_str_new(sink.ptr, sink.len);
1165
1166 stackenv_uninit(&se);
1167 stringsink_uninit(&sink);
1168
1169 return ret;
1170 }
1171
OLDNEW
« no previous file with comments | « third_party/protobuf/ruby/ext/google/protobuf_c/defs.c ('k') | third_party/protobuf/ruby/ext/google/protobuf_c/extconf.rb » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698