1ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format 2ffe3c632Sopenharmony_ci// Copyright 2014 Google Inc. All rights reserved. 3ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/ 4ffe3c632Sopenharmony_ci// 5ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 6ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are 7ffe3c632Sopenharmony_ci// met: 8ffe3c632Sopenharmony_ci// 9ffe3c632Sopenharmony_ci// * Redistributions of source code must retain the above copyright 10ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer. 11ffe3c632Sopenharmony_ci// * Redistributions in binary form must reproduce the above 12ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer 13ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the 14ffe3c632Sopenharmony_ci// distribution. 15ffe3c632Sopenharmony_ci// * Neither the name of Google Inc. nor the names of its 16ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from 17ffe3c632Sopenharmony_ci// this software without specific prior written permission. 18ffe3c632Sopenharmony_ci// 19ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30ffe3c632Sopenharmony_ci 31ffe3c632Sopenharmony_ci#include "protobuf.h" 32ffe3c632Sopenharmony_ci 33ffe3c632Sopenharmony_ciVALUE initialize_rb_class_with_no_args(VALUE klass) { 34ffe3c632Sopenharmony_ci return rb_funcall(klass, rb_intern("new"), 0); 35ffe3c632Sopenharmony_ci} 36ffe3c632Sopenharmony_ci 37ffe3c632Sopenharmony_ci// This function is equivalent to rb_str_cat(), but unlike the real 38ffe3c632Sopenharmony_ci// rb_str_cat(), it doesn't leak memory in some versions of Ruby. 39ffe3c632Sopenharmony_ci// For more information, see: 40ffe3c632Sopenharmony_ci// https://bugs.ruby-lang.org/issues/11328 41ffe3c632Sopenharmony_ciVALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) { 42ffe3c632Sopenharmony_ci char *p; 43ffe3c632Sopenharmony_ci size_t oldlen = RSTRING_LEN(rb_str); 44ffe3c632Sopenharmony_ci rb_str_modify_expand(rb_str, len); 45ffe3c632Sopenharmony_ci p = RSTRING_PTR(rb_str); 46ffe3c632Sopenharmony_ci memcpy(p + oldlen, str, len); 47ffe3c632Sopenharmony_ci rb_str_set_len(rb_str, oldlen + len); 48ffe3c632Sopenharmony_ci return rb_str; 49ffe3c632Sopenharmony_ci} 50ffe3c632Sopenharmony_ci 51ffe3c632Sopenharmony_cibool is_wrapper(const upb_msgdef* m) { 52ffe3c632Sopenharmony_ci switch (upb_msgdef_wellknowntype(m)) { 53ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_DOUBLEVALUE: 54ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_FLOATVALUE: 55ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_INT64VALUE: 56ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_UINT64VALUE: 57ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_INT32VALUE: 58ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_UINT32VALUE: 59ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_STRINGVALUE: 60ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_BYTESVALUE: 61ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_BOOLVALUE: 62ffe3c632Sopenharmony_ci return true; 63ffe3c632Sopenharmony_ci default: 64ffe3c632Sopenharmony_ci return false; 65ffe3c632Sopenharmony_ci } 66ffe3c632Sopenharmony_ci} 67ffe3c632Sopenharmony_ci 68ffe3c632Sopenharmony_ci// The code below also comes from upb's prototype Ruby binding, developed by 69ffe3c632Sopenharmony_ci// haberman@. 70ffe3c632Sopenharmony_ci 71ffe3c632Sopenharmony_ci/* stringsink *****************************************************************/ 72ffe3c632Sopenharmony_ci 73ffe3c632Sopenharmony_cistatic void *stringsink_start(void *_sink, const void *hd, size_t size_hint) { 74ffe3c632Sopenharmony_ci stringsink *sink = _sink; 75ffe3c632Sopenharmony_ci sink->len = 0; 76ffe3c632Sopenharmony_ci return sink; 77ffe3c632Sopenharmony_ci} 78ffe3c632Sopenharmony_ci 79ffe3c632Sopenharmony_cistatic size_t stringsink_string(void *_sink, const void *hd, const char *ptr, 80ffe3c632Sopenharmony_ci size_t len, const upb_bufhandle *handle) { 81ffe3c632Sopenharmony_ci stringsink *sink = _sink; 82ffe3c632Sopenharmony_ci size_t new_size = sink->size; 83ffe3c632Sopenharmony_ci 84ffe3c632Sopenharmony_ci UPB_UNUSED(hd); 85ffe3c632Sopenharmony_ci UPB_UNUSED(handle); 86ffe3c632Sopenharmony_ci 87ffe3c632Sopenharmony_ci while (sink->len + len > new_size) { 88ffe3c632Sopenharmony_ci new_size *= 2; 89ffe3c632Sopenharmony_ci } 90ffe3c632Sopenharmony_ci 91ffe3c632Sopenharmony_ci if (new_size != sink->size) { 92ffe3c632Sopenharmony_ci sink->ptr = realloc(sink->ptr, new_size); 93ffe3c632Sopenharmony_ci sink->size = new_size; 94ffe3c632Sopenharmony_ci } 95ffe3c632Sopenharmony_ci 96ffe3c632Sopenharmony_ci memcpy(sink->ptr + sink->len, ptr, len); 97ffe3c632Sopenharmony_ci sink->len += len; 98ffe3c632Sopenharmony_ci 99ffe3c632Sopenharmony_ci return len; 100ffe3c632Sopenharmony_ci} 101ffe3c632Sopenharmony_ci 102ffe3c632Sopenharmony_civoid stringsink_init(stringsink *sink) { 103ffe3c632Sopenharmony_ci upb_byteshandler_init(&sink->handler); 104ffe3c632Sopenharmony_ci upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL); 105ffe3c632Sopenharmony_ci upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL); 106ffe3c632Sopenharmony_ci 107ffe3c632Sopenharmony_ci upb_bytessink_reset(&sink->sink, &sink->handler, sink); 108ffe3c632Sopenharmony_ci 109ffe3c632Sopenharmony_ci sink->size = 32; 110ffe3c632Sopenharmony_ci sink->ptr = malloc(sink->size); 111ffe3c632Sopenharmony_ci sink->len = 0; 112ffe3c632Sopenharmony_ci} 113ffe3c632Sopenharmony_ci 114ffe3c632Sopenharmony_civoid stringsink_uninit(stringsink *sink) { 115ffe3c632Sopenharmony_ci free(sink->ptr); 116ffe3c632Sopenharmony_ci} 117ffe3c632Sopenharmony_ci 118ffe3c632Sopenharmony_ci// ----------------------------------------------------------------------------- 119ffe3c632Sopenharmony_ci// Parsing. 120ffe3c632Sopenharmony_ci// ----------------------------------------------------------------------------- 121ffe3c632Sopenharmony_ci 122ffe3c632Sopenharmony_ci#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs) 123ffe3c632Sopenharmony_ci 124ffe3c632Sopenharmony_citypedef struct { 125ffe3c632Sopenharmony_ci size_t ofs; 126ffe3c632Sopenharmony_ci int32_t hasbit; 127ffe3c632Sopenharmony_ci} field_handlerdata_t; 128ffe3c632Sopenharmony_ci 129ffe3c632Sopenharmony_ci// Creates a handlerdata that contains the offset and the hasbit for the field 130ffe3c632Sopenharmony_cistatic const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit) { 131ffe3c632Sopenharmony_ci field_handlerdata_t *hd = ALLOC(field_handlerdata_t); 132ffe3c632Sopenharmony_ci hd->ofs = ofs; 133ffe3c632Sopenharmony_ci hd->hasbit = hasbit; 134ffe3c632Sopenharmony_ci upb_handlers_addcleanup(h, hd, xfree); 135ffe3c632Sopenharmony_ci return hd; 136ffe3c632Sopenharmony_ci} 137ffe3c632Sopenharmony_ci 138ffe3c632Sopenharmony_citypedef struct { 139ffe3c632Sopenharmony_ci size_t ofs; 140ffe3c632Sopenharmony_ci int32_t hasbit; 141ffe3c632Sopenharmony_ci upb_fieldtype_t wrapped_type; // Only for wrappers. 142ffe3c632Sopenharmony_ci VALUE subklass; 143ffe3c632Sopenharmony_ci} submsg_handlerdata_t; 144ffe3c632Sopenharmony_ci 145ffe3c632Sopenharmony_ci// Creates a handlerdata that contains offset and submessage type information. 146ffe3c632Sopenharmony_cistatic const void *newsubmsghandlerdata(upb_handlers* h, 147ffe3c632Sopenharmony_ci const upb_fielddef *f, 148ffe3c632Sopenharmony_ci uint32_t ofs, 149ffe3c632Sopenharmony_ci int32_t hasbit, 150ffe3c632Sopenharmony_ci VALUE subklass) { 151ffe3c632Sopenharmony_ci submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t); 152ffe3c632Sopenharmony_ci const upb_msgdef *subm = upb_fielddef_msgsubdef(f); 153ffe3c632Sopenharmony_ci hd->ofs = ofs; 154ffe3c632Sopenharmony_ci hd->hasbit = hasbit; 155ffe3c632Sopenharmony_ci hd->subklass = subklass; 156ffe3c632Sopenharmony_ci upb_handlers_addcleanup(h, hd, xfree); 157ffe3c632Sopenharmony_ci if (is_wrapper(subm)) { 158ffe3c632Sopenharmony_ci const upb_fielddef *value_f = upb_msgdef_itof(subm, 1); 159ffe3c632Sopenharmony_ci hd->wrapped_type = upb_fielddef_type(value_f); 160ffe3c632Sopenharmony_ci } 161ffe3c632Sopenharmony_ci return hd; 162ffe3c632Sopenharmony_ci} 163ffe3c632Sopenharmony_ci 164ffe3c632Sopenharmony_citypedef struct { 165ffe3c632Sopenharmony_ci size_t ofs; // union data slot 166ffe3c632Sopenharmony_ci size_t case_ofs; // oneof_case field 167ffe3c632Sopenharmony_ci uint32_t oneof_case_num; // oneof-case number to place in oneof_case field 168ffe3c632Sopenharmony_ci VALUE subklass; 169ffe3c632Sopenharmony_ci} oneof_handlerdata_t; 170ffe3c632Sopenharmony_ci 171ffe3c632Sopenharmony_cistatic const void *newoneofhandlerdata(upb_handlers *h, 172ffe3c632Sopenharmony_ci uint32_t ofs, 173ffe3c632Sopenharmony_ci uint32_t case_ofs, 174ffe3c632Sopenharmony_ci const upb_fielddef *f, 175ffe3c632Sopenharmony_ci const Descriptor* desc) { 176ffe3c632Sopenharmony_ci oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t); 177ffe3c632Sopenharmony_ci hd->ofs = ofs; 178ffe3c632Sopenharmony_ci hd->case_ofs = case_ofs; 179ffe3c632Sopenharmony_ci // We reuse the field tag number as a oneof union discriminant tag. Note that 180ffe3c632Sopenharmony_ci // we don't expose these numbers to the user, so the only requirement is that 181ffe3c632Sopenharmony_ci // we have some unique ID for each union case/possibility. The field tag 182ffe3c632Sopenharmony_ci // numbers are already present and are easy to use so there's no reason to 183ffe3c632Sopenharmony_ci // create a separate ID space. In addition, using the field tag number here 184ffe3c632Sopenharmony_ci // lets us easily look up the field in the oneof accessor. 185ffe3c632Sopenharmony_ci hd->oneof_case_num = upb_fielddef_number(f); 186ffe3c632Sopenharmony_ci if (is_value_field(f)) { 187ffe3c632Sopenharmony_ci hd->oneof_case_num |= ONEOF_CASE_MASK; 188ffe3c632Sopenharmony_ci } 189ffe3c632Sopenharmony_ci hd->subklass = field_type_class(desc->layout, f); 190ffe3c632Sopenharmony_ci upb_handlers_addcleanup(h, hd, xfree); 191ffe3c632Sopenharmony_ci return hd; 192ffe3c632Sopenharmony_ci} 193ffe3c632Sopenharmony_ci 194ffe3c632Sopenharmony_ci// A handler that starts a repeated field. Gets the Repeated*Field instance for 195ffe3c632Sopenharmony_ci// this field (such an instance always exists even in an empty message). 196ffe3c632Sopenharmony_cistatic void *startseq_handler(void* closure, const void* hd) { 197ffe3c632Sopenharmony_ci MessageHeader* msg = closure; 198ffe3c632Sopenharmony_ci const size_t *ofs = hd; 199ffe3c632Sopenharmony_ci return (void*)DEREF(msg, *ofs, VALUE); 200ffe3c632Sopenharmony_ci} 201ffe3c632Sopenharmony_ci 202ffe3c632Sopenharmony_ci// Handlers that append primitive values to a repeated field. 203ffe3c632Sopenharmony_ci#define DEFINE_APPEND_HANDLER(type, ctype) \ 204ffe3c632Sopenharmony_ci static bool append##type##_handler(void *closure, const void *hd, \ 205ffe3c632Sopenharmony_ci ctype val) { \ 206ffe3c632Sopenharmony_ci VALUE ary = (VALUE)closure; \ 207ffe3c632Sopenharmony_ci RepeatedField_push_native(ary, &val); \ 208ffe3c632Sopenharmony_ci return true; \ 209ffe3c632Sopenharmony_ci } 210ffe3c632Sopenharmony_ci 211ffe3c632Sopenharmony_ciDEFINE_APPEND_HANDLER(bool, bool) 212ffe3c632Sopenharmony_ciDEFINE_APPEND_HANDLER(int32, int32_t) 213ffe3c632Sopenharmony_ciDEFINE_APPEND_HANDLER(uint32, uint32_t) 214ffe3c632Sopenharmony_ciDEFINE_APPEND_HANDLER(float, float) 215ffe3c632Sopenharmony_ciDEFINE_APPEND_HANDLER(int64, int64_t) 216ffe3c632Sopenharmony_ciDEFINE_APPEND_HANDLER(uint64, uint64_t) 217ffe3c632Sopenharmony_ciDEFINE_APPEND_HANDLER(double, double) 218ffe3c632Sopenharmony_ci 219ffe3c632Sopenharmony_ci// Appends a string to a repeated field. 220ffe3c632Sopenharmony_cistatic void* appendstr_handler(void *closure, 221ffe3c632Sopenharmony_ci const void *hd, 222ffe3c632Sopenharmony_ci size_t size_hint) { 223ffe3c632Sopenharmony_ci VALUE ary = (VALUE)closure; 224ffe3c632Sopenharmony_ci VALUE str = rb_str_new2(""); 225ffe3c632Sopenharmony_ci rb_enc_associate(str, kRubyStringUtf8Encoding); 226ffe3c632Sopenharmony_ci RepeatedField_push_native(ary, &str); 227ffe3c632Sopenharmony_ci return (void*)str; 228ffe3c632Sopenharmony_ci} 229ffe3c632Sopenharmony_ci 230ffe3c632Sopenharmony_cistatic void set_hasbit(void *closure, int32_t hasbit) { 231ffe3c632Sopenharmony_ci if (hasbit > 0) { 232ffe3c632Sopenharmony_ci uint8_t* storage = closure; 233ffe3c632Sopenharmony_ci storage[hasbit/8] |= 1 << (hasbit % 8); 234ffe3c632Sopenharmony_ci } 235ffe3c632Sopenharmony_ci} 236ffe3c632Sopenharmony_ci 237ffe3c632Sopenharmony_ci// Appends a 'bytes' string to a repeated field. 238ffe3c632Sopenharmony_cistatic void* appendbytes_handler(void *closure, 239ffe3c632Sopenharmony_ci const void *hd, 240ffe3c632Sopenharmony_ci size_t size_hint) { 241ffe3c632Sopenharmony_ci VALUE ary = (VALUE)closure; 242ffe3c632Sopenharmony_ci VALUE str = rb_str_new2(""); 243ffe3c632Sopenharmony_ci rb_enc_associate(str, kRubyString8bitEncoding); 244ffe3c632Sopenharmony_ci RepeatedField_push_native(ary, &str); 245ffe3c632Sopenharmony_ci return (void*)str; 246ffe3c632Sopenharmony_ci} 247ffe3c632Sopenharmony_ci 248ffe3c632Sopenharmony_ci// Sets a non-repeated string field in a message. 249ffe3c632Sopenharmony_cistatic void* str_handler(void *closure, 250ffe3c632Sopenharmony_ci const void *hd, 251ffe3c632Sopenharmony_ci size_t size_hint) { 252ffe3c632Sopenharmony_ci MessageHeader* msg = closure; 253ffe3c632Sopenharmony_ci const field_handlerdata_t *fieldhandler = hd; 254ffe3c632Sopenharmony_ci 255ffe3c632Sopenharmony_ci VALUE str = rb_str_new2(""); 256ffe3c632Sopenharmony_ci rb_enc_associate(str, kRubyStringUtf8Encoding); 257ffe3c632Sopenharmony_ci DEREF(msg, fieldhandler->ofs, VALUE) = str; 258ffe3c632Sopenharmony_ci set_hasbit(closure, fieldhandler->hasbit); 259ffe3c632Sopenharmony_ci return (void*)str; 260ffe3c632Sopenharmony_ci} 261ffe3c632Sopenharmony_ci 262ffe3c632Sopenharmony_ci// Sets a non-repeated 'bytes' field in a message. 263ffe3c632Sopenharmony_cistatic void* bytes_handler(void *closure, 264ffe3c632Sopenharmony_ci const void *hd, 265ffe3c632Sopenharmony_ci size_t size_hint) { 266ffe3c632Sopenharmony_ci MessageHeader* msg = closure; 267ffe3c632Sopenharmony_ci const field_handlerdata_t *fieldhandler = hd; 268ffe3c632Sopenharmony_ci 269ffe3c632Sopenharmony_ci VALUE str = rb_str_new2(""); 270ffe3c632Sopenharmony_ci rb_enc_associate(str, kRubyString8bitEncoding); 271ffe3c632Sopenharmony_ci DEREF(msg, fieldhandler->ofs, VALUE) = str; 272ffe3c632Sopenharmony_ci set_hasbit(closure, fieldhandler->hasbit); 273ffe3c632Sopenharmony_ci return (void*)str; 274ffe3c632Sopenharmony_ci} 275ffe3c632Sopenharmony_ci 276ffe3c632Sopenharmony_cistatic size_t stringdata_handler(void* closure, const void* hd, 277ffe3c632Sopenharmony_ci const char* str, size_t len, 278ffe3c632Sopenharmony_ci const upb_bufhandle* handle) { 279ffe3c632Sopenharmony_ci VALUE rb_str = (VALUE)closure; 280ffe3c632Sopenharmony_ci noleak_rb_str_cat(rb_str, str, len); 281ffe3c632Sopenharmony_ci return len; 282ffe3c632Sopenharmony_ci} 283ffe3c632Sopenharmony_ci 284ffe3c632Sopenharmony_cistatic bool stringdata_end_handler(void* closure, const void* hd) { 285ffe3c632Sopenharmony_ci VALUE rb_str = (VALUE)closure; 286ffe3c632Sopenharmony_ci rb_obj_freeze(rb_str); 287ffe3c632Sopenharmony_ci return true; 288ffe3c632Sopenharmony_ci} 289ffe3c632Sopenharmony_ci 290ffe3c632Sopenharmony_cistatic bool appendstring_end_handler(void* closure, const void* hd) { 291ffe3c632Sopenharmony_ci VALUE rb_str = (VALUE)closure; 292ffe3c632Sopenharmony_ci rb_obj_freeze(rb_str); 293ffe3c632Sopenharmony_ci return true; 294ffe3c632Sopenharmony_ci} 295ffe3c632Sopenharmony_ci 296ffe3c632Sopenharmony_ci// Appends a submessage to a repeated field (a regular Ruby array for now). 297ffe3c632Sopenharmony_cistatic void *appendsubmsg_handler(void *closure, const void *hd) { 298ffe3c632Sopenharmony_ci VALUE ary = (VALUE)closure; 299ffe3c632Sopenharmony_ci const submsg_handlerdata_t *submsgdata = hd; 300ffe3c632Sopenharmony_ci MessageHeader* submsg; 301ffe3c632Sopenharmony_ci 302ffe3c632Sopenharmony_ci VALUE submsg_rb = initialize_rb_class_with_no_args(submsgdata->subklass); 303ffe3c632Sopenharmony_ci RepeatedField_push(ary, submsg_rb); 304ffe3c632Sopenharmony_ci 305ffe3c632Sopenharmony_ci TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); 306ffe3c632Sopenharmony_ci return submsg; 307ffe3c632Sopenharmony_ci} 308ffe3c632Sopenharmony_ci 309ffe3c632Sopenharmony_ci// Appends a wrapper to a repeated field (a regular Ruby array for now). 310ffe3c632Sopenharmony_cistatic void *appendwrapper_handler(void *closure, const void *hd) { 311ffe3c632Sopenharmony_ci VALUE ary = (VALUE)closure; 312ffe3c632Sopenharmony_ci int size = RepeatedField_size(ary); 313ffe3c632Sopenharmony_ci (void)hd; 314ffe3c632Sopenharmony_ci 315ffe3c632Sopenharmony_ci RepeatedField_push(ary, Qnil); 316ffe3c632Sopenharmony_ci 317ffe3c632Sopenharmony_ci return RepeatedField_index_native(ary, size); 318ffe3c632Sopenharmony_ci} 319ffe3c632Sopenharmony_ci 320ffe3c632Sopenharmony_ci// Sets a non-repeated submessage field in a message. 321ffe3c632Sopenharmony_cistatic void *submsg_handler(void *closure, const void *hd) { 322ffe3c632Sopenharmony_ci MessageHeader* msg = closure; 323ffe3c632Sopenharmony_ci const submsg_handlerdata_t* submsgdata = hd; 324ffe3c632Sopenharmony_ci VALUE submsg_rb; 325ffe3c632Sopenharmony_ci MessageHeader* submsg; 326ffe3c632Sopenharmony_ci 327ffe3c632Sopenharmony_ci if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) { 328ffe3c632Sopenharmony_ci DEREF(msg, submsgdata->ofs, VALUE) = 329ffe3c632Sopenharmony_ci initialize_rb_class_with_no_args(submsgdata->subklass); 330ffe3c632Sopenharmony_ci } 331ffe3c632Sopenharmony_ci 332ffe3c632Sopenharmony_ci set_hasbit(closure, submsgdata->hasbit); 333ffe3c632Sopenharmony_ci 334ffe3c632Sopenharmony_ci submsg_rb = DEREF(msg, submsgdata->ofs, VALUE); 335ffe3c632Sopenharmony_ci TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); 336ffe3c632Sopenharmony_ci 337ffe3c632Sopenharmony_ci return submsg; 338ffe3c632Sopenharmony_ci} 339ffe3c632Sopenharmony_ci 340ffe3c632Sopenharmony_cistatic void* startwrapper(void* closure, const void* hd) { 341ffe3c632Sopenharmony_ci const submsg_handlerdata_t* submsgdata = hd; 342ffe3c632Sopenharmony_ci char* msg = closure; 343ffe3c632Sopenharmony_ci VALUE* field = (VALUE*)(msg + submsgdata->ofs); 344ffe3c632Sopenharmony_ci 345ffe3c632Sopenharmony_ci set_hasbit(closure, submsgdata->hasbit); 346ffe3c632Sopenharmony_ci 347ffe3c632Sopenharmony_ci switch (submsgdata->wrapped_type) { 348ffe3c632Sopenharmony_ci case UPB_TYPE_FLOAT: 349ffe3c632Sopenharmony_ci case UPB_TYPE_DOUBLE: 350ffe3c632Sopenharmony_ci *field = DBL2NUM(0); 351ffe3c632Sopenharmony_ci break; 352ffe3c632Sopenharmony_ci case UPB_TYPE_BOOL: 353ffe3c632Sopenharmony_ci *field = Qfalse; 354ffe3c632Sopenharmony_ci break; 355ffe3c632Sopenharmony_ci case UPB_TYPE_STRING: 356ffe3c632Sopenharmony_ci *field = get_frozen_string(NULL, 0, false); 357ffe3c632Sopenharmony_ci break; 358ffe3c632Sopenharmony_ci case UPB_TYPE_BYTES: 359ffe3c632Sopenharmony_ci *field = get_frozen_string(NULL, 0, true); 360ffe3c632Sopenharmony_ci break; 361ffe3c632Sopenharmony_ci case UPB_TYPE_ENUM: 362ffe3c632Sopenharmony_ci case UPB_TYPE_INT32: 363ffe3c632Sopenharmony_ci case UPB_TYPE_INT64: 364ffe3c632Sopenharmony_ci case UPB_TYPE_UINT32: 365ffe3c632Sopenharmony_ci case UPB_TYPE_UINT64: 366ffe3c632Sopenharmony_ci *field = INT2NUM(0); 367ffe3c632Sopenharmony_ci break; 368ffe3c632Sopenharmony_ci case UPB_TYPE_MESSAGE: 369ffe3c632Sopenharmony_ci rb_raise(rb_eRuntimeError, 370ffe3c632Sopenharmony_ci "Internal logic error with well-known types."); 371ffe3c632Sopenharmony_ci } 372ffe3c632Sopenharmony_ci 373ffe3c632Sopenharmony_ci return field; 374ffe3c632Sopenharmony_ci} 375ffe3c632Sopenharmony_ci 376ffe3c632Sopenharmony_ci// Handler data for startmap/endmap handlers. 377ffe3c632Sopenharmony_citypedef struct { 378ffe3c632Sopenharmony_ci size_t ofs; 379ffe3c632Sopenharmony_ci upb_fieldtype_t key_field_type; 380ffe3c632Sopenharmony_ci upb_fieldtype_t value_field_type; 381ffe3c632Sopenharmony_ci VALUE subklass; 382ffe3c632Sopenharmony_ci} map_handlerdata_t; 383ffe3c632Sopenharmony_ci 384ffe3c632Sopenharmony_ci// Temporary frame for map parsing: at the beginning of a map entry message, a 385ffe3c632Sopenharmony_ci// submsg handler allocates a frame to hold (i) a reference to the Map object 386ffe3c632Sopenharmony_ci// into which this message will be inserted and (ii) storage slots to 387ffe3c632Sopenharmony_ci// temporarily hold the key and value for this map entry until the end of the 388ffe3c632Sopenharmony_ci// submessage. When the submessage ends, another handler is called to insert the 389ffe3c632Sopenharmony_ci// value into the map. 390ffe3c632Sopenharmony_citypedef struct { 391ffe3c632Sopenharmony_ci VALUE map; 392ffe3c632Sopenharmony_ci const map_handlerdata_t* handlerdata; 393ffe3c632Sopenharmony_ci char key_storage[NATIVE_SLOT_MAX_SIZE]; 394ffe3c632Sopenharmony_ci char value_storage[NATIVE_SLOT_MAX_SIZE]; 395ffe3c632Sopenharmony_ci} map_parse_frame_t; 396ffe3c632Sopenharmony_ci 397ffe3c632Sopenharmony_cistatic void MapParseFrame_mark(void* _self) { 398ffe3c632Sopenharmony_ci map_parse_frame_t* frame = _self; 399ffe3c632Sopenharmony_ci 400ffe3c632Sopenharmony_ci // This shouldn't strictly be necessary since this should be rooted by the 401ffe3c632Sopenharmony_ci // message itself, but it can't hurt. 402ffe3c632Sopenharmony_ci rb_gc_mark(frame->map); 403ffe3c632Sopenharmony_ci 404ffe3c632Sopenharmony_ci native_slot_mark(frame->handlerdata->key_field_type, &frame->key_storage); 405ffe3c632Sopenharmony_ci native_slot_mark(frame->handlerdata->value_field_type, &frame->value_storage); 406ffe3c632Sopenharmony_ci} 407ffe3c632Sopenharmony_ci 408ffe3c632Sopenharmony_civoid MapParseFrame_free(void* self) { 409ffe3c632Sopenharmony_ci xfree(self); 410ffe3c632Sopenharmony_ci} 411ffe3c632Sopenharmony_ci 412ffe3c632Sopenharmony_cirb_data_type_t MapParseFrame_type = { 413ffe3c632Sopenharmony_ci "MapParseFrame", 414ffe3c632Sopenharmony_ci { MapParseFrame_mark, MapParseFrame_free, NULL }, 415ffe3c632Sopenharmony_ci}; 416ffe3c632Sopenharmony_ci 417ffe3c632Sopenharmony_ci// Handler to begin a map entry: allocates a temporary frame. This is the 418ffe3c632Sopenharmony_ci// 'startsubmsg' handler on the msgdef that contains the map field. 419ffe3c632Sopenharmony_cistatic void *startmap_handler(void *closure, const void *hd) { 420ffe3c632Sopenharmony_ci MessageHeader* msg = closure; 421ffe3c632Sopenharmony_ci const map_handlerdata_t* mapdata = hd; 422ffe3c632Sopenharmony_ci map_parse_frame_t* frame = ALLOC(map_parse_frame_t); 423ffe3c632Sopenharmony_ci VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE); 424ffe3c632Sopenharmony_ci 425ffe3c632Sopenharmony_ci frame->handlerdata = mapdata; 426ffe3c632Sopenharmony_ci frame->map = map_rb; 427ffe3c632Sopenharmony_ci native_slot_init(mapdata->key_field_type, &frame->key_storage); 428ffe3c632Sopenharmony_ci native_slot_init(mapdata->value_field_type, &frame->value_storage); 429ffe3c632Sopenharmony_ci 430ffe3c632Sopenharmony_ci Map_set_frame(map_rb, 431ffe3c632Sopenharmony_ci TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame)); 432ffe3c632Sopenharmony_ci 433ffe3c632Sopenharmony_ci return frame; 434ffe3c632Sopenharmony_ci} 435ffe3c632Sopenharmony_ci 436ffe3c632Sopenharmony_cistatic bool endmap_handler(void *closure, const void *hd) { 437ffe3c632Sopenharmony_ci map_parse_frame_t* frame = closure; 438ffe3c632Sopenharmony_ci Map_set_frame(frame->map, Qnil); 439ffe3c632Sopenharmony_ci return true; 440ffe3c632Sopenharmony_ci} 441ffe3c632Sopenharmony_ci 442ffe3c632Sopenharmony_ci// Handler to end a map entry: inserts the value defined during the message into 443ffe3c632Sopenharmony_ci// the map. This is the 'endmsg' handler on the map entry msgdef. 444ffe3c632Sopenharmony_cistatic bool endmapentry_handler(void* closure, const void* hd, upb_status* s) { 445ffe3c632Sopenharmony_ci map_parse_frame_t* frame = closure; 446ffe3c632Sopenharmony_ci const map_handlerdata_t* mapdata = hd; 447ffe3c632Sopenharmony_ci 448ffe3c632Sopenharmony_ci VALUE key = native_slot_get( 449ffe3c632Sopenharmony_ci mapdata->key_field_type, Qnil, 450ffe3c632Sopenharmony_ci &frame->key_storage); 451ffe3c632Sopenharmony_ci 452ffe3c632Sopenharmony_ci VALUE value = native_slot_get( 453ffe3c632Sopenharmony_ci mapdata->value_field_type, mapdata->subklass, 454ffe3c632Sopenharmony_ci &frame->value_storage); 455ffe3c632Sopenharmony_ci 456ffe3c632Sopenharmony_ci Map_index_set(frame->map, key, value); 457ffe3c632Sopenharmony_ci 458ffe3c632Sopenharmony_ci return true; 459ffe3c632Sopenharmony_ci} 460ffe3c632Sopenharmony_ci 461ffe3c632Sopenharmony_ci// Allocates a new map_handlerdata_t given the map entry message definition. If 462ffe3c632Sopenharmony_ci// the offset of the field within the parent message is also given, that is 463ffe3c632Sopenharmony_ci// added to the handler data as well. Note that this is called *twice* per map 464ffe3c632Sopenharmony_ci// field: once in the parent message handler setup when setting the startsubmsg 465ffe3c632Sopenharmony_ci// handler and once in the map entry message handler setup when setting the 466ffe3c632Sopenharmony_ci// key/value and endmsg handlers. The reason is that there is no easy way to 467ffe3c632Sopenharmony_ci// pass the handlerdata down to the sub-message handler setup. 468ffe3c632Sopenharmony_cistatic map_handlerdata_t* new_map_handlerdata( 469ffe3c632Sopenharmony_ci size_t ofs, 470ffe3c632Sopenharmony_ci const upb_msgdef* mapentry_def, 471ffe3c632Sopenharmony_ci const Descriptor* desc) { 472ffe3c632Sopenharmony_ci const upb_fielddef* key_field; 473ffe3c632Sopenharmony_ci const upb_fielddef* value_field; 474ffe3c632Sopenharmony_ci map_handlerdata_t* hd = ALLOC(map_handlerdata_t); 475ffe3c632Sopenharmony_ci hd->ofs = ofs; 476ffe3c632Sopenharmony_ci key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD); 477ffe3c632Sopenharmony_ci assert(key_field != NULL); 478ffe3c632Sopenharmony_ci hd->key_field_type = upb_fielddef_type(key_field); 479ffe3c632Sopenharmony_ci value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD); 480ffe3c632Sopenharmony_ci assert(value_field != NULL); 481ffe3c632Sopenharmony_ci hd->value_field_type = upb_fielddef_type(value_field); 482ffe3c632Sopenharmony_ci hd->subklass = field_type_class(desc->layout, value_field); 483ffe3c632Sopenharmony_ci 484ffe3c632Sopenharmony_ci return hd; 485ffe3c632Sopenharmony_ci} 486ffe3c632Sopenharmony_ci 487ffe3c632Sopenharmony_ci// Handlers that set primitive values in oneofs. 488ffe3c632Sopenharmony_ci#define DEFINE_ONEOF_HANDLER(type, ctype) \ 489ffe3c632Sopenharmony_ci static bool oneof##type##_handler(void *closure, const void *hd, \ 490ffe3c632Sopenharmony_ci ctype val) { \ 491ffe3c632Sopenharmony_ci const oneof_handlerdata_t *oneofdata = hd; \ 492ffe3c632Sopenharmony_ci DEREF(closure, oneofdata->case_ofs, uint32_t) = \ 493ffe3c632Sopenharmony_ci oneofdata->oneof_case_num; \ 494ffe3c632Sopenharmony_ci DEREF(closure, oneofdata->ofs, ctype) = val; \ 495ffe3c632Sopenharmony_ci return true; \ 496ffe3c632Sopenharmony_ci } 497ffe3c632Sopenharmony_ci 498ffe3c632Sopenharmony_ciDEFINE_ONEOF_HANDLER(bool, bool) 499ffe3c632Sopenharmony_ciDEFINE_ONEOF_HANDLER(int32, int32_t) 500ffe3c632Sopenharmony_ciDEFINE_ONEOF_HANDLER(uint32, uint32_t) 501ffe3c632Sopenharmony_ciDEFINE_ONEOF_HANDLER(float, float) 502ffe3c632Sopenharmony_ciDEFINE_ONEOF_HANDLER(int64, int64_t) 503ffe3c632Sopenharmony_ciDEFINE_ONEOF_HANDLER(uint64, uint64_t) 504ffe3c632Sopenharmony_ciDEFINE_ONEOF_HANDLER(double, double) 505ffe3c632Sopenharmony_ci 506ffe3c632Sopenharmony_ci#undef DEFINE_ONEOF_HANDLER 507ffe3c632Sopenharmony_ci 508ffe3c632Sopenharmony_ci// Handlers for strings in a oneof. 509ffe3c632Sopenharmony_cistatic void *oneofstr_handler(void *closure, 510ffe3c632Sopenharmony_ci const void *hd, 511ffe3c632Sopenharmony_ci size_t size_hint) { 512ffe3c632Sopenharmony_ci MessageHeader* msg = closure; 513ffe3c632Sopenharmony_ci const oneof_handlerdata_t *oneofdata = hd; 514ffe3c632Sopenharmony_ci VALUE str = rb_str_new2(""); 515ffe3c632Sopenharmony_ci rb_enc_associate(str, kRubyStringUtf8Encoding); 516ffe3c632Sopenharmony_ci DEREF(msg, oneofdata->case_ofs, uint32_t) = 517ffe3c632Sopenharmony_ci oneofdata->oneof_case_num; 518ffe3c632Sopenharmony_ci DEREF(msg, oneofdata->ofs, VALUE) = str; 519ffe3c632Sopenharmony_ci return (void*)str; 520ffe3c632Sopenharmony_ci} 521ffe3c632Sopenharmony_ci 522ffe3c632Sopenharmony_cistatic void *oneofbytes_handler(void *closure, 523ffe3c632Sopenharmony_ci const void *hd, 524ffe3c632Sopenharmony_ci size_t size_hint) { 525ffe3c632Sopenharmony_ci MessageHeader* msg = closure; 526ffe3c632Sopenharmony_ci const oneof_handlerdata_t *oneofdata = hd; 527ffe3c632Sopenharmony_ci VALUE str = rb_str_new2(""); 528ffe3c632Sopenharmony_ci rb_enc_associate(str, kRubyString8bitEncoding); 529ffe3c632Sopenharmony_ci DEREF(msg, oneofdata->case_ofs, uint32_t) = 530ffe3c632Sopenharmony_ci oneofdata->oneof_case_num; 531ffe3c632Sopenharmony_ci DEREF(msg, oneofdata->ofs, VALUE) = str; 532ffe3c632Sopenharmony_ci return (void*)str; 533ffe3c632Sopenharmony_ci} 534ffe3c632Sopenharmony_ci 535ffe3c632Sopenharmony_cistatic bool oneofstring_end_handler(void* closure, const void* hd) { 536ffe3c632Sopenharmony_ci VALUE rb_str = rb_str_new2(""); 537ffe3c632Sopenharmony_ci rb_obj_freeze(rb_str); 538ffe3c632Sopenharmony_ci return true; 539ffe3c632Sopenharmony_ci} 540ffe3c632Sopenharmony_ci 541ffe3c632Sopenharmony_ci// Handler for a submessage field in a oneof. 542ffe3c632Sopenharmony_cistatic void *oneofsubmsg_handler(void *closure, 543ffe3c632Sopenharmony_ci const void *hd) { 544ffe3c632Sopenharmony_ci MessageHeader* msg = closure; 545ffe3c632Sopenharmony_ci const oneof_handlerdata_t *oneofdata = hd; 546ffe3c632Sopenharmony_ci uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t); 547ffe3c632Sopenharmony_ci 548ffe3c632Sopenharmony_ci VALUE submsg_rb; 549ffe3c632Sopenharmony_ci MessageHeader* submsg; 550ffe3c632Sopenharmony_ci 551ffe3c632Sopenharmony_ci if (oldcase != oneofdata->oneof_case_num || 552ffe3c632Sopenharmony_ci DEREF(msg, oneofdata->ofs, VALUE) == Qnil) { 553ffe3c632Sopenharmony_ci DEREF(msg, oneofdata->ofs, VALUE) = 554ffe3c632Sopenharmony_ci initialize_rb_class_with_no_args(oneofdata->subklass); 555ffe3c632Sopenharmony_ci } 556ffe3c632Sopenharmony_ci // Set the oneof case *after* allocating the new class instance -- otherwise, 557ffe3c632Sopenharmony_ci // if the Ruby GC is invoked as part of a call into the VM, it might invoke 558ffe3c632Sopenharmony_ci // our mark routines, and our mark routines might see the case value 559ffe3c632Sopenharmony_ci // indicating a VALUE is present and expect a valid VALUE. See comment in 560ffe3c632Sopenharmony_ci // layout_set() for more detail: basically, the change to the value and the 561ffe3c632Sopenharmony_ci // case must be atomic w.r.t. the Ruby VM. 562ffe3c632Sopenharmony_ci DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num; 563ffe3c632Sopenharmony_ci 564ffe3c632Sopenharmony_ci submsg_rb = DEREF(msg, oneofdata->ofs, VALUE); 565ffe3c632Sopenharmony_ci TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); 566ffe3c632Sopenharmony_ci return submsg; 567ffe3c632Sopenharmony_ci} 568ffe3c632Sopenharmony_ci 569ffe3c632Sopenharmony_cistatic void* oneof_startwrapper(void* closure, const void* hd) { 570ffe3c632Sopenharmony_ci char* msg = closure; 571ffe3c632Sopenharmony_ci const oneof_handlerdata_t *oneofdata = hd; 572ffe3c632Sopenharmony_ci 573ffe3c632Sopenharmony_ci DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num; 574ffe3c632Sopenharmony_ci 575ffe3c632Sopenharmony_ci return msg + oneofdata->ofs; 576ffe3c632Sopenharmony_ci} 577ffe3c632Sopenharmony_ci 578ffe3c632Sopenharmony_ci// Set up handlers for a repeated field. 579ffe3c632Sopenharmony_cistatic void add_handlers_for_repeated_field(upb_handlers *h, 580ffe3c632Sopenharmony_ci const Descriptor* desc, 581ffe3c632Sopenharmony_ci const upb_fielddef *f, 582ffe3c632Sopenharmony_ci size_t offset) { 583ffe3c632Sopenharmony_ci upb_handlerattr attr = UPB_HANDLERATTR_INIT; 584ffe3c632Sopenharmony_ci attr.handler_data = newhandlerdata(h, offset, -1); 585ffe3c632Sopenharmony_ci upb_handlers_setstartseq(h, f, startseq_handler, &attr); 586ffe3c632Sopenharmony_ci 587ffe3c632Sopenharmony_ci switch (upb_fielddef_type(f)) { 588ffe3c632Sopenharmony_ci 589ffe3c632Sopenharmony_ci#define SET_HANDLER(utype, ltype) \ 590ffe3c632Sopenharmony_ci case utype: \ 591ffe3c632Sopenharmony_ci upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \ 592ffe3c632Sopenharmony_ci break; 593ffe3c632Sopenharmony_ci 594ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_BOOL, bool); 595ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_INT32, int32); 596ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_UINT32, uint32); 597ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_ENUM, int32); 598ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_FLOAT, float); 599ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_INT64, int64); 600ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_UINT64, uint64); 601ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_DOUBLE, double); 602ffe3c632Sopenharmony_ci 603ffe3c632Sopenharmony_ci#undef SET_HANDLER 604ffe3c632Sopenharmony_ci 605ffe3c632Sopenharmony_ci case UPB_TYPE_STRING: 606ffe3c632Sopenharmony_ci case UPB_TYPE_BYTES: { 607ffe3c632Sopenharmony_ci bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; 608ffe3c632Sopenharmony_ci upb_handlers_setstartstr(h, f, is_bytes ? 609ffe3c632Sopenharmony_ci appendbytes_handler : appendstr_handler, 610ffe3c632Sopenharmony_ci NULL); 611ffe3c632Sopenharmony_ci upb_handlers_setstring(h, f, stringdata_handler, NULL); 612ffe3c632Sopenharmony_ci upb_handlers_setendstr(h, f, appendstring_end_handler, NULL); 613ffe3c632Sopenharmony_ci break; 614ffe3c632Sopenharmony_ci } 615ffe3c632Sopenharmony_ci case UPB_TYPE_MESSAGE: { 616ffe3c632Sopenharmony_ci VALUE subklass = field_type_class(desc->layout, f); 617ffe3c632Sopenharmony_ci upb_handlerattr attr = UPB_HANDLERATTR_INIT; 618ffe3c632Sopenharmony_ci attr.handler_data = newsubmsghandlerdata(h, f, 0, -1, subklass); 619ffe3c632Sopenharmony_ci if (is_wrapper(upb_fielddef_msgsubdef(f))) { 620ffe3c632Sopenharmony_ci upb_handlers_setstartsubmsg(h, f, appendwrapper_handler, &attr); 621ffe3c632Sopenharmony_ci } else { 622ffe3c632Sopenharmony_ci upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr); 623ffe3c632Sopenharmony_ci } 624ffe3c632Sopenharmony_ci break; 625ffe3c632Sopenharmony_ci } 626ffe3c632Sopenharmony_ci } 627ffe3c632Sopenharmony_ci} 628ffe3c632Sopenharmony_ci 629ffe3c632Sopenharmony_cistatic bool doublewrapper_handler(void* closure, const void* hd, double val) { 630ffe3c632Sopenharmony_ci VALUE* rbval = closure; 631ffe3c632Sopenharmony_ci *rbval = DBL2NUM(val); 632ffe3c632Sopenharmony_ci return true; 633ffe3c632Sopenharmony_ci} 634ffe3c632Sopenharmony_ci 635ffe3c632Sopenharmony_cistatic bool floatwrapper_handler(void* closure, const void* hd, float val) { 636ffe3c632Sopenharmony_ci VALUE* rbval = closure; 637ffe3c632Sopenharmony_ci *rbval = DBL2NUM(val); 638ffe3c632Sopenharmony_ci return true; 639ffe3c632Sopenharmony_ci} 640ffe3c632Sopenharmony_ci 641ffe3c632Sopenharmony_cistatic bool int64wrapper_handler(void* closure, const void* hd, int64_t val) { 642ffe3c632Sopenharmony_ci VALUE* rbval = closure; 643ffe3c632Sopenharmony_ci *rbval = LL2NUM(val); 644ffe3c632Sopenharmony_ci return true; 645ffe3c632Sopenharmony_ci} 646ffe3c632Sopenharmony_ci 647ffe3c632Sopenharmony_cistatic bool uint64wrapper_handler(void* closure, const void* hd, uint64_t val) { 648ffe3c632Sopenharmony_ci VALUE* rbval = closure; 649ffe3c632Sopenharmony_ci *rbval = ULL2NUM(val); 650ffe3c632Sopenharmony_ci return true; 651ffe3c632Sopenharmony_ci} 652ffe3c632Sopenharmony_ci 653ffe3c632Sopenharmony_cistatic bool int32wrapper_handler(void* closure, const void* hd, int32_t val) { 654ffe3c632Sopenharmony_ci VALUE* rbval = closure; 655ffe3c632Sopenharmony_ci *rbval = INT2NUM(val); 656ffe3c632Sopenharmony_ci return true; 657ffe3c632Sopenharmony_ci} 658ffe3c632Sopenharmony_ci 659ffe3c632Sopenharmony_cistatic bool uint32wrapper_handler(void* closure, const void* hd, uint32_t val) { 660ffe3c632Sopenharmony_ci VALUE* rbval = closure; 661ffe3c632Sopenharmony_ci *rbval = UINT2NUM(val); 662ffe3c632Sopenharmony_ci return true; 663ffe3c632Sopenharmony_ci} 664ffe3c632Sopenharmony_ci 665ffe3c632Sopenharmony_cistatic void* startstringwrapper_handler(void* closure, const void* hd, 666ffe3c632Sopenharmony_ci size_t size_hint) { 667ffe3c632Sopenharmony_ci VALUE* rbval = closure; 668ffe3c632Sopenharmony_ci (void)size_hint; 669ffe3c632Sopenharmony_ci *rbval = rb_str_new(NULL, 0); 670ffe3c632Sopenharmony_ci rb_enc_associate(*rbval, kRubyStringUtf8Encoding); 671ffe3c632Sopenharmony_ci return closure; 672ffe3c632Sopenharmony_ci} 673ffe3c632Sopenharmony_ci 674ffe3c632Sopenharmony_cistatic size_t stringwrapper_handler(void* closure, const void* hd, 675ffe3c632Sopenharmony_ci const char* ptr, size_t len, 676ffe3c632Sopenharmony_ci const upb_bufhandle* handle) { 677ffe3c632Sopenharmony_ci VALUE* rbval = closure; 678ffe3c632Sopenharmony_ci *rbval = noleak_rb_str_cat(*rbval, ptr, len); 679ffe3c632Sopenharmony_ci return len; 680ffe3c632Sopenharmony_ci} 681ffe3c632Sopenharmony_ci 682ffe3c632Sopenharmony_cistatic void* startbyteswrapper_handler(void* closure, const void* hd, 683ffe3c632Sopenharmony_ci size_t size_hint) { 684ffe3c632Sopenharmony_ci VALUE* rbval = closure; 685ffe3c632Sopenharmony_ci (void)size_hint; 686ffe3c632Sopenharmony_ci *rbval = rb_str_new(NULL, 0); 687ffe3c632Sopenharmony_ci rb_enc_associate(*rbval, kRubyString8bitEncoding); 688ffe3c632Sopenharmony_ci return closure; 689ffe3c632Sopenharmony_ci} 690ffe3c632Sopenharmony_ci 691ffe3c632Sopenharmony_cistatic size_t byteswrapper_handler(void* closure, const void* hd, 692ffe3c632Sopenharmony_ci const char* ptr, size_t len, 693ffe3c632Sopenharmony_ci const upb_bufhandle* handle) { 694ffe3c632Sopenharmony_ci VALUE* rbval = closure; 695ffe3c632Sopenharmony_ci *rbval = noleak_rb_str_cat(*rbval, ptr, len); 696ffe3c632Sopenharmony_ci return len; 697ffe3c632Sopenharmony_ci} 698ffe3c632Sopenharmony_ci 699ffe3c632Sopenharmony_cistatic bool boolwrapper_handler(void* closure, const void* hd, bool val) { 700ffe3c632Sopenharmony_ci VALUE* rbval = closure; 701ffe3c632Sopenharmony_ci if (val) { 702ffe3c632Sopenharmony_ci *rbval = Qtrue; 703ffe3c632Sopenharmony_ci } else { 704ffe3c632Sopenharmony_ci *rbval = Qfalse; 705ffe3c632Sopenharmony_ci } 706ffe3c632Sopenharmony_ci return true; 707ffe3c632Sopenharmony_ci} 708ffe3c632Sopenharmony_ci 709ffe3c632Sopenharmony_ci// Set up handlers for a singular field. 710ffe3c632Sopenharmony_cistatic void add_handlers_for_singular_field(const Descriptor* desc, 711ffe3c632Sopenharmony_ci upb_handlers* h, 712ffe3c632Sopenharmony_ci const upb_fielddef* f, 713ffe3c632Sopenharmony_ci size_t offset, size_t hasbit_off) { 714ffe3c632Sopenharmony_ci // The offset we pass to UPB points to the start of the Message, 715ffe3c632Sopenharmony_ci // rather than the start of where our data is stored. 716ffe3c632Sopenharmony_ci int32_t hasbit = -1; 717ffe3c632Sopenharmony_ci if (hasbit_off != MESSAGE_FIELD_NO_HASBIT) { 718ffe3c632Sopenharmony_ci hasbit = hasbit_off + sizeof(MessageHeader) * 8; 719ffe3c632Sopenharmony_ci } 720ffe3c632Sopenharmony_ci 721ffe3c632Sopenharmony_ci switch (upb_fielddef_type(f)) { 722ffe3c632Sopenharmony_ci case UPB_TYPE_BOOL: 723ffe3c632Sopenharmony_ci case UPB_TYPE_INT32: 724ffe3c632Sopenharmony_ci case UPB_TYPE_UINT32: 725ffe3c632Sopenharmony_ci case UPB_TYPE_ENUM: 726ffe3c632Sopenharmony_ci case UPB_TYPE_FLOAT: 727ffe3c632Sopenharmony_ci case UPB_TYPE_INT64: 728ffe3c632Sopenharmony_ci case UPB_TYPE_UINT64: 729ffe3c632Sopenharmony_ci case UPB_TYPE_DOUBLE: 730ffe3c632Sopenharmony_ci upb_msg_setscalarhandler(h, f, offset, hasbit); 731ffe3c632Sopenharmony_ci break; 732ffe3c632Sopenharmony_ci case UPB_TYPE_STRING: 733ffe3c632Sopenharmony_ci case UPB_TYPE_BYTES: { 734ffe3c632Sopenharmony_ci bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; 735ffe3c632Sopenharmony_ci upb_handlerattr attr = UPB_HANDLERATTR_INIT; 736ffe3c632Sopenharmony_ci attr.handler_data = newhandlerdata(h, offset, hasbit); 737ffe3c632Sopenharmony_ci upb_handlers_setstartstr(h, f, 738ffe3c632Sopenharmony_ci is_bytes ? bytes_handler : str_handler, 739ffe3c632Sopenharmony_ci &attr); 740ffe3c632Sopenharmony_ci upb_handlers_setstring(h, f, stringdata_handler, &attr); 741ffe3c632Sopenharmony_ci upb_handlers_setendstr(h, f, stringdata_end_handler, &attr); 742ffe3c632Sopenharmony_ci break; 743ffe3c632Sopenharmony_ci } 744ffe3c632Sopenharmony_ci case UPB_TYPE_MESSAGE: { 745ffe3c632Sopenharmony_ci upb_handlerattr attr = UPB_HANDLERATTR_INIT; 746ffe3c632Sopenharmony_ci attr.handler_data = newsubmsghandlerdata( 747ffe3c632Sopenharmony_ci h, f, offset, hasbit, field_type_class(desc->layout, f)); 748ffe3c632Sopenharmony_ci if (is_wrapper(upb_fielddef_msgsubdef(f))) { 749ffe3c632Sopenharmony_ci upb_handlers_setstartsubmsg(h, f, startwrapper, &attr); 750ffe3c632Sopenharmony_ci } else { 751ffe3c632Sopenharmony_ci upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr); 752ffe3c632Sopenharmony_ci } 753ffe3c632Sopenharmony_ci } 754ffe3c632Sopenharmony_ci } 755ffe3c632Sopenharmony_ci} 756ffe3c632Sopenharmony_ci 757ffe3c632Sopenharmony_ci// Adds handlers to a map field. 758ffe3c632Sopenharmony_cistatic void add_handlers_for_mapfield(upb_handlers* h, 759ffe3c632Sopenharmony_ci const upb_fielddef* fielddef, 760ffe3c632Sopenharmony_ci size_t offset, 761ffe3c632Sopenharmony_ci const Descriptor* desc) { 762ffe3c632Sopenharmony_ci const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef); 763ffe3c632Sopenharmony_ci map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc); 764ffe3c632Sopenharmony_ci upb_handlerattr attr = UPB_HANDLERATTR_INIT; 765ffe3c632Sopenharmony_ci 766ffe3c632Sopenharmony_ci upb_handlers_addcleanup(h, hd, xfree); 767ffe3c632Sopenharmony_ci attr.handler_data = hd; 768ffe3c632Sopenharmony_ci upb_handlers_setstartsubmsg(h, fielddef, startmap_handler, &attr); 769ffe3c632Sopenharmony_ci upb_handlers_setendsubmsg(h, fielddef, endmap_handler, &attr); 770ffe3c632Sopenharmony_ci} 771ffe3c632Sopenharmony_ci 772ffe3c632Sopenharmony_ci// Adds handlers to a map-entry msgdef. 773ffe3c632Sopenharmony_cistatic void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h, 774ffe3c632Sopenharmony_ci const Descriptor* desc) { 775ffe3c632Sopenharmony_ci const upb_fielddef* key_field = map_entry_key(msgdef); 776ffe3c632Sopenharmony_ci const upb_fielddef* value_field = map_entry_value(msgdef); 777ffe3c632Sopenharmony_ci map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc); 778ffe3c632Sopenharmony_ci upb_handlerattr attr = UPB_HANDLERATTR_INIT; 779ffe3c632Sopenharmony_ci 780ffe3c632Sopenharmony_ci upb_handlers_addcleanup(h, hd, xfree); 781ffe3c632Sopenharmony_ci attr.handler_data = hd; 782ffe3c632Sopenharmony_ci upb_handlers_setendmsg(h, endmapentry_handler, &attr); 783ffe3c632Sopenharmony_ci 784ffe3c632Sopenharmony_ci add_handlers_for_singular_field( 785ffe3c632Sopenharmony_ci desc, h, key_field, 786ffe3c632Sopenharmony_ci offsetof(map_parse_frame_t, key_storage), 787ffe3c632Sopenharmony_ci MESSAGE_FIELD_NO_HASBIT); 788ffe3c632Sopenharmony_ci add_handlers_for_singular_field( 789ffe3c632Sopenharmony_ci desc, h, value_field, 790ffe3c632Sopenharmony_ci offsetof(map_parse_frame_t, value_storage), 791ffe3c632Sopenharmony_ci MESSAGE_FIELD_NO_HASBIT); 792ffe3c632Sopenharmony_ci} 793ffe3c632Sopenharmony_ci 794ffe3c632Sopenharmony_cistatic void add_handlers_for_wrapper(const upb_msgdef* msgdef, 795ffe3c632Sopenharmony_ci upb_handlers* h) { 796ffe3c632Sopenharmony_ci const upb_fielddef* f = upb_msgdef_itof(msgdef, 1); 797ffe3c632Sopenharmony_ci switch (upb_msgdef_wellknowntype(msgdef)) { 798ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_DOUBLEVALUE: 799ffe3c632Sopenharmony_ci upb_handlers_setdouble(h, f, doublewrapper_handler, NULL); 800ffe3c632Sopenharmony_ci break; 801ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_FLOATVALUE: 802ffe3c632Sopenharmony_ci upb_handlers_setfloat(h, f, floatwrapper_handler, NULL); 803ffe3c632Sopenharmony_ci break; 804ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_INT64VALUE: 805ffe3c632Sopenharmony_ci upb_handlers_setint64(h, f, int64wrapper_handler, NULL); 806ffe3c632Sopenharmony_ci break; 807ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_UINT64VALUE: 808ffe3c632Sopenharmony_ci upb_handlers_setuint64(h, f, uint64wrapper_handler, NULL); 809ffe3c632Sopenharmony_ci break; 810ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_INT32VALUE: 811ffe3c632Sopenharmony_ci upb_handlers_setint32(h, f, int32wrapper_handler, NULL); 812ffe3c632Sopenharmony_ci break; 813ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_UINT32VALUE: 814ffe3c632Sopenharmony_ci upb_handlers_setuint32(h, f, uint32wrapper_handler, NULL); 815ffe3c632Sopenharmony_ci break; 816ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_STRINGVALUE: 817ffe3c632Sopenharmony_ci upb_handlers_setstartstr(h, f, startstringwrapper_handler, NULL); 818ffe3c632Sopenharmony_ci upb_handlers_setstring(h, f, stringwrapper_handler, NULL); 819ffe3c632Sopenharmony_ci break; 820ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_BYTESVALUE: 821ffe3c632Sopenharmony_ci upb_handlers_setstartstr(h, f, startbyteswrapper_handler, NULL); 822ffe3c632Sopenharmony_ci upb_handlers_setstring(h, f, byteswrapper_handler, NULL); 823ffe3c632Sopenharmony_ci break; 824ffe3c632Sopenharmony_ci case UPB_WELLKNOWN_BOOLVALUE: 825ffe3c632Sopenharmony_ci upb_handlers_setbool(h, f, boolwrapper_handler, NULL); 826ffe3c632Sopenharmony_ci return; 827ffe3c632Sopenharmony_ci default: 828ffe3c632Sopenharmony_ci rb_raise(rb_eRuntimeError, 829ffe3c632Sopenharmony_ci "Internal logic error with well-known types."); 830ffe3c632Sopenharmony_ci } 831ffe3c632Sopenharmony_ci} 832ffe3c632Sopenharmony_ci 833ffe3c632Sopenharmony_ci// Set up handlers for a oneof field. 834ffe3c632Sopenharmony_cistatic void add_handlers_for_oneof_field(upb_handlers *h, 835ffe3c632Sopenharmony_ci const upb_fielddef *f, 836ffe3c632Sopenharmony_ci size_t offset, 837ffe3c632Sopenharmony_ci size_t oneof_case_offset, 838ffe3c632Sopenharmony_ci const Descriptor* desc) { 839ffe3c632Sopenharmony_ci upb_handlerattr attr = UPB_HANDLERATTR_INIT; 840ffe3c632Sopenharmony_ci attr.handler_data = 841ffe3c632Sopenharmony_ci newoneofhandlerdata(h, offset, oneof_case_offset, f, desc); 842ffe3c632Sopenharmony_ci 843ffe3c632Sopenharmony_ci switch (upb_fielddef_type(f)) { 844ffe3c632Sopenharmony_ci 845ffe3c632Sopenharmony_ci#define SET_HANDLER(utype, ltype) \ 846ffe3c632Sopenharmony_ci case utype: \ 847ffe3c632Sopenharmony_ci upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \ 848ffe3c632Sopenharmony_ci break; 849ffe3c632Sopenharmony_ci 850ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_BOOL, bool); 851ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_INT32, int32); 852ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_UINT32, uint32); 853ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_ENUM, int32); 854ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_FLOAT, float); 855ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_INT64, int64); 856ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_UINT64, uint64); 857ffe3c632Sopenharmony_ci SET_HANDLER(UPB_TYPE_DOUBLE, double); 858ffe3c632Sopenharmony_ci 859ffe3c632Sopenharmony_ci#undef SET_HANDLER 860ffe3c632Sopenharmony_ci 861ffe3c632Sopenharmony_ci case UPB_TYPE_STRING: 862ffe3c632Sopenharmony_ci case UPB_TYPE_BYTES: { 863ffe3c632Sopenharmony_ci bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; 864ffe3c632Sopenharmony_ci upb_handlers_setstartstr(h, f, is_bytes ? 865ffe3c632Sopenharmony_ci oneofbytes_handler : oneofstr_handler, 866ffe3c632Sopenharmony_ci &attr); 867ffe3c632Sopenharmony_ci upb_handlers_setstring(h, f, stringdata_handler, NULL); 868ffe3c632Sopenharmony_ci upb_handlers_setendstr(h, f, oneofstring_end_handler, &attr); 869ffe3c632Sopenharmony_ci break; 870ffe3c632Sopenharmony_ci } 871ffe3c632Sopenharmony_ci case UPB_TYPE_MESSAGE: { 872ffe3c632Sopenharmony_ci if (is_wrapper(upb_fielddef_msgsubdef(f))) { 873ffe3c632Sopenharmony_ci upb_handlers_setstartsubmsg(h, f, oneof_startwrapper, &attr); 874ffe3c632Sopenharmony_ci } else { 875ffe3c632Sopenharmony_ci upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr); 876ffe3c632Sopenharmony_ci } 877ffe3c632Sopenharmony_ci break; 878ffe3c632Sopenharmony_ci } 879ffe3c632Sopenharmony_ci } 880ffe3c632Sopenharmony_ci} 881ffe3c632Sopenharmony_ci 882ffe3c632Sopenharmony_cistatic bool unknown_field_handler(void* closure, const void* hd, 883ffe3c632Sopenharmony_ci const char* buf, size_t size) { 884ffe3c632Sopenharmony_ci MessageHeader* msg = (MessageHeader*)closure; 885ffe3c632Sopenharmony_ci UPB_UNUSED(hd); 886ffe3c632Sopenharmony_ci 887ffe3c632Sopenharmony_ci if (msg->unknown_fields == NULL) { 888ffe3c632Sopenharmony_ci msg->unknown_fields = malloc(sizeof(stringsink)); 889ffe3c632Sopenharmony_ci stringsink_init(msg->unknown_fields); 890ffe3c632Sopenharmony_ci } 891ffe3c632Sopenharmony_ci 892ffe3c632Sopenharmony_ci stringsink_string(msg->unknown_fields, NULL, buf, size, NULL); 893ffe3c632Sopenharmony_ci 894ffe3c632Sopenharmony_ci return true; 895ffe3c632Sopenharmony_ci} 896ffe3c632Sopenharmony_ci 897ffe3c632Sopenharmony_cisize_t get_field_offset(MessageLayout* layout, const upb_fielddef* f) { 898ffe3c632Sopenharmony_ci return layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader); 899ffe3c632Sopenharmony_ci} 900ffe3c632Sopenharmony_ci 901ffe3c632Sopenharmony_civoid add_handlers_for_message(const void *closure, upb_handlers *h) { 902ffe3c632Sopenharmony_ci const VALUE descriptor_pool = (VALUE)closure; 903ffe3c632Sopenharmony_ci const upb_msgdef* msgdef = upb_handlers_msgdef(h); 904ffe3c632Sopenharmony_ci Descriptor* desc = 905ffe3c632Sopenharmony_ci ruby_to_Descriptor(get_msgdef_obj(descriptor_pool, msgdef)); 906ffe3c632Sopenharmony_ci upb_msg_field_iter i; 907ffe3c632Sopenharmony_ci upb_handlerattr attr = UPB_HANDLERATTR_INIT; 908ffe3c632Sopenharmony_ci 909ffe3c632Sopenharmony_ci // Ensure layout exists. We may be invoked to create handlers for a given 910ffe3c632Sopenharmony_ci // message if we are included as a submsg of another message type before our 911ffe3c632Sopenharmony_ci // class is actually built, so to work around this, we just create the layout 912ffe3c632Sopenharmony_ci // (and handlers, in the class-building function) on-demand. 913ffe3c632Sopenharmony_ci if (desc->layout == NULL) { 914ffe3c632Sopenharmony_ci create_layout(desc); 915ffe3c632Sopenharmony_ci } 916ffe3c632Sopenharmony_ci 917ffe3c632Sopenharmony_ci // If this is a mapentry message type, set up a special set of handlers and 918ffe3c632Sopenharmony_ci // bail out of the normal (user-defined) message type handling. 919ffe3c632Sopenharmony_ci if (upb_msgdef_mapentry(msgdef)) { 920ffe3c632Sopenharmony_ci add_handlers_for_mapentry(msgdef, h, desc); 921ffe3c632Sopenharmony_ci return; 922ffe3c632Sopenharmony_ci } 923ffe3c632Sopenharmony_ci 924ffe3c632Sopenharmony_ci // If this is a wrapper type, use special handlers and bail. 925ffe3c632Sopenharmony_ci if (is_wrapper(msgdef)) { 926ffe3c632Sopenharmony_ci add_handlers_for_wrapper(msgdef, h); 927ffe3c632Sopenharmony_ci return; 928ffe3c632Sopenharmony_ci } 929ffe3c632Sopenharmony_ci 930ffe3c632Sopenharmony_ci upb_handlers_setunknown(h, unknown_field_handler, &attr); 931ffe3c632Sopenharmony_ci 932ffe3c632Sopenharmony_ci for (upb_msg_field_begin(&i, desc->msgdef); 933ffe3c632Sopenharmony_ci !upb_msg_field_done(&i); 934ffe3c632Sopenharmony_ci upb_msg_field_next(&i)) { 935ffe3c632Sopenharmony_ci const upb_fielddef *f = upb_msg_iter_field(&i); 936ffe3c632Sopenharmony_ci const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f); 937ffe3c632Sopenharmony_ci size_t offset = get_field_offset(desc->layout, f); 938ffe3c632Sopenharmony_ci 939ffe3c632Sopenharmony_ci if (oneof) { 940ffe3c632Sopenharmony_ci size_t oneof_case_offset = 941ffe3c632Sopenharmony_ci desc->layout->oneofs[upb_oneofdef_index(oneof)].case_offset + 942ffe3c632Sopenharmony_ci sizeof(MessageHeader); 943ffe3c632Sopenharmony_ci add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc); 944ffe3c632Sopenharmony_ci } else if (is_map_field(f)) { 945ffe3c632Sopenharmony_ci add_handlers_for_mapfield(h, f, offset, desc); 946ffe3c632Sopenharmony_ci } else if (upb_fielddef_isseq(f)) { 947ffe3c632Sopenharmony_ci add_handlers_for_repeated_field(h, desc, f, offset); 948ffe3c632Sopenharmony_ci } else { 949ffe3c632Sopenharmony_ci add_handlers_for_singular_field( 950ffe3c632Sopenharmony_ci desc, h, f, offset, 951ffe3c632Sopenharmony_ci desc->layout->fields[upb_fielddef_index(f)].hasbit); 952ffe3c632Sopenharmony_ci } 953ffe3c632Sopenharmony_ci } 954ffe3c632Sopenharmony_ci} 955ffe3c632Sopenharmony_ci 956ffe3c632Sopenharmony_ci// Constructs the handlers for filling a message's data into an in-memory 957ffe3c632Sopenharmony_ci// object. 958ffe3c632Sopenharmony_ciconst upb_handlers* get_fill_handlers(Descriptor* desc) { 959ffe3c632Sopenharmony_ci DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 960ffe3c632Sopenharmony_ci return upb_handlercache_get(pool->fill_handler_cache, desc->msgdef); 961ffe3c632Sopenharmony_ci} 962ffe3c632Sopenharmony_ci 963ffe3c632Sopenharmony_cistatic const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) { 964ffe3c632Sopenharmony_ci DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 965ffe3c632Sopenharmony_ci return upb_pbcodecache_get(pool->fill_method_cache, desc->msgdef); 966ffe3c632Sopenharmony_ci} 967ffe3c632Sopenharmony_ci 968ffe3c632Sopenharmony_cistatic const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { 969ffe3c632Sopenharmony_ci DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 970ffe3c632Sopenharmony_ci return upb_json_codecache_get(pool->json_fill_method_cache, desc->msgdef); 971ffe3c632Sopenharmony_ci} 972ffe3c632Sopenharmony_ci 973ffe3c632Sopenharmony_cistatic const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { 974ffe3c632Sopenharmony_ci DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 975ffe3c632Sopenharmony_ci return upb_handlercache_get(pool->pb_serialize_handler_cache, desc->msgdef); 976ffe3c632Sopenharmony_ci} 977ffe3c632Sopenharmony_ci 978ffe3c632Sopenharmony_cistatic const upb_handlers* msgdef_json_serialize_handlers( 979ffe3c632Sopenharmony_ci Descriptor* desc, bool preserve_proto_fieldnames) { 980ffe3c632Sopenharmony_ci DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 981ffe3c632Sopenharmony_ci if (preserve_proto_fieldnames) { 982ffe3c632Sopenharmony_ci return upb_handlercache_get(pool->json_serialize_handler_preserve_cache, 983ffe3c632Sopenharmony_ci desc->msgdef); 984ffe3c632Sopenharmony_ci } else { 985ffe3c632Sopenharmony_ci return upb_handlercache_get(pool->json_serialize_handler_cache, 986ffe3c632Sopenharmony_ci desc->msgdef); 987ffe3c632Sopenharmony_ci } 988ffe3c632Sopenharmony_ci} 989ffe3c632Sopenharmony_ci 990ffe3c632Sopenharmony_ci 991ffe3c632Sopenharmony_ci// Stack-allocated context during an encode/decode operation. Contains the upb 992ffe3c632Sopenharmony_ci// environment and its stack-based allocator, an initial buffer for allocations 993ffe3c632Sopenharmony_ci// to avoid malloc() when possible, and a template for Ruby exception messages 994ffe3c632Sopenharmony_ci// if any error occurs. 995ffe3c632Sopenharmony_ci#define STACK_ENV_STACKBYTES 4096 996ffe3c632Sopenharmony_citypedef struct { 997ffe3c632Sopenharmony_ci upb_arena *arena; 998ffe3c632Sopenharmony_ci upb_status status; 999ffe3c632Sopenharmony_ci const char* ruby_error_template; 1000ffe3c632Sopenharmony_ci char allocbuf[STACK_ENV_STACKBYTES]; 1001ffe3c632Sopenharmony_ci} stackenv; 1002ffe3c632Sopenharmony_ci 1003ffe3c632Sopenharmony_cistatic void stackenv_init(stackenv* se, const char* errmsg); 1004ffe3c632Sopenharmony_cistatic void stackenv_uninit(stackenv* se); 1005ffe3c632Sopenharmony_ci 1006ffe3c632Sopenharmony_cistatic void stackenv_init(stackenv* se, const char* errmsg) { 1007ffe3c632Sopenharmony_ci se->ruby_error_template = errmsg; 1008ffe3c632Sopenharmony_ci se->arena = 1009ffe3c632Sopenharmony_ci upb_arena_init(se->allocbuf, sizeof(se->allocbuf), &upb_alloc_global); 1010ffe3c632Sopenharmony_ci upb_status_clear(&se->status); 1011ffe3c632Sopenharmony_ci} 1012ffe3c632Sopenharmony_ci 1013ffe3c632Sopenharmony_cistatic void stackenv_uninit(stackenv* se) { 1014ffe3c632Sopenharmony_ci upb_arena_free(se->arena); 1015ffe3c632Sopenharmony_ci 1016ffe3c632Sopenharmony_ci if (!upb_ok(&se->status)) { 1017ffe3c632Sopenharmony_ci // TODO(haberman): have a way to verify that this is actually a parse error, 1018ffe3c632Sopenharmony_ci // instead of just throwing "parse error" unconditionally. 1019ffe3c632Sopenharmony_ci VALUE errmsg = rb_str_new2(upb_status_errmsg(&se->status)); 1020ffe3c632Sopenharmony_ci rb_raise(cParseError, se->ruby_error_template, errmsg); 1021ffe3c632Sopenharmony_ci } 1022ffe3c632Sopenharmony_ci} 1023ffe3c632Sopenharmony_ci 1024ffe3c632Sopenharmony_ci/* 1025ffe3c632Sopenharmony_ci * call-seq: 1026ffe3c632Sopenharmony_ci * MessageClass.decode(data) => message 1027ffe3c632Sopenharmony_ci * 1028ffe3c632Sopenharmony_ci * Decodes the given data (as a string containing bytes in protocol buffers wire 1029ffe3c632Sopenharmony_ci * format) under the interpretration given by this message class's definition 1030ffe3c632Sopenharmony_ci * and returns a message object with the corresponding field values. 1031ffe3c632Sopenharmony_ci */ 1032ffe3c632Sopenharmony_ciVALUE Message_decode(VALUE klass, VALUE data) { 1033ffe3c632Sopenharmony_ci VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1034ffe3c632Sopenharmony_ci Descriptor* desc = ruby_to_Descriptor(descriptor); 1035ffe3c632Sopenharmony_ci VALUE msgklass = Descriptor_msgclass(descriptor); 1036ffe3c632Sopenharmony_ci VALUE msg_rb; 1037ffe3c632Sopenharmony_ci MessageHeader* msg; 1038ffe3c632Sopenharmony_ci 1039ffe3c632Sopenharmony_ci if (TYPE(data) != T_STRING) { 1040ffe3c632Sopenharmony_ci rb_raise(rb_eArgError, "Expected string for binary protobuf data."); 1041ffe3c632Sopenharmony_ci } 1042ffe3c632Sopenharmony_ci 1043ffe3c632Sopenharmony_ci msg_rb = initialize_rb_class_with_no_args(msgklass); 1044ffe3c632Sopenharmony_ci TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1045ffe3c632Sopenharmony_ci 1046ffe3c632Sopenharmony_ci { 1047ffe3c632Sopenharmony_ci const upb_pbdecodermethod* method = msgdef_decodermethod(desc); 1048ffe3c632Sopenharmony_ci const upb_handlers* h = upb_pbdecodermethod_desthandlers(method); 1049ffe3c632Sopenharmony_ci const upb_msgdef* m = upb_handlers_msgdef(h); 1050ffe3c632Sopenharmony_ci VALUE wrapper = Qnil; 1051ffe3c632Sopenharmony_ci void* ptr = msg; 1052ffe3c632Sopenharmony_ci stackenv se; 1053ffe3c632Sopenharmony_ci upb_sink sink; 1054ffe3c632Sopenharmony_ci upb_pbdecoder* decoder; 1055ffe3c632Sopenharmony_ci stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE); 1056ffe3c632Sopenharmony_ci 1057ffe3c632Sopenharmony_ci if (is_wrapper(m)) { 1058ffe3c632Sopenharmony_ci ptr = &wrapper; 1059ffe3c632Sopenharmony_ci } 1060ffe3c632Sopenharmony_ci 1061ffe3c632Sopenharmony_ci upb_sink_reset(&sink, h, ptr); 1062ffe3c632Sopenharmony_ci decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status); 1063ffe3c632Sopenharmony_ci upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), 1064ffe3c632Sopenharmony_ci upb_pbdecoder_input(decoder)); 1065ffe3c632Sopenharmony_ci 1066ffe3c632Sopenharmony_ci stackenv_uninit(&se); 1067ffe3c632Sopenharmony_ci 1068ffe3c632Sopenharmony_ci if (is_wrapper(m)) { 1069ffe3c632Sopenharmony_ci msg_rb = ruby_wrapper_type(msgklass, wrapper); 1070ffe3c632Sopenharmony_ci } 1071ffe3c632Sopenharmony_ci } 1072ffe3c632Sopenharmony_ci 1073ffe3c632Sopenharmony_ci return msg_rb; 1074ffe3c632Sopenharmony_ci} 1075ffe3c632Sopenharmony_ci 1076ffe3c632Sopenharmony_ci/* 1077ffe3c632Sopenharmony_ci * call-seq: 1078ffe3c632Sopenharmony_ci * MessageClass.decode_json(data, options = {}) => message 1079ffe3c632Sopenharmony_ci * 1080ffe3c632Sopenharmony_ci * Decodes the given data (as a string containing bytes in protocol buffers wire 1081ffe3c632Sopenharmony_ci * format) under the interpretration given by this message class's definition 1082ffe3c632Sopenharmony_ci * and returns a message object with the corresponding field values. 1083ffe3c632Sopenharmony_ci * 1084ffe3c632Sopenharmony_ci * @param options [Hash] options for the decoder 1085ffe3c632Sopenharmony_ci * ignore_unknown_fields: set true to ignore unknown fields (default is to 1086ffe3c632Sopenharmony_ci * raise an error) 1087ffe3c632Sopenharmony_ci */ 1088ffe3c632Sopenharmony_ciVALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) { 1089ffe3c632Sopenharmony_ci VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1090ffe3c632Sopenharmony_ci Descriptor* desc = ruby_to_Descriptor(descriptor); 1091ffe3c632Sopenharmony_ci VALUE msgklass = Descriptor_msgclass(descriptor); 1092ffe3c632Sopenharmony_ci VALUE msg_rb; 1093ffe3c632Sopenharmony_ci VALUE data = argv[0]; 1094ffe3c632Sopenharmony_ci VALUE ignore_unknown_fields = Qfalse; 1095ffe3c632Sopenharmony_ci MessageHeader* msg; 1096ffe3c632Sopenharmony_ci 1097ffe3c632Sopenharmony_ci if (argc < 1 || argc > 2) { 1098ffe3c632Sopenharmony_ci rb_raise(rb_eArgError, "Expected 1 or 2 arguments."); 1099ffe3c632Sopenharmony_ci } 1100ffe3c632Sopenharmony_ci 1101ffe3c632Sopenharmony_ci if (argc == 2) { 1102ffe3c632Sopenharmony_ci VALUE hash_args = argv[1]; 1103ffe3c632Sopenharmony_ci if (TYPE(hash_args) != T_HASH) { 1104ffe3c632Sopenharmony_ci rb_raise(rb_eArgError, "Expected hash arguments."); 1105ffe3c632Sopenharmony_ci } 1106ffe3c632Sopenharmony_ci 1107ffe3c632Sopenharmony_ci ignore_unknown_fields = rb_hash_lookup2( 1108ffe3c632Sopenharmony_ci hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse); 1109ffe3c632Sopenharmony_ci } 1110ffe3c632Sopenharmony_ci 1111ffe3c632Sopenharmony_ci if (TYPE(data) != T_STRING) { 1112ffe3c632Sopenharmony_ci rb_raise(rb_eArgError, "Expected string for JSON data."); 1113ffe3c632Sopenharmony_ci } 1114ffe3c632Sopenharmony_ci 1115ffe3c632Sopenharmony_ci // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to 1116ffe3c632Sopenharmony_ci // convert, because string handlers pass data directly to message string 1117ffe3c632Sopenharmony_ci // fields. 1118ffe3c632Sopenharmony_ci 1119ffe3c632Sopenharmony_ci msg_rb = initialize_rb_class_with_no_args(msgklass); 1120ffe3c632Sopenharmony_ci TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1121ffe3c632Sopenharmony_ci 1122ffe3c632Sopenharmony_ci { 1123ffe3c632Sopenharmony_ci const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc); 1124ffe3c632Sopenharmony_ci const upb_handlers* h = get_fill_handlers(desc); 1125ffe3c632Sopenharmony_ci const upb_msgdef* m = upb_handlers_msgdef(h); 1126ffe3c632Sopenharmony_ci stackenv se; 1127ffe3c632Sopenharmony_ci upb_sink sink; 1128ffe3c632Sopenharmony_ci upb_json_parser* parser; 1129ffe3c632Sopenharmony_ci DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool); 1130ffe3c632Sopenharmony_ci stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE); 1131ffe3c632Sopenharmony_ci 1132ffe3c632Sopenharmony_ci if (is_wrapper(m)) { 1133ffe3c632Sopenharmony_ci rb_raise( 1134ffe3c632Sopenharmony_ci rb_eRuntimeError, 1135ffe3c632Sopenharmony_ci "Parsing a wrapper type from JSON at the top level does not work."); 1136ffe3c632Sopenharmony_ci } 1137ffe3c632Sopenharmony_ci 1138ffe3c632Sopenharmony_ci upb_sink_reset(&sink, h, msg); 1139ffe3c632Sopenharmony_ci parser = upb_json_parser_create(se.arena, method, pool->symtab, sink, 1140ffe3c632Sopenharmony_ci &se.status, RTEST(ignore_unknown_fields)); 1141ffe3c632Sopenharmony_ci upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), 1142ffe3c632Sopenharmony_ci upb_json_parser_input(parser)); 1143ffe3c632Sopenharmony_ci 1144ffe3c632Sopenharmony_ci stackenv_uninit(&se); 1145ffe3c632Sopenharmony_ci } 1146ffe3c632Sopenharmony_ci 1147ffe3c632Sopenharmony_ci return msg_rb; 1148ffe3c632Sopenharmony_ci} 1149ffe3c632Sopenharmony_ci 1150ffe3c632Sopenharmony_ci// ----------------------------------------------------------------------------- 1151ffe3c632Sopenharmony_ci// Serializing. 1152ffe3c632Sopenharmony_ci// ----------------------------------------------------------------------------- 1153ffe3c632Sopenharmony_ci 1154ffe3c632Sopenharmony_ci/* msgvisitor *****************************************************************/ 1155ffe3c632Sopenharmony_ci 1156ffe3c632Sopenharmony_cistatic void putmsg(VALUE msg, const Descriptor* desc, upb_sink sink, int depth, 1157ffe3c632Sopenharmony_ci bool emit_defaults, bool is_json, bool open_msg); 1158ffe3c632Sopenharmony_ci 1159ffe3c632Sopenharmony_cistatic upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { 1160ffe3c632Sopenharmony_ci upb_selector_t ret; 1161ffe3c632Sopenharmony_ci bool ok = upb_handlers_getselector(f, type, &ret); 1162ffe3c632Sopenharmony_ci UPB_ASSERT(ok); 1163ffe3c632Sopenharmony_ci return ret; 1164ffe3c632Sopenharmony_ci} 1165ffe3c632Sopenharmony_ci 1166ffe3c632Sopenharmony_cistatic void putstr(VALUE str, const upb_fielddef *f, upb_sink sink) { 1167ffe3c632Sopenharmony_ci upb_sink subsink; 1168ffe3c632Sopenharmony_ci 1169ffe3c632Sopenharmony_ci if (str == Qnil) return; 1170ffe3c632Sopenharmony_ci 1171ffe3c632Sopenharmony_ci assert(BUILTIN_TYPE(str) == RUBY_T_STRING); 1172ffe3c632Sopenharmony_ci 1173ffe3c632Sopenharmony_ci // We should be guaranteed that the string has the correct encoding because 1174ffe3c632Sopenharmony_ci // we ensured this at assignment time and then froze the string. 1175ffe3c632Sopenharmony_ci if (upb_fielddef_type(f) == UPB_TYPE_STRING) { 1176ffe3c632Sopenharmony_ci assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyStringUtf8Encoding); 1177ffe3c632Sopenharmony_ci } else { 1178ffe3c632Sopenharmony_ci assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyString8bitEncoding); 1179ffe3c632Sopenharmony_ci } 1180ffe3c632Sopenharmony_ci 1181ffe3c632Sopenharmony_ci upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str), 1182ffe3c632Sopenharmony_ci &subsink); 1183ffe3c632Sopenharmony_ci upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str), 1184ffe3c632Sopenharmony_ci RSTRING_LEN(str), NULL); 1185ffe3c632Sopenharmony_ci upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR)); 1186ffe3c632Sopenharmony_ci} 1187ffe3c632Sopenharmony_ci 1188ffe3c632Sopenharmony_cistatic void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink, 1189ffe3c632Sopenharmony_ci int depth, bool emit_defaults, bool is_json) { 1190ffe3c632Sopenharmony_ci upb_sink subsink; 1191ffe3c632Sopenharmony_ci VALUE descriptor; 1192ffe3c632Sopenharmony_ci Descriptor* subdesc; 1193ffe3c632Sopenharmony_ci 1194ffe3c632Sopenharmony_ci if (submsg == Qnil) return; 1195ffe3c632Sopenharmony_ci 1196ffe3c632Sopenharmony_ci descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 1197ffe3c632Sopenharmony_ci subdesc = ruby_to_Descriptor(descriptor); 1198ffe3c632Sopenharmony_ci 1199ffe3c632Sopenharmony_ci upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink); 1200ffe3c632Sopenharmony_ci putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true); 1201ffe3c632Sopenharmony_ci upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); 1202ffe3c632Sopenharmony_ci} 1203ffe3c632Sopenharmony_ci 1204ffe3c632Sopenharmony_cistatic void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth, 1205ffe3c632Sopenharmony_ci bool emit_defaults, bool is_json) { 1206ffe3c632Sopenharmony_ci upb_sink subsink; 1207ffe3c632Sopenharmony_ci upb_fieldtype_t type = upb_fielddef_type(f); 1208ffe3c632Sopenharmony_ci upb_selector_t sel = 0; 1209ffe3c632Sopenharmony_ci int size; 1210ffe3c632Sopenharmony_ci int i; 1211ffe3c632Sopenharmony_ci VALUE type_class = ruby_to_RepeatedField(ary)->field_type_class; 1212ffe3c632Sopenharmony_ci 1213ffe3c632Sopenharmony_ci if (ary == Qnil) return; 1214ffe3c632Sopenharmony_ci if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return; 1215ffe3c632Sopenharmony_ci 1216ffe3c632Sopenharmony_ci size = NUM2INT(RepeatedField_length(ary)); 1217ffe3c632Sopenharmony_ci if (size == 0 && !emit_defaults) return; 1218ffe3c632Sopenharmony_ci 1219ffe3c632Sopenharmony_ci upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); 1220ffe3c632Sopenharmony_ci 1221ffe3c632Sopenharmony_ci if (upb_fielddef_isprimitive(f)) { 1222ffe3c632Sopenharmony_ci sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); 1223ffe3c632Sopenharmony_ci } 1224ffe3c632Sopenharmony_ci 1225ffe3c632Sopenharmony_ci for (i = 0; i < size; i++) { 1226ffe3c632Sopenharmony_ci void* memory = RepeatedField_index_native(ary, i); 1227ffe3c632Sopenharmony_ci switch (type) { 1228ffe3c632Sopenharmony_ci#define T(upbtypeconst, upbtype, ctype) \ 1229ffe3c632Sopenharmony_ci case upbtypeconst: \ 1230ffe3c632Sopenharmony_ci upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \ 1231ffe3c632Sopenharmony_ci break; 1232ffe3c632Sopenharmony_ci 1233ffe3c632Sopenharmony_ci T(UPB_TYPE_FLOAT, float, float) 1234ffe3c632Sopenharmony_ci T(UPB_TYPE_DOUBLE, double, double) 1235ffe3c632Sopenharmony_ci T(UPB_TYPE_BOOL, bool, int8_t) 1236ffe3c632Sopenharmony_ci case UPB_TYPE_ENUM: 1237ffe3c632Sopenharmony_ci T(UPB_TYPE_INT32, int32, int32_t) 1238ffe3c632Sopenharmony_ci T(UPB_TYPE_UINT32, uint32, uint32_t) 1239ffe3c632Sopenharmony_ci T(UPB_TYPE_INT64, int64, int64_t) 1240ffe3c632Sopenharmony_ci T(UPB_TYPE_UINT64, uint64, uint64_t) 1241ffe3c632Sopenharmony_ci 1242ffe3c632Sopenharmony_ci case UPB_TYPE_STRING: 1243ffe3c632Sopenharmony_ci case UPB_TYPE_BYTES: 1244ffe3c632Sopenharmony_ci putstr(*((VALUE *)memory), f, subsink); 1245ffe3c632Sopenharmony_ci break; 1246ffe3c632Sopenharmony_ci case UPB_TYPE_MESSAGE: { 1247ffe3c632Sopenharmony_ci VALUE val = native_slot_get(UPB_TYPE_MESSAGE, type_class, memory); 1248ffe3c632Sopenharmony_ci putsubmsg(val, f, subsink, depth, emit_defaults, is_json); 1249ffe3c632Sopenharmony_ci break; 1250ffe3c632Sopenharmony_ci } 1251ffe3c632Sopenharmony_ci 1252ffe3c632Sopenharmony_ci#undef T 1253ffe3c632Sopenharmony_ci 1254ffe3c632Sopenharmony_ci } 1255ffe3c632Sopenharmony_ci } 1256ffe3c632Sopenharmony_ci upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); 1257ffe3c632Sopenharmony_ci} 1258ffe3c632Sopenharmony_ci 1259ffe3c632Sopenharmony_cistatic void put_ruby_value(VALUE value, const upb_fielddef* f, VALUE type_class, 1260ffe3c632Sopenharmony_ci int depth, upb_sink sink, bool emit_defaults, 1261ffe3c632Sopenharmony_ci bool is_json) { 1262ffe3c632Sopenharmony_ci upb_selector_t sel = 0; 1263ffe3c632Sopenharmony_ci 1264ffe3c632Sopenharmony_ci if (depth > ENCODE_MAX_NESTING) { 1265ffe3c632Sopenharmony_ci rb_raise(rb_eRuntimeError, 1266ffe3c632Sopenharmony_ci "Maximum recursion depth exceeded during encoding."); 1267ffe3c632Sopenharmony_ci } 1268ffe3c632Sopenharmony_ci 1269ffe3c632Sopenharmony_ci if (upb_fielddef_isprimitive(f)) { 1270ffe3c632Sopenharmony_ci sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); 1271ffe3c632Sopenharmony_ci } 1272ffe3c632Sopenharmony_ci 1273ffe3c632Sopenharmony_ci switch (upb_fielddef_type(f)) { 1274ffe3c632Sopenharmony_ci case UPB_TYPE_INT32: 1275ffe3c632Sopenharmony_ci upb_sink_putint32(sink, sel, NUM2INT(value)); 1276ffe3c632Sopenharmony_ci break; 1277ffe3c632Sopenharmony_ci case UPB_TYPE_INT64: 1278ffe3c632Sopenharmony_ci upb_sink_putint64(sink, sel, NUM2LL(value)); 1279ffe3c632Sopenharmony_ci break; 1280ffe3c632Sopenharmony_ci case UPB_TYPE_UINT32: 1281ffe3c632Sopenharmony_ci upb_sink_putuint32(sink, sel, NUM2UINT(value)); 1282ffe3c632Sopenharmony_ci break; 1283ffe3c632Sopenharmony_ci case UPB_TYPE_UINT64: 1284ffe3c632Sopenharmony_ci upb_sink_putuint64(sink, sel, NUM2ULL(value)); 1285ffe3c632Sopenharmony_ci break; 1286ffe3c632Sopenharmony_ci case UPB_TYPE_FLOAT: 1287ffe3c632Sopenharmony_ci upb_sink_putfloat(sink, sel, NUM2DBL(value)); 1288ffe3c632Sopenharmony_ci break; 1289ffe3c632Sopenharmony_ci case UPB_TYPE_DOUBLE: 1290ffe3c632Sopenharmony_ci upb_sink_putdouble(sink, sel, NUM2DBL(value)); 1291ffe3c632Sopenharmony_ci break; 1292ffe3c632Sopenharmony_ci case UPB_TYPE_ENUM: { 1293ffe3c632Sopenharmony_ci if (TYPE(value) == T_SYMBOL) { 1294ffe3c632Sopenharmony_ci value = rb_funcall(type_class, rb_intern("resolve"), 1, value); 1295ffe3c632Sopenharmony_ci } 1296ffe3c632Sopenharmony_ci upb_sink_putint32(sink, sel, NUM2INT(value)); 1297ffe3c632Sopenharmony_ci break; 1298ffe3c632Sopenharmony_ci } 1299ffe3c632Sopenharmony_ci case UPB_TYPE_BOOL: 1300ffe3c632Sopenharmony_ci upb_sink_putbool(sink, sel, value == Qtrue); 1301ffe3c632Sopenharmony_ci break; 1302ffe3c632Sopenharmony_ci case UPB_TYPE_STRING: 1303ffe3c632Sopenharmony_ci case UPB_TYPE_BYTES: 1304ffe3c632Sopenharmony_ci putstr(value, f, sink); 1305ffe3c632Sopenharmony_ci break; 1306ffe3c632Sopenharmony_ci case UPB_TYPE_MESSAGE: 1307ffe3c632Sopenharmony_ci putsubmsg(value, f, sink, depth, emit_defaults, is_json); 1308ffe3c632Sopenharmony_ci } 1309ffe3c632Sopenharmony_ci} 1310ffe3c632Sopenharmony_ci 1311ffe3c632Sopenharmony_cistatic void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth, 1312ffe3c632Sopenharmony_ci bool emit_defaults, bool is_json) { 1313ffe3c632Sopenharmony_ci Map* self; 1314ffe3c632Sopenharmony_ci upb_sink subsink; 1315ffe3c632Sopenharmony_ci const upb_fielddef* key_field; 1316ffe3c632Sopenharmony_ci const upb_fielddef* value_field; 1317ffe3c632Sopenharmony_ci Map_iter it; 1318ffe3c632Sopenharmony_ci 1319ffe3c632Sopenharmony_ci if (map == Qnil) return; 1320ffe3c632Sopenharmony_ci if (!emit_defaults && Map_length(map) == 0) return; 1321ffe3c632Sopenharmony_ci 1322ffe3c632Sopenharmony_ci self = ruby_to_Map(map); 1323ffe3c632Sopenharmony_ci 1324ffe3c632Sopenharmony_ci upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); 1325ffe3c632Sopenharmony_ci 1326ffe3c632Sopenharmony_ci assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE); 1327ffe3c632Sopenharmony_ci key_field = map_field_key(f); 1328ffe3c632Sopenharmony_ci value_field = map_field_value(f); 1329ffe3c632Sopenharmony_ci 1330ffe3c632Sopenharmony_ci for (Map_begin(map, &it); !Map_done(&it); Map_next(&it)) { 1331ffe3c632Sopenharmony_ci VALUE key = Map_iter_key(&it); 1332ffe3c632Sopenharmony_ci VALUE value = Map_iter_value(&it); 1333ffe3c632Sopenharmony_ci upb_status status; 1334ffe3c632Sopenharmony_ci 1335ffe3c632Sopenharmony_ci upb_sink entry_sink; 1336ffe3c632Sopenharmony_ci upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG), 1337ffe3c632Sopenharmony_ci &entry_sink); 1338ffe3c632Sopenharmony_ci upb_sink_startmsg(entry_sink); 1339ffe3c632Sopenharmony_ci 1340ffe3c632Sopenharmony_ci put_ruby_value(key, key_field, Qnil, depth + 1, entry_sink, emit_defaults, 1341ffe3c632Sopenharmony_ci is_json); 1342ffe3c632Sopenharmony_ci put_ruby_value(value, value_field, self->value_type_class, depth + 1, 1343ffe3c632Sopenharmony_ci entry_sink, emit_defaults, is_json); 1344ffe3c632Sopenharmony_ci 1345ffe3c632Sopenharmony_ci upb_sink_endmsg(entry_sink, &status); 1346ffe3c632Sopenharmony_ci upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG)); 1347ffe3c632Sopenharmony_ci } 1348ffe3c632Sopenharmony_ci 1349ffe3c632Sopenharmony_ci upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); 1350ffe3c632Sopenharmony_ci} 1351ffe3c632Sopenharmony_ci 1352ffe3c632Sopenharmony_cistatic const upb_handlers* msgdef_json_serialize_handlers( 1353ffe3c632Sopenharmony_ci Descriptor* desc, bool preserve_proto_fieldnames); 1354ffe3c632Sopenharmony_ci 1355ffe3c632Sopenharmony_cistatic void putjsonany(VALUE msg_rb, const Descriptor* desc, upb_sink sink, 1356ffe3c632Sopenharmony_ci int depth, bool emit_defaults) { 1357ffe3c632Sopenharmony_ci upb_status status; 1358ffe3c632Sopenharmony_ci MessageHeader* msg = NULL; 1359ffe3c632Sopenharmony_ci const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE); 1360ffe3c632Sopenharmony_ci const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE); 1361ffe3c632Sopenharmony_ci 1362ffe3c632Sopenharmony_ci size_t type_url_offset; 1363ffe3c632Sopenharmony_ci VALUE type_url_str_rb; 1364ffe3c632Sopenharmony_ci const upb_msgdef *payload_type = NULL; 1365ffe3c632Sopenharmony_ci 1366ffe3c632Sopenharmony_ci TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1367ffe3c632Sopenharmony_ci 1368ffe3c632Sopenharmony_ci upb_sink_startmsg(sink); 1369ffe3c632Sopenharmony_ci 1370ffe3c632Sopenharmony_ci /* Handle type url */ 1371ffe3c632Sopenharmony_ci type_url_offset = desc->layout->fields[upb_fielddef_index(type_field)].offset; 1372ffe3c632Sopenharmony_ci type_url_str_rb = DEREF(Message_data(msg), type_url_offset, VALUE); 1373ffe3c632Sopenharmony_ci if (RSTRING_LEN(type_url_str_rb) > 0) { 1374ffe3c632Sopenharmony_ci putstr(type_url_str_rb, type_field, sink); 1375ffe3c632Sopenharmony_ci } 1376ffe3c632Sopenharmony_ci 1377ffe3c632Sopenharmony_ci { 1378ffe3c632Sopenharmony_ci const char* type_url_str = RSTRING_PTR(type_url_str_rb); 1379ffe3c632Sopenharmony_ci size_t type_url_len = RSTRING_LEN(type_url_str_rb); 1380ffe3c632Sopenharmony_ci DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool); 1381ffe3c632Sopenharmony_ci 1382ffe3c632Sopenharmony_ci if (type_url_len <= 20 || 1383ffe3c632Sopenharmony_ci strncmp(type_url_str, "type.googleapis.com/", 20) != 0) { 1384ffe3c632Sopenharmony_ci rb_raise(rb_eRuntimeError, "Invalid type url: %s", type_url_str); 1385ffe3c632Sopenharmony_ci return; 1386ffe3c632Sopenharmony_ci } 1387ffe3c632Sopenharmony_ci 1388ffe3c632Sopenharmony_ci /* Resolve type url */ 1389ffe3c632Sopenharmony_ci type_url_str += 20; 1390ffe3c632Sopenharmony_ci type_url_len -= 20; 1391ffe3c632Sopenharmony_ci 1392ffe3c632Sopenharmony_ci payload_type = upb_symtab_lookupmsg2( 1393ffe3c632Sopenharmony_ci pool->symtab, type_url_str, type_url_len); 1394ffe3c632Sopenharmony_ci if (payload_type == NULL) { 1395ffe3c632Sopenharmony_ci rb_raise(rb_eRuntimeError, "Unknown type: %s", type_url_str); 1396ffe3c632Sopenharmony_ci return; 1397ffe3c632Sopenharmony_ci } 1398ffe3c632Sopenharmony_ci } 1399ffe3c632Sopenharmony_ci 1400ffe3c632Sopenharmony_ci { 1401ffe3c632Sopenharmony_ci uint32_t value_offset; 1402ffe3c632Sopenharmony_ci VALUE value_str_rb; 1403ffe3c632Sopenharmony_ci size_t value_len; 1404ffe3c632Sopenharmony_ci 1405ffe3c632Sopenharmony_ci value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset; 1406ffe3c632Sopenharmony_ci value_str_rb = DEREF(Message_data(msg), value_offset, VALUE); 1407ffe3c632Sopenharmony_ci value_len = RSTRING_LEN(value_str_rb); 1408ffe3c632Sopenharmony_ci 1409ffe3c632Sopenharmony_ci if (value_len > 0) { 1410ffe3c632Sopenharmony_ci VALUE payload_desc_rb = get_msgdef_obj(generated_pool, payload_type); 1411ffe3c632Sopenharmony_ci Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb); 1412ffe3c632Sopenharmony_ci VALUE payload_class = Descriptor_msgclass(payload_desc_rb); 1413ffe3c632Sopenharmony_ci upb_sink subsink; 1414ffe3c632Sopenharmony_ci bool is_wellknown; 1415ffe3c632Sopenharmony_ci 1416ffe3c632Sopenharmony_ci VALUE payload_msg_rb = Message_decode(payload_class, value_str_rb); 1417ffe3c632Sopenharmony_ci 1418ffe3c632Sopenharmony_ci is_wellknown = 1419ffe3c632Sopenharmony_ci upb_msgdef_wellknowntype(payload_desc->msgdef) != 1420ffe3c632Sopenharmony_ci UPB_WELLKNOWN_UNSPECIFIED; 1421ffe3c632Sopenharmony_ci if (is_wellknown) { 1422ffe3c632Sopenharmony_ci upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0, 1423ffe3c632Sopenharmony_ci &subsink); 1424ffe3c632Sopenharmony_ci } 1425ffe3c632Sopenharmony_ci 1426ffe3c632Sopenharmony_ci subsink.handlers = 1427ffe3c632Sopenharmony_ci msgdef_json_serialize_handlers(payload_desc, true); 1428ffe3c632Sopenharmony_ci subsink.closure = sink.closure; 1429ffe3c632Sopenharmony_ci putmsg(payload_msg_rb, payload_desc, subsink, depth, emit_defaults, true, 1430ffe3c632Sopenharmony_ci is_wellknown); 1431ffe3c632Sopenharmony_ci } 1432ffe3c632Sopenharmony_ci } 1433ffe3c632Sopenharmony_ci 1434ffe3c632Sopenharmony_ci upb_sink_endmsg(sink, &status); 1435ffe3c632Sopenharmony_ci} 1436ffe3c632Sopenharmony_ci 1437ffe3c632Sopenharmony_cistatic void putjsonlistvalue( 1438ffe3c632Sopenharmony_ci VALUE msg_rb, const Descriptor* desc, 1439ffe3c632Sopenharmony_ci upb_sink sink, int depth, bool emit_defaults) { 1440ffe3c632Sopenharmony_ci upb_status status; 1441ffe3c632Sopenharmony_ci upb_sink subsink; 1442ffe3c632Sopenharmony_ci MessageHeader* msg = NULL; 1443ffe3c632Sopenharmony_ci const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1); 1444ffe3c632Sopenharmony_ci uint32_t offset = 1445ffe3c632Sopenharmony_ci desc->layout->fields[upb_fielddef_index(f)].offset + 1446ffe3c632Sopenharmony_ci sizeof(MessageHeader); 1447ffe3c632Sopenharmony_ci VALUE ary; 1448ffe3c632Sopenharmony_ci 1449ffe3c632Sopenharmony_ci TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1450ffe3c632Sopenharmony_ci 1451ffe3c632Sopenharmony_ci upb_sink_startmsg(sink); 1452ffe3c632Sopenharmony_ci 1453ffe3c632Sopenharmony_ci ary = DEREF(msg, offset, VALUE); 1454ffe3c632Sopenharmony_ci 1455ffe3c632Sopenharmony_ci if (ary == Qnil || RepeatedField_size(ary) == 0) { 1456ffe3c632Sopenharmony_ci upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); 1457ffe3c632Sopenharmony_ci upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); 1458ffe3c632Sopenharmony_ci } else { 1459ffe3c632Sopenharmony_ci putary(ary, f, sink, depth, emit_defaults, true); 1460ffe3c632Sopenharmony_ci } 1461ffe3c632Sopenharmony_ci 1462ffe3c632Sopenharmony_ci upb_sink_endmsg(sink, &status); 1463ffe3c632Sopenharmony_ci} 1464ffe3c632Sopenharmony_ci 1465ffe3c632Sopenharmony_cistatic void putmsg(VALUE msg_rb, const Descriptor* desc, 1466ffe3c632Sopenharmony_ci upb_sink sink, int depth, bool emit_defaults, 1467ffe3c632Sopenharmony_ci bool is_json, bool open_msg) { 1468ffe3c632Sopenharmony_ci MessageHeader* msg; 1469ffe3c632Sopenharmony_ci upb_msg_field_iter i; 1470ffe3c632Sopenharmony_ci upb_status status; 1471ffe3c632Sopenharmony_ci bool json_wrapper = is_wrapper(desc->msgdef) && is_json; 1472ffe3c632Sopenharmony_ci 1473ffe3c632Sopenharmony_ci if (is_json && 1474ffe3c632Sopenharmony_ci upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) { 1475ffe3c632Sopenharmony_ci putjsonany(msg_rb, desc, sink, depth, emit_defaults); 1476ffe3c632Sopenharmony_ci return; 1477ffe3c632Sopenharmony_ci } 1478ffe3c632Sopenharmony_ci 1479ffe3c632Sopenharmony_ci if (is_json && 1480ffe3c632Sopenharmony_ci upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) { 1481ffe3c632Sopenharmony_ci putjsonlistvalue(msg_rb, desc, sink, depth, emit_defaults); 1482ffe3c632Sopenharmony_ci return; 1483ffe3c632Sopenharmony_ci } 1484ffe3c632Sopenharmony_ci 1485ffe3c632Sopenharmony_ci if (open_msg) { 1486ffe3c632Sopenharmony_ci upb_sink_startmsg(sink); 1487ffe3c632Sopenharmony_ci } 1488ffe3c632Sopenharmony_ci 1489ffe3c632Sopenharmony_ci // Protect against cycles (possible because users may freely reassign message 1490ffe3c632Sopenharmony_ci // and repeated fields) by imposing a maximum recursion depth. 1491ffe3c632Sopenharmony_ci if (depth > ENCODE_MAX_NESTING) { 1492ffe3c632Sopenharmony_ci rb_raise(rb_eRuntimeError, 1493ffe3c632Sopenharmony_ci "Maximum recursion depth exceeded during encoding."); 1494ffe3c632Sopenharmony_ci } 1495ffe3c632Sopenharmony_ci 1496ffe3c632Sopenharmony_ci TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1497ffe3c632Sopenharmony_ci 1498ffe3c632Sopenharmony_ci if (desc != msg->descriptor) { 1499ffe3c632Sopenharmony_ci rb_raise(rb_eArgError, 1500ffe3c632Sopenharmony_ci "The type of given msg is '%s', expect '%s'.", 1501ffe3c632Sopenharmony_ci upb_msgdef_fullname(msg->descriptor->msgdef), 1502ffe3c632Sopenharmony_ci upb_msgdef_fullname(desc->msgdef)); 1503ffe3c632Sopenharmony_ci } 1504ffe3c632Sopenharmony_ci 1505ffe3c632Sopenharmony_ci for (upb_msg_field_begin(&i, desc->msgdef); 1506ffe3c632Sopenharmony_ci !upb_msg_field_done(&i); 1507ffe3c632Sopenharmony_ci upb_msg_field_next(&i)) { 1508ffe3c632Sopenharmony_ci upb_fielddef *f = upb_msg_iter_field(&i); 1509ffe3c632Sopenharmony_ci const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f); 1510ffe3c632Sopenharmony_ci bool is_matching_oneof = false; 1511ffe3c632Sopenharmony_ci uint32_t offset = 1512ffe3c632Sopenharmony_ci desc->layout->fields[upb_fielddef_index(f)].offset + 1513ffe3c632Sopenharmony_ci sizeof(MessageHeader); 1514ffe3c632Sopenharmony_ci 1515ffe3c632Sopenharmony_ci if (oneof) { 1516ffe3c632Sopenharmony_ci uint32_t oneof_case = 1517ffe3c632Sopenharmony_ci slot_read_oneof_case(desc->layout, Message_data(msg), oneof); 1518ffe3c632Sopenharmony_ci // For a oneof, check that this field is actually present -- skip all the 1519ffe3c632Sopenharmony_ci // below if not. 1520ffe3c632Sopenharmony_ci if (oneof_case != upb_fielddef_number(f)) { 1521ffe3c632Sopenharmony_ci continue; 1522ffe3c632Sopenharmony_ci } 1523ffe3c632Sopenharmony_ci // Otherwise, fall through to the appropriate singular-field handler 1524ffe3c632Sopenharmony_ci // below. 1525ffe3c632Sopenharmony_ci is_matching_oneof = true; 1526ffe3c632Sopenharmony_ci } 1527ffe3c632Sopenharmony_ci 1528ffe3c632Sopenharmony_ci if (is_map_field(f)) { 1529ffe3c632Sopenharmony_ci VALUE map = DEREF(msg, offset, VALUE); 1530ffe3c632Sopenharmony_ci if (map != Qnil || emit_defaults) { 1531ffe3c632Sopenharmony_ci putmap(map, f, sink, depth, emit_defaults, is_json); 1532ffe3c632Sopenharmony_ci } 1533ffe3c632Sopenharmony_ci } else if (upb_fielddef_isseq(f)) { 1534ffe3c632Sopenharmony_ci VALUE ary = DEREF(msg, offset, VALUE); 1535ffe3c632Sopenharmony_ci if (ary != Qnil) { 1536ffe3c632Sopenharmony_ci putary(ary, f, sink, depth, emit_defaults, is_json); 1537ffe3c632Sopenharmony_ci } 1538ffe3c632Sopenharmony_ci } else if (upb_fielddef_isstring(f)) { 1539ffe3c632Sopenharmony_ci VALUE str = DEREF(msg, offset, VALUE); 1540ffe3c632Sopenharmony_ci bool is_default = false; 1541ffe3c632Sopenharmony_ci 1542ffe3c632Sopenharmony_ci if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO2) { 1543ffe3c632Sopenharmony_ci is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; 1544ffe3c632Sopenharmony_ci } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) { 1545ffe3c632Sopenharmony_ci is_default = RSTRING_LEN(str) == 0; 1546ffe3c632Sopenharmony_ci } 1547ffe3c632Sopenharmony_ci 1548ffe3c632Sopenharmony_ci if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) { 1549ffe3c632Sopenharmony_ci putstr(str, f, sink); 1550ffe3c632Sopenharmony_ci } 1551ffe3c632Sopenharmony_ci } else if (upb_fielddef_issubmsg(f)) { 1552ffe3c632Sopenharmony_ci // OPT: could try to avoid the layout_get() (which will expand lazy 1553ffe3c632Sopenharmony_ci // wrappers). 1554ffe3c632Sopenharmony_ci VALUE val = layout_get(desc->layout, Message_data(msg), f); 1555ffe3c632Sopenharmony_ci putsubmsg(val, f, sink, depth, emit_defaults, is_json); 1556ffe3c632Sopenharmony_ci } else { 1557ffe3c632Sopenharmony_ci upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); 1558ffe3c632Sopenharmony_ci 1559ffe3c632Sopenharmony_ci#define T(upbtypeconst, upbtype, ctype, default_value) \ 1560ffe3c632Sopenharmony_ci case upbtypeconst: { \ 1561ffe3c632Sopenharmony_ci ctype value = DEREF(msg, offset, ctype); \ 1562ffe3c632Sopenharmony_ci bool is_default = false; \ 1563ffe3c632Sopenharmony_ci if (upb_fielddef_haspresence(f)) { \ 1564ffe3c632Sopenharmony_ci is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; \ 1565ffe3c632Sopenharmony_ci } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) { \ 1566ffe3c632Sopenharmony_ci is_default = default_value == value; \ 1567ffe3c632Sopenharmony_ci } \ 1568ffe3c632Sopenharmony_ci if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) { \ 1569ffe3c632Sopenharmony_ci upb_sink_put##upbtype(sink, sel, value); \ 1570ffe3c632Sopenharmony_ci } \ 1571ffe3c632Sopenharmony_ci } break; 1572ffe3c632Sopenharmony_ci 1573ffe3c632Sopenharmony_ci switch (upb_fielddef_type(f)) { 1574ffe3c632Sopenharmony_ci T(UPB_TYPE_FLOAT, float, float, 0.0) 1575ffe3c632Sopenharmony_ci T(UPB_TYPE_DOUBLE, double, double, 0.0) 1576ffe3c632Sopenharmony_ci T(UPB_TYPE_BOOL, bool, uint8_t, 0) 1577ffe3c632Sopenharmony_ci case UPB_TYPE_ENUM: 1578ffe3c632Sopenharmony_ci T(UPB_TYPE_INT32, int32, int32_t, 0) 1579ffe3c632Sopenharmony_ci T(UPB_TYPE_UINT32, uint32, uint32_t, 0) 1580ffe3c632Sopenharmony_ci T(UPB_TYPE_INT64, int64, int64_t, 0) 1581ffe3c632Sopenharmony_ci T(UPB_TYPE_UINT64, uint64, uint64_t, 0) 1582ffe3c632Sopenharmony_ci 1583ffe3c632Sopenharmony_ci case UPB_TYPE_STRING: 1584ffe3c632Sopenharmony_ci case UPB_TYPE_BYTES: 1585ffe3c632Sopenharmony_ci case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error."); 1586ffe3c632Sopenharmony_ci } 1587ffe3c632Sopenharmony_ci 1588ffe3c632Sopenharmony_ci#undef T 1589ffe3c632Sopenharmony_ci } 1590ffe3c632Sopenharmony_ci } 1591ffe3c632Sopenharmony_ci 1592ffe3c632Sopenharmony_ci { 1593ffe3c632Sopenharmony_ci stringsink* unknown = msg->unknown_fields; 1594ffe3c632Sopenharmony_ci if (unknown != NULL) { 1595ffe3c632Sopenharmony_ci upb_sink_putunknown(sink, unknown->ptr, unknown->len); 1596ffe3c632Sopenharmony_ci } 1597ffe3c632Sopenharmony_ci } 1598ffe3c632Sopenharmony_ci 1599ffe3c632Sopenharmony_ci if (open_msg) { 1600ffe3c632Sopenharmony_ci upb_sink_endmsg(sink, &status); 1601ffe3c632Sopenharmony_ci } 1602ffe3c632Sopenharmony_ci} 1603ffe3c632Sopenharmony_ci 1604ffe3c632Sopenharmony_ci/* 1605ffe3c632Sopenharmony_ci * call-seq: 1606ffe3c632Sopenharmony_ci * MessageClass.encode(msg) => bytes 1607ffe3c632Sopenharmony_ci * 1608ffe3c632Sopenharmony_ci * Encodes the given message object to its serialized form in protocol buffers 1609ffe3c632Sopenharmony_ci * wire format. 1610ffe3c632Sopenharmony_ci */ 1611ffe3c632Sopenharmony_ciVALUE Message_encode(VALUE klass, VALUE msg_rb) { 1612ffe3c632Sopenharmony_ci VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1613ffe3c632Sopenharmony_ci Descriptor* desc = ruby_to_Descriptor(descriptor); 1614ffe3c632Sopenharmony_ci 1615ffe3c632Sopenharmony_ci stringsink sink; 1616ffe3c632Sopenharmony_ci stringsink_init(&sink); 1617ffe3c632Sopenharmony_ci 1618ffe3c632Sopenharmony_ci { 1619ffe3c632Sopenharmony_ci const upb_handlers* serialize_handlers = 1620ffe3c632Sopenharmony_ci msgdef_pb_serialize_handlers(desc); 1621ffe3c632Sopenharmony_ci 1622ffe3c632Sopenharmony_ci stackenv se; 1623ffe3c632Sopenharmony_ci upb_pb_encoder* encoder; 1624ffe3c632Sopenharmony_ci VALUE ret; 1625ffe3c632Sopenharmony_ci 1626ffe3c632Sopenharmony_ci stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE); 1627ffe3c632Sopenharmony_ci encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink); 1628ffe3c632Sopenharmony_ci 1629ffe3c632Sopenharmony_ci putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true); 1630ffe3c632Sopenharmony_ci 1631ffe3c632Sopenharmony_ci ret = rb_str_new(sink.ptr, sink.len); 1632ffe3c632Sopenharmony_ci 1633ffe3c632Sopenharmony_ci stackenv_uninit(&se); 1634ffe3c632Sopenharmony_ci stringsink_uninit(&sink); 1635ffe3c632Sopenharmony_ci 1636ffe3c632Sopenharmony_ci return ret; 1637ffe3c632Sopenharmony_ci } 1638ffe3c632Sopenharmony_ci} 1639ffe3c632Sopenharmony_ci 1640ffe3c632Sopenharmony_ci/* 1641ffe3c632Sopenharmony_ci * call-seq: 1642ffe3c632Sopenharmony_ci * MessageClass.encode_json(msg, options = {}) => json_string 1643ffe3c632Sopenharmony_ci * 1644ffe3c632Sopenharmony_ci * Encodes the given message object into its serialized JSON representation. 1645ffe3c632Sopenharmony_ci * @param options [Hash] options for the decoder 1646ffe3c632Sopenharmony_ci * preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase) 1647ffe3c632Sopenharmony_ci * emit_defaults: set true to emit 0/false values (default is to omit them) 1648ffe3c632Sopenharmony_ci */ 1649ffe3c632Sopenharmony_ciVALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { 1650ffe3c632Sopenharmony_ci VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1651ffe3c632Sopenharmony_ci Descriptor* desc = ruby_to_Descriptor(descriptor); 1652ffe3c632Sopenharmony_ci VALUE msg_rb; 1653ffe3c632Sopenharmony_ci VALUE preserve_proto_fieldnames = Qfalse; 1654ffe3c632Sopenharmony_ci VALUE emit_defaults = Qfalse; 1655ffe3c632Sopenharmony_ci stringsink sink; 1656ffe3c632Sopenharmony_ci 1657ffe3c632Sopenharmony_ci if (argc < 1 || argc > 2) { 1658ffe3c632Sopenharmony_ci rb_raise(rb_eArgError, "Expected 1 or 2 arguments."); 1659ffe3c632Sopenharmony_ci } 1660ffe3c632Sopenharmony_ci 1661ffe3c632Sopenharmony_ci msg_rb = argv[0]; 1662ffe3c632Sopenharmony_ci 1663ffe3c632Sopenharmony_ci if (argc == 2) { 1664ffe3c632Sopenharmony_ci VALUE hash_args = argv[1]; 1665ffe3c632Sopenharmony_ci if (TYPE(hash_args) != T_HASH) { 1666ffe3c632Sopenharmony_ci rb_raise(rb_eArgError, "Expected hash arguments."); 1667ffe3c632Sopenharmony_ci } 1668ffe3c632Sopenharmony_ci preserve_proto_fieldnames = rb_hash_lookup2( 1669ffe3c632Sopenharmony_ci hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse); 1670ffe3c632Sopenharmony_ci 1671ffe3c632Sopenharmony_ci emit_defaults = rb_hash_lookup2( 1672ffe3c632Sopenharmony_ci hash_args, ID2SYM(rb_intern("emit_defaults")), Qfalse); 1673ffe3c632Sopenharmony_ci } 1674ffe3c632Sopenharmony_ci 1675ffe3c632Sopenharmony_ci stringsink_init(&sink); 1676ffe3c632Sopenharmony_ci 1677ffe3c632Sopenharmony_ci { 1678ffe3c632Sopenharmony_ci const upb_handlers* serialize_handlers = 1679ffe3c632Sopenharmony_ci msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames)); 1680ffe3c632Sopenharmony_ci upb_json_printer* printer; 1681ffe3c632Sopenharmony_ci stackenv se; 1682ffe3c632Sopenharmony_ci VALUE ret; 1683ffe3c632Sopenharmony_ci 1684ffe3c632Sopenharmony_ci stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE); 1685ffe3c632Sopenharmony_ci printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink); 1686ffe3c632Sopenharmony_ci 1687ffe3c632Sopenharmony_ci putmsg(msg_rb, desc, upb_json_printer_input(printer), 0, 1688ffe3c632Sopenharmony_ci RTEST(emit_defaults), true, true); 1689ffe3c632Sopenharmony_ci 1690ffe3c632Sopenharmony_ci ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding()); 1691ffe3c632Sopenharmony_ci 1692ffe3c632Sopenharmony_ci stackenv_uninit(&se); 1693ffe3c632Sopenharmony_ci stringsink_uninit(&sink); 1694ffe3c632Sopenharmony_ci 1695ffe3c632Sopenharmony_ci return ret; 1696ffe3c632Sopenharmony_ci } 1697ffe3c632Sopenharmony_ci} 1698ffe3c632Sopenharmony_ci 1699ffe3c632Sopenharmony_cistatic void discard_unknown(VALUE msg_rb, const Descriptor* desc) { 1700ffe3c632Sopenharmony_ci MessageHeader* msg; 1701ffe3c632Sopenharmony_ci upb_msg_field_iter it; 1702ffe3c632Sopenharmony_ci 1703ffe3c632Sopenharmony_ci TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1704ffe3c632Sopenharmony_ci 1705ffe3c632Sopenharmony_ci { 1706ffe3c632Sopenharmony_ci stringsink* unknown = msg->unknown_fields; 1707ffe3c632Sopenharmony_ci if (unknown != NULL) { 1708ffe3c632Sopenharmony_ci stringsink_uninit(unknown); 1709ffe3c632Sopenharmony_ci msg->unknown_fields = NULL; 1710ffe3c632Sopenharmony_ci } 1711ffe3c632Sopenharmony_ci } 1712ffe3c632Sopenharmony_ci 1713ffe3c632Sopenharmony_ci for (upb_msg_field_begin(&it, desc->msgdef); 1714ffe3c632Sopenharmony_ci !upb_msg_field_done(&it); 1715ffe3c632Sopenharmony_ci upb_msg_field_next(&it)) { 1716ffe3c632Sopenharmony_ci upb_fielddef *f = upb_msg_iter_field(&it); 1717ffe3c632Sopenharmony_ci const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f); 1718ffe3c632Sopenharmony_ci uint32_t offset = 1719ffe3c632Sopenharmony_ci desc->layout->fields[upb_fielddef_index(f)].offset + 1720ffe3c632Sopenharmony_ci sizeof(MessageHeader); 1721ffe3c632Sopenharmony_ci 1722ffe3c632Sopenharmony_ci if (oneof) { 1723ffe3c632Sopenharmony_ci uint32_t oneof_case = 1724ffe3c632Sopenharmony_ci slot_read_oneof_case(desc->layout, Message_data(msg), oneof); 1725ffe3c632Sopenharmony_ci // For a oneof, check that this field is actually present -- skip all the 1726ffe3c632Sopenharmony_ci // below if not. 1727ffe3c632Sopenharmony_ci if (oneof_case != upb_fielddef_number(f)) { 1728ffe3c632Sopenharmony_ci continue; 1729ffe3c632Sopenharmony_ci } 1730ffe3c632Sopenharmony_ci // Otherwise, fall through to the appropriate singular-field handler 1731ffe3c632Sopenharmony_ci // below. 1732ffe3c632Sopenharmony_ci } 1733ffe3c632Sopenharmony_ci 1734ffe3c632Sopenharmony_ci if (!upb_fielddef_issubmsg(f)) { 1735ffe3c632Sopenharmony_ci continue; 1736ffe3c632Sopenharmony_ci } 1737ffe3c632Sopenharmony_ci 1738ffe3c632Sopenharmony_ci if (is_map_field(f)) { 1739ffe3c632Sopenharmony_ci VALUE map; 1740ffe3c632Sopenharmony_ci Map_iter map_it; 1741ffe3c632Sopenharmony_ci 1742ffe3c632Sopenharmony_ci if (!upb_fielddef_issubmsg(map_field_value(f))) continue; 1743ffe3c632Sopenharmony_ci map = DEREF(msg, offset, VALUE); 1744ffe3c632Sopenharmony_ci if (map == Qnil) continue; 1745ffe3c632Sopenharmony_ci for (Map_begin(map, &map_it); !Map_done(&map_it); Map_next(&map_it)) { 1746ffe3c632Sopenharmony_ci VALUE submsg = Map_iter_value(&map_it); 1747ffe3c632Sopenharmony_ci VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 1748ffe3c632Sopenharmony_ci const Descriptor* subdesc = ruby_to_Descriptor(descriptor); 1749ffe3c632Sopenharmony_ci discard_unknown(submsg, subdesc); 1750ffe3c632Sopenharmony_ci } 1751ffe3c632Sopenharmony_ci } else if (upb_fielddef_isseq(f)) { 1752ffe3c632Sopenharmony_ci VALUE ary = DEREF(msg, offset, VALUE); 1753ffe3c632Sopenharmony_ci int size; 1754ffe3c632Sopenharmony_ci int i; 1755ffe3c632Sopenharmony_ci 1756ffe3c632Sopenharmony_ci if (ary == Qnil) continue; 1757ffe3c632Sopenharmony_ci size = NUM2INT(RepeatedField_length(ary)); 1758ffe3c632Sopenharmony_ci for (i = 0; i < size; i++) { 1759ffe3c632Sopenharmony_ci void* memory = RepeatedField_index_native(ary, i); 1760ffe3c632Sopenharmony_ci VALUE submsg = *((VALUE *)memory); 1761ffe3c632Sopenharmony_ci VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 1762ffe3c632Sopenharmony_ci const Descriptor* subdesc = ruby_to_Descriptor(descriptor); 1763ffe3c632Sopenharmony_ci discard_unknown(submsg, subdesc); 1764ffe3c632Sopenharmony_ci } 1765ffe3c632Sopenharmony_ci } else { 1766ffe3c632Sopenharmony_ci VALUE submsg = DEREF(msg, offset, VALUE); 1767ffe3c632Sopenharmony_ci VALUE descriptor; 1768ffe3c632Sopenharmony_ci const Descriptor* subdesc; 1769ffe3c632Sopenharmony_ci 1770ffe3c632Sopenharmony_ci if (submsg == Qnil) continue; 1771ffe3c632Sopenharmony_ci descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 1772ffe3c632Sopenharmony_ci subdesc = ruby_to_Descriptor(descriptor); 1773ffe3c632Sopenharmony_ci discard_unknown(submsg, subdesc); 1774ffe3c632Sopenharmony_ci } 1775ffe3c632Sopenharmony_ci } 1776ffe3c632Sopenharmony_ci} 1777ffe3c632Sopenharmony_ci 1778ffe3c632Sopenharmony_ci/* 1779ffe3c632Sopenharmony_ci * call-seq: 1780ffe3c632Sopenharmony_ci * Google::Protobuf.discard_unknown(msg) 1781ffe3c632Sopenharmony_ci * 1782ffe3c632Sopenharmony_ci * Discard unknown fields in the given message object and recursively discard 1783ffe3c632Sopenharmony_ci * unknown fields in submessages. 1784ffe3c632Sopenharmony_ci */ 1785ffe3c632Sopenharmony_ciVALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb) { 1786ffe3c632Sopenharmony_ci VALUE klass = CLASS_OF(msg_rb); 1787ffe3c632Sopenharmony_ci VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1788ffe3c632Sopenharmony_ci Descriptor* desc = ruby_to_Descriptor(descriptor); 1789ffe3c632Sopenharmony_ci if (klass == cRepeatedField || klass == cMap) { 1790ffe3c632Sopenharmony_ci rb_raise(rb_eArgError, "Expected proto msg for discard unknown."); 1791ffe3c632Sopenharmony_ci } else { 1792ffe3c632Sopenharmony_ci discard_unknown(msg_rb, desc); 1793ffe3c632Sopenharmony_ci } 1794ffe3c632Sopenharmony_ci return Qnil; 1795ffe3c632Sopenharmony_ci} 1796