@ -117,18 +117,18 @@ static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit)
typedef struct {
size_t ofs ;
int32_t hasbit ;
const upb_msgdef * md ;
VALUE subklass ;
} submsg_handlerdata_t ;
// Creates a handlerdata that contains offset and submessage type information.
static const void * newsubmsghandlerdata ( upb_handlers * h ,
uint32_t ofs ,
int32_t hasbit ,
const upb_fielddef * f ) {
VALUE subklass ) {
submsg_handlerdata_t * hd = ALLOC ( submsg_handlerdata_t ) ;
hd - > ofs = ofs ;
hd - > hasbit = hasbit ;
hd - > md = upb_fielddef_msgsubdef ( f ) ;
hd - > subklass = subklass ;
upb_handlers_addcleanup ( h , hd , xfree ) ;
return hd ;
}
@ -137,13 +137,14 @@ typedef struct {
size_t ofs ; // union data slot
size_t case_ofs ; // oneof_case field
uint32_t oneof_case_num ; // oneof-case number to place in oneof_case field
const upb_msgdef * md ; // msgdef, for oneof submessage handler
VALUE subklass ;
} oneof_handlerdata_t ;
static const void * newoneofhandlerdata ( upb_handlers * h ,
uint32_t ofs ,
uint32_t case_ofs ,
const upb_fielddef * f ) {
const upb_fielddef * f ,
const Descriptor * desc ) {
oneof_handlerdata_t * hd = ALLOC ( oneof_handlerdata_t ) ;
hd - > ofs = ofs ;
hd - > case_ofs = case_ofs ;
@ -154,11 +155,7 @@ static const void *newoneofhandlerdata(upb_handlers *h,
// create a separate ID space. In addition, using the field tag number here
// lets us easily look up the field in the oneof accessor.
hd - > oneof_case_num = upb_fielddef_number ( f ) ;
if ( upb_fielddef_type ( f ) = = UPB_TYPE_MESSAGE ) {
hd - > md = upb_fielddef_msgsubdef ( f ) ;
} else {
hd - > md = NULL ;
}
hd - > subklass = field_type_class ( desc - > layout , f ) ;
upb_handlers_addcleanup ( h , hd , xfree ) ;
return hd ;
}
@ -254,13 +251,13 @@ static size_t stringdata_handler(void* closure, const void* hd,
}
static bool stringdata_end_handler ( void * closure , const void * hd ) {
VALUE rb_str = closure ;
VALUE rb_str = ( VALUE ) closure ;
rb_obj_freeze ( rb_str ) ;
return true ;
}
static bool appendstring_end_handler ( void * closure , const void * hd ) {
VALUE rb_str = closure ;
VALUE rb_str = ( VALUE ) closure ;
rb_obj_freeze ( rb_str ) ;
return true ;
}
@ -269,12 +266,9 @@ static bool appendstring_end_handler(void* closure, const void* hd) {
static void * appendsubmsg_handler ( void * closure , const void * hd ) {
VALUE ary = ( VALUE ) closure ;
const submsg_handlerdata_t * submsgdata = hd ;
VALUE subdesc =
get_def_obj ( ( void * ) submsgdata - > md ) ;
VALUE subklass = Descriptor_msgclass ( subdesc ) ;
MessageHeader * submsg ;
VALUE submsg_rb = rb_class_new_instance ( 0 , NULL , subklass ) ;
VALUE submsg_rb = rb_class_new_instance ( 0 , NULL , submsgdata - > subklass ) ;
RepeatedField_push ( ary , submsg_rb ) ;
TypedData_Get_Struct ( submsg_rb , MessageHeader , & Message_type , submsg ) ;
@ -285,15 +279,12 @@ static void *appendsubmsg_handler(void *closure, const void *hd) {
static void * submsg_handler ( void * closure , const void * hd ) {
MessageHeader * msg = closure ;
const submsg_handlerdata_t * submsgdata = hd ;
VALUE subdesc =
get_def_obj ( ( void * ) submsgdata - > md ) ;
VALUE subklass = Descriptor_msgclass ( subdesc ) ;
VALUE submsg_rb ;
MessageHeader * submsg ;
if ( DEREF ( msg , submsgdata - > ofs , VALUE ) = = Qnil ) {
DEREF ( msg , submsgdata - > ofs , VALUE ) =
rb_class_new_instance ( 0 , NULL , subklass ) ;
rb_class_new_instance ( 0 , NULL , submsgdata - > sub klass ) ;
}
set_hasbit ( closure , submsgdata - > hasbit ) ;
@ -309,11 +300,7 @@ typedef struct {
size_t ofs ;
upb_fieldtype_t key_field_type ;
upb_fieldtype_t value_field_type ;
// We know that we can hold this reference because the handlerdata has the
// same lifetime as the upb_handlers struct, and the upb_handlers struct holds
// a reference to the upb_msgdef, which in turn has references to its subdefs.
const upb_def * value_field_subdef ;
VALUE subklass ;
} map_handlerdata_t ;
// Temporary frame for map parsing: at the beginning of a map entry message, a
@ -383,19 +370,8 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
mapdata - > key_field_type , Qnil ,
& frame - > key_storage ) ;
VALUE value_field_typeclass = Qnil ;
VALUE value ;
if ( mapdata - > value_field_type = = UPB_TYPE_MESSAGE | |
mapdata - > value_field_type = = UPB_TYPE_ENUM ) {
value_field_typeclass = get_def_obj ( mapdata - > value_field_subdef ) ;
if ( mapdata - > value_field_type = = UPB_TYPE_ENUM ) {
value_field_typeclass = EnumDescriptor_enummodule ( value_field_typeclass ) ;
}
}
value = native_slot_get (
mapdata - > value_field_type , value_field_typeclass ,
VALUE value = native_slot_get (
mapdata - > value_field_type , mapdata - > subklass ,
& frame - > value_storage ) ;
Map_index_set ( frame - > map , key , value ) ;
@ -414,7 +390,7 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
static map_handlerdata_t * new_map_handlerdata (
size_t ofs ,
const upb_msgdef * mapentry_def ,
Descriptor * desc ) {
const Descriptor * desc ) {
const upb_fielddef * key_field ;
const upb_fielddef * value_field ;
map_handlerdata_t * hd = ALLOC ( map_handlerdata_t ) ;
@ -425,7 +401,7 @@ static map_handlerdata_t* new_map_handlerdata(
value_field = upb_msgdef_itof ( mapentry_def , MAP_VALUE_FIELD ) ;
assert ( value_field ! = NULL ) ;
hd - > value_field_type = upb_fielddef_type ( value_field ) ;
hd - > value_field_subdef = upb_fielddef_subdef ( value_field ) ;
hd - > subklass = field_type_class ( desc - > layout , value_field ) ;
return hd ;
}
@ -491,16 +467,13 @@ static void *oneofsubmsg_handler(void *closure,
const oneof_handlerdata_t * oneofdata = hd ;
uint32_t oldcase = DEREF ( msg , oneofdata - > case_ofs , uint32_t ) ;
VALUE subdesc =
get_def_obj ( ( void * ) oneofdata - > md ) ;
VALUE subklass = Descriptor_msgclass ( subdesc ) ;
VALUE submsg_rb ;
MessageHeader * submsg ;
if ( oldcase ! = oneofdata - > oneof_case_num | |
DEREF ( msg , oneofdata - > ofs , VALUE ) = = Qnil ) {
DEREF ( msg , oneofdata - > ofs , VALUE ) =
rb_class_new_instance ( 0 , NULL , subklass ) ;
rb_class_new_instance ( 0 , NULL , oneofdata - > subklass ) ;
}
// Set the oneof case *after* allocating the new class instance -- otherwise,
// if the Ruby GC is invoked as part of a call into the VM, it might invoke
@ -518,12 +491,12 @@ static void *oneofsubmsg_handler(void *closure,
// Set up handlers for a repeated field.
static void add_handlers_for_repeated_field ( upb_handlers * h ,
const Descriptor * desc ,
const upb_fielddef * f ,
size_t offset ) {
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER ;
upb_handlerattr_sethandlerdata ( & attr , newhandlerdata ( h , offset , - 1 ) ) ;
upb_handlerattr attr = UPB_HANDLERATTR_INIT ;
attr . handler_data = newhandlerdata ( h , offset , - 1 ) ;
upb_handlers_setstartseq ( h , f , startseq_handler , & attr ) ;
upb_handlerattr_uninit ( & attr ) ;
switch ( upb_fielddef_type ( f ) ) {
@ -554,20 +527,20 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
break ;
}
case UPB_TYPE_MESSAGE : {
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER ;
upb_handlerattr_sethandlerdata ( & attr , newsubmsghandlerdata ( h , 0 , - 1 , f ) ) ;
VALUE subklass = field_type_class ( desc - > layout , f ) ;
upb_handlerattr attr = UPB_HANDLERATTR_INIT ;
attr . handler_data = newsubmsghandlerdata ( h , 0 , - 1 , subklass ) ;
upb_handlers_setstartsubmsg ( h , f , appendsubmsg_handler , & attr ) ;
upb_handlerattr_uninit ( & attr ) ;
break ;
}
}
}
// Set up handlers for a singular field.
static void add_handlers_for_singular_field ( upb_handlers * h ,
const upb_fielddef * f ,
size_t offset ,
size_t hasbit_off ) {
static void add_handlers_for_singular_field ( const Descriptor * desc ,
upb_handlers * h ,
const upb_fielddef * f ,
size_t offset , size_t hasbit_off ) {
// The offset we pass to UPB points to the start of the Message,
// rather than the start of where our data is stored.
int32_t hasbit = - 1 ;
@ -589,23 +562,20 @@ static void add_handlers_for_singular_field(upb_handlers *h,
case UPB_TYPE_STRING :
case UPB_TYPE_BYTES : {
bool is_bytes = upb_fielddef_type ( f ) = = UPB_TYPE_BYTES ;
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER ;
upb_handlerattr_sethandlerdata ( & attr , newhandlerdata ( h , offset , hasbit ) ) ;
upb_handlerattr attr = UPB_HANDLERATTR_INIT ;
attr . handler_data = newhandlerdata ( h , offset , hasbit ) ;
upb_handlers_setstartstr ( h , f ,
is_bytes ? bytes_handler : str_handler ,
& attr ) ;
upb_handlers_setstring ( h , f , stringdata_handler , & attr ) ;
upb_handlers_setendstr ( h , f , stringdata_end_handler , & attr ) ;
upb_handlerattr_uninit ( & attr ) ;
break ;
}
case UPB_TYPE_MESSAGE : {
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER ;
upb_handlerattr_sethandlerdata ( & attr ,
newsubmsghandlerdata ( h , offset ,
hasbit , f ) ) ;
upb_handlerattr attr = UPB_HANDLERATTR_INIT ;
attr . handler_data = newsubmsghandlerdata (
h , offset , hasbit , field_type_class ( desc - > layout , f ) ) ;
upb_handlers_setstartsubmsg ( h , f , submsg_handler , & attr ) ;
upb_handlerattr_uninit ( & attr ) ;
break ;
}
}
@ -615,36 +585,34 @@ static void add_handlers_for_singular_field(upb_handlers *h,
static void add_handlers_for_mapfield ( upb_handlers * h ,
const upb_fielddef * fielddef ,
size_t offset ,
Descriptor * desc ) {
const Descriptor * desc ) {
const upb_msgdef * map_msgdef = upb_fielddef_msgsubdef ( fielddef ) ;
map_handlerdata_t * hd = new_map_handlerdata ( offset , map_msgdef , desc ) ;
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER ;
upb_handlerattr attr = UPB_HANDLERATTR_INIT ;
upb_handlers_addcleanup ( h , hd , xfree ) ;
upb_handlerattr_sethandlerdata ( & attr , hd ) ;
attr . handler_data = hd ;
upb_handlers_setstartsubmsg ( h , fielddef , startmapentry_handler , & attr ) ;
upb_handlerattr_uninit ( & attr ) ;
}
// Adds handlers to a map-entry msgdef.
static void add_handlers_for_mapentry ( const upb_msgdef * msgdef ,
upb_handlers * h ,
Descriptor * desc ) {
static void add_handlers_for_mapentry ( const upb_msgdef * msgdef , upb_handlers * h ,
const Descriptor * desc ) {
const upb_fielddef * key_field = map_entry_key ( msgdef ) ;
const upb_fielddef * value_field = map_entry_value ( msgdef ) ;
map_handlerdata_t * hd = new_map_handlerdata ( 0 , msgdef , desc ) ;
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER ;
upb_handlerattr attr = UPB_HANDLERATTR_INIT ;
upb_handlers_addcleanup ( h , hd , xfree ) ;
upb_handlerattr_sethandlerdata ( & attr , hd ) ;
attr . handler_data = hd ;
upb_handlers_setendmsg ( h , endmap_handler , & attr ) ;
add_handlers_for_singular_field (
h , key_field ,
desc , h , key_field ,
offsetof ( map_parse_frame_t , key_storage ) ,
MESSAGE_FIELD_NO_HASBIT ) ;
add_handlers_for_singular_field (
h , value_field ,
desc , h , value_field ,
offsetof ( map_parse_frame_t , value_storage ) ,
MESSAGE_FIELD_NO_HASBIT ) ;
}
@ -653,11 +621,11 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
static void add_handlers_for_oneof_field ( upb_handlers * h ,
const upb_fielddef * f ,
size_t offset ,
size_t oneof_case_offset ) {
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER ;
upb_handlerattr_sethandlerdata (
& attr , newoneofhandlerdata ( h , offset , oneof_case_offset , f ) ) ;
size_t oneof_case_offset ,
const Descriptor * desc ) {
upb_handlerattr attr = UPB_HANDLERATTR_INIT ;
attr . handler_data =
newoneofhandlerdata ( h , offset , oneof_case_offset , f , desc ) ;
switch ( upb_fielddef_type ( f ) ) {
@ -692,15 +660,13 @@ static void add_handlers_for_oneof_field(upb_handlers *h,
break ;
}
}
upb_handlerattr_uninit ( & attr ) ;
}
static bool unknown_field_handler ( void * closure , const void * hd ,
const char * buf , size_t size ) {
MessageHeader * msg = ( MessageHeader * ) closure ;
UPB_UNUSED ( hd ) ;
MessageHeader * msg = ( MessageHeader * ) closure ;
if ( msg - > unknown_fields = = NULL ) {
msg - > unknown_fields = malloc ( sizeof ( stringsink ) ) ;
stringsink_init ( msg - > unknown_fields ) ;
@ -711,27 +677,29 @@ static bool unknown_field_handler(void* closure, const void* hd,
return true ;
}
static void add_handlers_for_message ( const void * closure , upb_handlers * h ) {
void add_handlers_for_message ( const void * closure , upb_handlers * h ) {
const VALUE descriptor_pool = ( VALUE ) closure ;
const upb_msgdef * msgdef = upb_handlers_msgdef ( h ) ;
Descriptor * desc = ruby_to_Descriptor ( get_def_obj ( ( void * ) msgdef ) ) ;
Descriptor * desc =
ruby_to_Descriptor ( get_msgdef_obj ( descriptor_pool , msgdef ) ) ;
upb_msg_field_iter i ;
// If this is a mapentry message type, set up a special set of handlers and
// bail out of the normal (user-defined) message type handling.
if ( upb_msgdef_mapentry ( msgdef ) ) {
add_handlers_for_mapentry ( msgdef , h , desc ) ;
return ;
}
upb_handlerattr attr = UPB_HANDLERATTR_INIT ;
// Ensure layout exists. We may be invoked to create handlers for a given
// message if we are included as a submsg of another message type before our
// class is actually built, so to work around this, we just create the layout
// (and handlers, in the class-building function) on-demand.
if ( desc - > layout = = NULL ) {
desc - > layout = create_layout ( desc - > msgdef ) ;
desc - > layout = create_layout ( desc ) ;
}
// If this is a mapentry message type, set up a special set of handlers and
// bail out of the normal (user-defined) message type handling.
if ( upb_msgdef_mapentry ( msgdef ) ) {
add_handlers_for_mapentry ( msgdef , h , desc ) ;
return ;
}
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER ;
upb_handlers_setunknown ( h , unknown_field_handler , & attr ) ;
for ( upb_msg_field_begin ( & i , desc - > msgdef ) ;
@ -745,64 +713,51 @@ static void add_handlers_for_message(const void *closure, upb_handlers *h) {
size_t oneof_case_offset =
desc - > layout - > fields [ upb_fielddef_index ( f ) ] . case_offset +
sizeof ( MessageHeader ) ;
add_handlers_for_oneof_field ( h , f , offset , oneof_case_offset ) ;
add_handlers_for_oneof_field ( h , f , offset , oneof_case_offset , desc ) ;
} else if ( is_map_field ( f ) ) {
add_handlers_for_mapfield ( h , f , offset , desc ) ;
} else if ( upb_fielddef_isseq ( f ) ) {
add_handlers_for_repeated_field ( h , f , offset ) ;
add_handlers_for_repeated_field ( h , desc , f , offset ) ;
} else {
add_handlers_for_singular_field (
h , f , offset , desc - > layout - > fields [ upb_fielddef_index ( f ) ] . hasbit ) ;
desc , h , f , offset ,
desc - > layout - > fields [ upb_fielddef_index ( f ) ] . hasbit ) ;
}
}
}
// Creates upb handlers for populating a message.
static const upb_handlers * new_fill_handlers ( Descriptor * desc ,
const void * owner ) {
// TODO(cfallin, haberman): once upb gets a caching/memoization layer for
// handlers, reuse subdef handlers so that e.g. if we already parse
// B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to
// parse A-with-field-of-type-B-with-field-of-type-C.
return upb_handlers_newfrozen ( desc - > msgdef , owner ,
add_handlers_for_message , NULL ) ;
}
// Constructs the handlers for filling a message's data into an in-memory
// object.
const upb_handlers * get_fill_handlers ( Descriptor * desc ) {
if ( ! desc - > fill_handlers ) {
desc - > fill_handlers =
new_fill_handlers ( desc , & desc - > fill_handlers ) ;
}
return desc - > fill_handlers ;
DescriptorPool * pool = ruby_to_DescriptorPool ( desc - > descriptor_pool ) ;
return upb_handlercache_get ( pool - > fill_handler_cache , desc - > msgdef ) ;
}
// Constructs the upb decoder method for parsing messages of this type.
// This is called from the message class creation code.
const upb_pbdecodermethod * new_fillmsg_decodermethod ( Descriptor * desc ,
const void * owner ) {
const upb_handlers * handlers = get_fill_handlers ( desc ) ;
upb_pbdecodermethodopts opts ;
upb_pbdecodermethodopts_init ( & opts , handlers ) ;
static const upb_pbdecodermethod * msgdef_decodermethod ( Descriptor * desc ) {
DescriptorPool * pool = ruby_to_DescriptorPool ( desc - > descriptor_pool ) ;
return upb_pbcodecache_get ( pool - > fill_method_cache , desc - > msgdef ) ;
}
return upb_pbdecodermethod_new ( & opts , owner ) ;
static const upb_json_parsermethod * msgdef_jsonparsermethod ( Descriptor * desc ) {
DescriptorPool * pool = ruby_to_DescriptorPool ( desc - > descriptor_pool ) ;
return upb_json_codecache_get ( pool - > json_fill_method_cache , desc - > msgdef ) ;
}
static const upb_pbdecodermethod * msgdef_decodermethod ( Descriptor * desc ) {
if ( desc - > fill_method = = NULL ) {
desc - > fill_method = new_fillmsg_decodermethod (
desc , & desc - > fill_method ) ;
}
return desc - > fill_method ;
static const upb_handlers * msgdef_pb_serialize_handlers ( Descriptor * desc ) {
DescriptorPool * pool = ruby_to_DescriptorPool ( desc - > descriptor_pool ) ;
return upb_handlercache_get ( pool - > pb_serialize_handler_cache , desc - > msgdef ) ;
}
static const upb_json_parsermethod * msgdef_jsonparsermethod ( Descriptor * desc ) {
if ( desc - > json_fill_method = = NULL ) {
desc - > json_fill_method =
upb_json_parsermethod_new ( desc - > msgdef , & desc - > json_fill_method ) ;
static const upb_handlers * msgdef_json_serialize_handlers (
Descriptor * desc , bool preserve_proto_fieldnames ) {
DescriptorPool * pool = ruby_to_DescriptorPool ( desc - > descriptor_pool ) ;
if ( preserve_proto_fieldnames ) {
return upb_handlercache_get ( pool - > json_serialize_handler_preserve_cache ,
desc - > msgdef ) ;
} else {
return upb_handlercache_get ( pool - > json_serialize_handler_cache ,
desc - > msgdef ) ;
}
return desc - > json_fill_method ;
}
@ -812,7 +767,8 @@ static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
// if any error occurs.
# define STACK_ENV_STACKBYTES 4096
typedef struct {
upb_env env ;
upb_arena * arena ;
upb_status status ;
const char * ruby_error_template ;
char allocbuf [ STACK_ENV_STACKBYTES ] ;
} stackenv ;
@ -820,29 +776,22 @@ typedef struct {
static void stackenv_init ( stackenv * se , const char * errmsg ) ;
static void stackenv_uninit ( stackenv * se ) ;
// Callback invoked by upb if any error occurs during parsing or serialization.
static bool env_error_func ( void * ud , const upb_status * status ) {
stackenv * se = ud ;
// Free the env -- rb_raise will longjmp up the stack past the encode/decode
// function so it would not otherwise have been freed.
stackenv_uninit ( se ) ;
// TODO(haberman): have a way to verify that this is actually a parse error,
// instead of just throwing "parse error" unconditionally.
rb_raise ( cParseError , se - > ruby_error_template , upb_status_errmsg ( status ) ) ;
// Never reached: rb_raise() always longjmp()s up the stack, past all of our
// code, back to Ruby.
return false ;
}
static void stackenv_init ( stackenv * se , const char * errmsg ) {
se - > ruby_error_template = errmsg ;
upb_env_init2 ( & se - > env , se - > allocbuf , sizeof ( se - > allocbuf ) , NULL ) ;
upb_env_seterrorfunc ( & se - > env , env_error_func , se ) ;
se - > arena =
upb_arena_init ( se - > allocbuf , sizeof ( se - > allocbuf ) , & upb_alloc_global ) ;
upb_status_clear ( & se - > status ) ;
}
static void stackenv_uninit ( stackenv * se ) {
upb_env_uninit ( & se - > env ) ;
upb_arena_free ( se - > arena ) ;
if ( ! upb_ok ( & se - > status ) ) {
// TODO(haberman): have a way to verify that this is actually a parse error,
// instead of just throwing "parse error" unconditionally.
VALUE errmsg = rb_str_new2 ( upb_status_errmsg ( & se - > status ) ) ;
rb_raise ( cParseError , se - > ruby_error_template , errmsg ) ;
}
}
/*
@ -873,10 +822,10 @@ VALUE Message_decode(VALUE klass, VALUE data) {
stackenv se ;
upb_sink sink ;
upb_pbdecoder * decoder ;
stackenv_init ( & se , " Error occurred during parsing: %s " ) ;
stackenv_init ( & se , " Error occurred during parsing: % " PRIsVALUE ) ;
upb_sink_reset ( & sink , h , msg ) ;
decoder = upb_pbdecoder_create ( & se . env , method , & sink ) ;
decoder = upb_pbdecoder_create ( se . arena , method , sink , & se . status ) ;
upb_bufsrc_putbuf ( RSTRING_PTR ( data ) , RSTRING_LEN ( data ) ,
upb_pbdecoder_input ( decoder ) ) ;
@ -894,8 +843,9 @@ VALUE Message_decode(VALUE klass, VALUE data) {
* format ) under the interpretration given by this message class ' s definition
* and returns a message object with the corresponding field values .
*
* @ param options [ Hash ] options for the decoder
* ignore_unknown_fields : set true to ignore unknown fields ( default is to raise an error )
* @ param options [ Hash ] options for the decoder
* ignore_unknown_fields : set true to ignore unknown fields ( default is to
* raise an error )
*/
VALUE Message_decode_json ( int argc , VALUE * argv , VALUE klass ) {
VALUE descriptor = rb_ivar_get ( klass , descriptor_instancevar_interned ) ;
@ -923,6 +873,7 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
if ( TYPE ( data ) ! = T_STRING ) {
rb_raise ( rb_eArgError , " Expected string for JSON data. " ) ;
}
// TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
// convert, because string handlers pass data directly to message string
// fields.
@ -936,11 +887,11 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
upb_sink sink ;
upb_json_parser * parser ;
DescriptorPool * pool = ruby_to_DescriptorPool ( generated_pool ) ;
stackenv_init ( & se , " Error occurred during parsing: %s " ) ;
stackenv_init ( & se , " Error occurred during parsing: % " PRIsVALUE ) ;
upb_sink_reset ( & sink , get_fill_handlers ( desc ) , msg ) ;
parser = upb_json_parser_create ( & se . env , method , pool - > symtab ,
& sink , ignore_unknown_fields ) ;
parser = upb_json_parser_create ( se . arena , method , pool - > symtab , sink ,
& se . status , RTEST ( ignore_unknown_fields ) ) ;
upb_bufsrc_putbuf ( RSTRING_PTR ( data ) , RSTRING_LEN ( data ) ,
upb_json_parser_input ( parser ) ) ;
@ -956,9 +907,8 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
/* msgvisitor *****************************************************************/
static void putmsg ( VALUE msg , const Descriptor * desc ,
upb_sink * sink , int depth , bool emit_defaults ,
bool is_json , bool open_msg ) ;
static void putmsg ( VALUE msg , const Descriptor * desc , upb_sink sink , int depth ,
bool emit_defaults , bool is_json , bool open_msg ) ;
static upb_selector_t getsel ( const upb_fielddef * f , upb_handlertype_t type ) {
upb_selector_t ret ;
@ -967,7 +917,7 @@ static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
return ret ;
}
static void putstr ( VALUE str , const upb_fielddef * f , upb_sink * sink ) {
static void putstr ( VALUE str , const upb_fielddef * f , upb_sink sink ) {
upb_sink subsink ;
if ( str = = Qnil ) return ;
@ -984,12 +934,12 @@ static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) {
upb_sink_startstr ( sink , getsel ( f , UPB_HANDLER_STARTSTR ) , RSTRING_LEN ( str ) ,
& subsink ) ;
upb_sink_putstring ( & subsink , getsel ( f , UPB_HANDLER_STRING ) , RSTRING_PTR ( str ) ,
upb_sink_putstring ( subsink , getsel ( f , UPB_HANDLER_STRING ) , RSTRING_PTR ( str ) ,
RSTRING_LEN ( str ) , NULL ) ;
upb_sink_endstr ( sink , getsel ( f , UPB_HANDLER_ENDSTR ) ) ;
}
static void putsubmsg ( VALUE submsg , const upb_fielddef * f , upb_sink * sink ,
static void putsubmsg ( VALUE submsg , const upb_fielddef * f , upb_sink sink ,
int depth , bool emit_defaults , bool is_json ) {
upb_sink subsink ;
VALUE descriptor ;
@ -1001,16 +951,17 @@ static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
subdesc = ruby_to_Descriptor ( descriptor ) ;
upb_sink_startsubmsg ( sink , getsel ( f , UPB_HANDLER_STARTSUBMSG ) , & subsink ) ;
putmsg ( submsg , subdesc , & subsink , depth + 1 , emit_defaults , is_json , true ) ;
putmsg ( submsg , subdesc , subsink , depth + 1 , emit_defaults , is_json , true ) ;
upb_sink_endsubmsg ( sink , getsel ( f , UPB_HANDLER_ENDSUBMSG ) ) ;
}
static void putary ( VALUE ary , const upb_fielddef * f , upb_sink * sink ,
int depth , bool emit_defaults , bool is_json ) {
static void putary ( VALUE ary , const upb_fielddef * f , upb_sink sink , int depth ,
bool emit_defaults , bool is_json ) {
upb_sink subsink ;
upb_fieldtype_t type = upb_fielddef_type ( f ) ;
upb_selector_t sel = 0 ;
int size ;
int i ;
if ( ary = = Qnil ) return ;
if ( ! emit_defaults & & NUM2INT ( RepeatedField_length ( ary ) ) = = 0 ) return ;
@ -1024,12 +975,12 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
sel = getsel ( f , upb_handlers_getprimitivehandlertype ( f ) ) ;
}
for ( int i = 0 ; i < size ; i + + ) {
for ( i = 0 ; i < size ; i + + ) {
void * memory = RepeatedField_index_native ( ary , i ) ;
switch ( type ) {
# define T(upbtypeconst, upbtype, ctype) \
case upbtypeconst : \
upb_sink_put # # upbtype ( & subsink , sel , * ( ( ctype * ) memory ) ) ; \
# define T(upbtypeconst, upbtype, ctype) \
case upbtypeconst : \
upb_sink_put # # upbtype ( subsink , sel , * ( ( ctype * ) memory ) ) ; \
break ;
T ( UPB_TYPE_FLOAT , float , float )
@ -1043,11 +994,10 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
case UPB_TYPE_STRING :
case UPB_TYPE_BYTES :
putstr ( * ( ( VALUE * ) memory ) , f , & subsink ) ;
putstr ( * ( ( VALUE * ) memory ) , f , subsink ) ;
break ;
case UPB_TYPE_MESSAGE :
putsubmsg ( * ( ( VALUE * ) memory ) , f , & subsink , depth ,
emit_defaults , is_json ) ;
putsubmsg ( * ( ( VALUE * ) memory ) , f , subsink , depth , emit_defaults , is_json ) ;
break ;
# undef T
@ -1057,19 +1007,16 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
upb_sink_endseq ( sink , getsel ( f , UPB_HANDLER_ENDSEQ ) ) ;
}
static void put_ruby_value ( VALUE value ,
const upb_fielddef * f ,
VALUE type_class ,
int depth ,
upb_sink * sink ,
bool emit_defaults ,
static void put_ruby_value ( VALUE value , const upb_fielddef * f , VALUE type_class ,
int depth , upb_sink sink , bool emit_defaults ,
bool is_json ) {
upb_selector_t sel = 0 ;
if ( depth > ENCODE_MAX_NESTING ) {
rb_raise ( rb_eRuntimeError ,
" Maximum recursion depth exceeded during encoding. " ) ;
}
upb_selector_t sel = 0 ;
if ( upb_fielddef_isprimitive ( f ) ) {
sel = getsel ( f , upb_handlers_getprimitivehandlertype ( f ) ) ;
}
@ -1112,8 +1059,8 @@ static void put_ruby_value(VALUE value,
}
}
static void putmap ( VALUE map , const upb_fielddef * f , upb_sink * sink ,
int depth , bool emit_defaults , bool is_json ) {
static void putmap ( VALUE map , const upb_fielddef * f , upb_sink sink , int depth ,
bool emit_defaults , bool is_json ) {
Map * self ;
upb_sink subsink ;
const upb_fielddef * key_field ;
@ -1137,17 +1084,17 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
upb_status status ;
upb_sink entry_sink ;
upb_sink_startsubmsg ( & subsink , getsel ( f , UPB_HANDLER_STARTSUBMSG ) ,
upb_sink_startsubmsg ( subsink , getsel ( f , UPB_HANDLER_STARTSUBMSG ) ,
& entry_sink ) ;
upb_sink_startmsg ( & entry_sink ) ;
upb_sink_startmsg ( entry_sink ) ;
put_ruby_value ( key , key_field , Qnil , depth + 1 , & entry_sink ,
emit_defaults , is_json ) ;
put_ruby_value ( key , key_field , Qnil , depth + 1 , entry_sink , emit_defaults ,
is_json ) ;
put_ruby_value ( value , value_field , self - > value_type_class , depth + 1 ,
& entry_sink , emit_defaults , is_json ) ;
entry_sink , emit_defaults , is_json ) ;
upb_sink_endmsg ( & entry_sink , & status ) ;
upb_sink_endsubmsg ( & subsink , getsel ( f , UPB_HANDLER_ENDSUBMSG ) ) ;
upb_sink_endmsg ( entry_sink , & status ) ;
upb_sink_endsubmsg ( subsink , getsel ( f , UPB_HANDLER_ENDSUBMSG ) ) ;
}
upb_sink_endseq ( sink , getsel ( f , UPB_HANDLER_ENDSEQ ) ) ;
@ -1156,8 +1103,8 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
static const upb_handlers * msgdef_json_serialize_handlers (
Descriptor * desc , bool preserve_proto_fieldnames ) ;
static void putjsonany ( VALUE msg_rb , const Descriptor * desc ,
upb_sink * sink , int depth , bool emit_defaults ) {
static void putjsonany ( VALUE msg_rb , const Descriptor * desc , upb_sink sink ,
int depth , bool emit_defaults ) {
upb_status status ;
MessageHeader * msg = NULL ;
const upb_fielddef * type_field = upb_msgdef_itof ( desc - > msgdef , UPB_ANY_TYPE ) ;
@ -1204,16 +1151,14 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc,
{
uint32_t value_offset ;
VALUE value_str_rb ;
const char * value_str ;
size_t value_len ;
value_offset = desc - > layout - > fields [ upb_fielddef_index ( value_field ) ] . offset ;
value_str_rb = DEREF ( Message_data ( msg ) , value_offset , VALUE ) ;
value_str = RSTRING_PTR ( value_str_rb ) ;
value_len = RSTRING_LEN ( value_str_rb ) ;
if ( value_len > 0 ) {
VALUE payload_desc_rb = get_def_obj ( payload_type ) ;
VALUE payload_desc_rb = get_msg def_obj ( generated_pool , payload_type ) ;
Descriptor * payload_desc = ruby_to_Descriptor ( payload_desc_rb ) ;
VALUE payload_class = Descriptor_msgclass ( payload_desc_rb ) ;
upb_sink subsink ;
@ -1231,8 +1176,8 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc,
subsink . handlers =
msgdef_json_serialize_handlers ( payload_desc , true ) ;
subsink . closure = sink - > closure ;
putmsg ( payload_msg_rb , payload_desc , & subsink , depth , emit_defaults , true ,
subsink . closure = sink . closure ;
putmsg ( payload_msg_rb , payload_desc , subsink , depth , emit_defaults , true ,
is_wellknown ) ;
}
}
@ -1242,7 +1187,7 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc,
static void putjsonlistvalue (
VALUE msg_rb , const Descriptor * desc ,
upb_sink * sink , int depth , bool emit_defaults ) {
upb_sink sink , int depth , bool emit_defaults ) {
upb_status status ;
upb_sink subsink ;
MessageHeader * msg = NULL ;
@ -1269,7 +1214,7 @@ static void putjsonlistvalue(
}
static void putmsg ( VALUE msg_rb , const Descriptor * desc ,
upb_sink * sink , int depth , bool emit_defaults ,
upb_sink sink , int depth , bool emit_defaults ,
bool is_json , bool open_msg ) {
MessageHeader * msg ;
upb_msg_field_iter i ;
@ -1360,20 +1305,19 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
} else {
upb_selector_t sel = getsel ( f , upb_handlers_getprimitivehandlertype ( f ) ) ;
# define T(upbtypeconst, upbtype, ctype, default_value) \
case upbtypeconst : { \
ctype value = DEREF ( msg , offset , ctype ) ; \
bool is_default = false ; \
if ( upb_fielddef_haspresence ( f ) ) { \
is_default = layout_has ( desc - > layout , Message_data ( msg ) , f ) = = Qfalse ; \
} else if ( upb_msgdef_syntax ( desc - > msgdef ) = = UPB_SYNTAX_PROTO3 ) { \
is_default = default_value = = value ; \
} \
if ( is_matching_oneof | | emit_defaults | | ! is_default ) { \
upb_sink_put # # upbtype ( sink , sel , value ) ; \
} \
} \
break ;
# define T(upbtypeconst, upbtype, ctype, default_value) \
case upbtypeconst : { \
ctype value = DEREF ( msg , offset , ctype ) ; \
bool is_default = false ; \
if ( upb_fielddef_haspresence ( f ) ) { \
is_default = layout_has ( desc - > layout , Message_data ( msg ) , f ) = = Qfalse ; \
} else if ( upb_msgdef_syntax ( desc - > msgdef ) = = UPB_SYNTAX_PROTO3 ) { \
is_default = default_value = = value ; \
} \
if ( is_matching_oneof | | emit_defaults | | ! is_default ) { \
upb_sink_put # # upbtype ( sink , sel , value ) ; \
} \
} break ;
switch ( upb_fielddef_type ( f ) ) {
T ( UPB_TYPE_FLOAT , float , float , 0.0 )
@ -1395,9 +1339,11 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
}
}
stringsink * unknown = msg - > unknown_fields ;
if ( unknown ! = NULL ) {
upb_sink_putunknown ( sink , unknown - > ptr , unknown - > len ) ;
{
stringsink * unknown = msg - > unknown_fields ;
if ( unknown ! = NULL ) {
upb_sink_putunknown ( sink , unknown - > ptr , unknown - > len ) ;
}
}
if ( open_msg ) {
@ -1405,33 +1351,6 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
}
}
static const upb_handlers * msgdef_pb_serialize_handlers ( Descriptor * desc ) {
if ( desc - > pb_serialize_handlers = = NULL ) {
desc - > pb_serialize_handlers =
upb_pb_encoder_newhandlers ( desc - > msgdef , & desc - > pb_serialize_handlers ) ;
}
return desc - > pb_serialize_handlers ;
}
static const upb_handlers * msgdef_json_serialize_handlers (
Descriptor * desc , bool preserve_proto_fieldnames ) {
if ( preserve_proto_fieldnames ) {
if ( desc - > json_serialize_handlers = = NULL ) {
desc - > json_serialize_handlers =
upb_json_printer_newhandlers (
desc - > msgdef , true , & desc - > json_serialize_handlers ) ;
}
return desc - > json_serialize_handlers ;
} else {
if ( desc - > json_serialize_handlers_preserve = = NULL ) {
desc - > json_serialize_handlers_preserve =
upb_json_printer_newhandlers (
desc - > msgdef , false , & desc - > json_serialize_handlers_preserve ) ;
}
return desc - > json_serialize_handlers_preserve ;
}
}
/*
* call - seq :
* MessageClass . encode ( msg ) = > bytes
@ -1454,8 +1373,8 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) {
upb_pb_encoder * encoder ;
VALUE ret ;
stackenv_init ( & se , " Error occurred during encoding: %s " ) ;
encoder = upb_pb_encoder_create ( & se . env , serialize_handlers , & sink . sink ) ;
stackenv_init ( & se , " Error occurred during encoding: % " PRIsVALUE ) ;
encoder = upb_pb_encoder_create ( se . arena , serialize_handlers , sink . sink ) ;
putmsg ( msg_rb , desc , upb_pb_encoder_input ( encoder ) , 0 , false , false , true ) ;
@ -1512,8 +1431,8 @@ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
stackenv se ;
VALUE ret ;
stackenv_init ( & se , " Error occurred during encoding: %s " ) ;
printer = upb_json_printer_create ( & se . env , serialize_handlers , & sink . sink ) ;
stackenv_init ( & se , " Error occurred during encoding: % " PRIsVALUE ) ;
printer = upb_json_printer_create ( se . arena , serialize_handlers , sink . sink ) ;
putmsg ( msg_rb , desc , upb_json_printer_input ( printer ) , 0 ,
RTEST ( emit_defaults ) , true , true ) ;
@ -1533,10 +1452,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
TypedData_Get_Struct ( msg_rb , MessageHeader , & Message_type , msg ) ;
stringsink * unknown = msg - > unknown_fields ;
if ( unknown ! = NULL ) {
stringsink_uninit ( unknown ) ;
msg - > unknown_fields = NULL ;
{
stringsink * unknown = msg - > unknown_fields ;
if ( unknown ! = NULL ) {
stringsink_uninit ( unknown ) ;
msg - > unknown_fields = NULL ;
}
}
for ( upb_msg_field_begin ( & it , desc - > msgdef ) ;
@ -1566,10 +1487,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
}
if ( is_map_field ( f ) ) {
VALUE map ;
Map_iter map_it ;
if ( ! upb_fielddef_issubmsg ( map_field_value ( f ) ) ) continue ;
VALUE map = DEREF ( msg , offset , VALUE ) ;
map = DEREF ( msg , offset , VALUE ) ;
if ( map = = Qnil ) continue ;
Map_iter map_it ;
for ( Map_begin ( map , & map_it ) ; ! Map_done ( & map_it ) ; Map_next ( & map_it ) ) {
VALUE submsg = Map_iter_value ( & map_it ) ;
VALUE descriptor = rb_ivar_get ( submsg , descriptor_instancevar_interned ) ;
@ -1578,9 +1501,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
}
} else if ( upb_fielddef_isseq ( f ) ) {
VALUE ary = DEREF ( msg , offset , VALUE ) ;
int size ;
int i ;
if ( ary = = Qnil ) continue ;
int size = NUM2INT ( RepeatedField_length ( ary ) ) ;
for ( int i = 0 ; i < size ; i + + ) {
size = NUM2INT ( RepeatedField_length ( ary ) ) ;
for ( i = 0 ; i < size ; i + + ) {
void * memory = RepeatedField_index_native ( ary , i ) ;
VALUE submsg = * ( ( VALUE * ) memory ) ;
VALUE descriptor = rb_ivar_get ( submsg , descriptor_instancevar_interned ) ;
@ -1589,9 +1515,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
}
} else {
VALUE submsg = DEREF ( msg , offset , VALUE ) ;
VALUE descriptor ;
const Descriptor * subdesc ;
if ( submsg = = Qnil ) continue ;
VALUE descriptor = rb_ivar_get ( submsg , descriptor_instancevar_interned ) ;
const Descriptor * subdesc = ruby_to_Descriptor ( descriptor ) ;
descriptor = rb_ivar_get ( submsg , descriptor_instancevar_interned ) ;
subdesc = ruby_to_Descriptor ( descriptor ) ;
discard_unknown ( submsg , subdesc ) ;
}
}