@ -517,7 +517,8 @@ void create_layout(Descriptor* desc) {
! upb_msg_field_done ( & it ) ;
upb_msg_field_next ( & it ) ) {
const upb_fielddef * field = upb_msg_iter_field ( & it ) ;
if ( upb_fielddef_haspresence ( field ) ) {
if ( upb_fielddef_haspresence ( field ) & &
! upb_fielddef_containingoneof ( field ) ) {
layout - > fields [ upb_fielddef_index ( field ) ] . hasbit = hasbit + + ;
} else {
layout - > fields [ upb_fielddef_index ( field ) ] . hasbit =
@ -724,11 +725,8 @@ static void slot_clear_hasbit(MessageLayout* layout,
static bool slot_is_hasbit_set ( MessageLayout * layout ,
const void * storage ,
const upb_fielddef * field ) {
assert ( field_contains_hasbit ( layout , field ) ) ;
size_t hasbit = layout - > fields [ upb_fielddef_index ( field ) ] . hasbit ;
if ( hasbit = = MESSAGE_FIELD_NO_HASBIT ) {
return false ;
}
return DEREF_OFFSET (
( uint8_t * ) storage , hasbit / 8 , char ) & ( 1 < < ( hasbit % 8 ) ) ;
}
@ -736,8 +734,14 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
VALUE layout_has ( MessageLayout * layout ,
const void * storage ,
const upb_fielddef * field ) {
assert ( field_contains_hasbit ( layout , field ) ) ;
return slot_is_hasbit_set ( layout , storage , field ) ? Qtrue : Qfalse ;
assert ( upb_fielddef_haspresence ( field ) ) ;
const upb_oneofdef * oneof = upb_fielddef_containingoneof ( field ) ;
if ( oneof ) {
uint32_t oneof_case = slot_read_oneof_case ( layout , storage , oneof ) ;
return oneof_case = = upb_fielddef_number ( field ) ;
} else {
return slot_is_hasbit_set ( layout , storage , field ) ? Qtrue : Qfalse ;
}
}
void layout_clear ( MessageLayout * layout ,
@ -953,7 +957,16 @@ void layout_set(MessageLayout* layout,
if ( layout - > fields [ upb_fielddef_index ( field ) ] . hasbit ! =
MESSAGE_FIELD_NO_HASBIT ) {
slot_set_hasbit ( layout , storage , field ) ;
if ( val = = Qnil ) {
// No other field type has a hasbit and allows nil assignment.
if ( upb_fielddef_type ( field ) ! = UPB_TYPE_MESSAGE ) {
fprintf ( stderr , " field: %s \n " , upb_fielddef_fullname ( field ) ) ;
}
assert ( upb_fielddef_type ( field ) = = UPB_TYPE_MESSAGE ) ;
slot_clear_hasbit ( layout , storage , field ) ;
} else {
slot_set_hasbit ( layout , storage , field ) ;
}
}
}
@ -1095,9 +1108,16 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
return Qfalse ;
}
} else {
if ( slot_is_hasbit_set ( layout , msg1 , field ) ! =
slot_is_hasbit_set ( layout , msg2 , field ) | |
! native_slot_eq ( upb_fielddef_type ( field ) ,
if ( field_contains_hasbit ( layout , field ) & &
slot_is_hasbit_set ( layout , msg1 , field ) ! =
slot_is_hasbit_set ( layout , msg2 , field ) ) {
// TODO(haberman): I don't think we should actually care about hasbits
// here: an unset default should be able to equal a set default. But we
// can address this later (will also have to make sure defaults are
// being properly set when hasbit is clear).
return Qfalse ;
}
if ( ! native_slot_eq ( upb_fielddef_type ( field ) ,
field_type_class ( layout , field ) , msg1_memory ,
msg2_memory ) ) {
return Qfalse ;