diff --git a/upb/message/BUILD b/upb/message/BUILD index 2640868573..05fa825232 100644 --- a/upb/message/BUILD +++ b/upb/message/BUILD @@ -35,6 +35,7 @@ cc_library( "//upb:base", "//upb:eps_copy_input_stream", "//upb:mem", + "//upb:message_types", "//upb:mini_table", "//upb:mini_table_internal", "//upb:port", diff --git a/upb/message/accessors.c b/upb/message/accessors.c index 25c0f9e5ef..70a60a0536 100644 --- a/upb/message/accessors.c +++ b/upb/message/accessors.c @@ -7,15 +7,15 @@ #include "upb/message/accessors.h" +#include + +#include "upb/mem/arena.h" #include "upb/message/array.h" -#include "upb/message/internal/array.h" #include "upb/message/map.h" #include "upb/message/message.h" #include "upb/mini_table/field.h" -#include "upb/wire/decode.h" +#include "upb/mini_table/message.h" #include "upb/wire/encode.h" -#include "upb/wire/eps_copy_input_stream.h" -#include "upb/wire/reader.h" // Must be last. #include "upb/port/def.inc" @@ -37,12 +37,10 @@ upb_MapInsertStatus upb_Message_InsertMapEntry(upb_Map* map, // hence assuming a zero default is valid. upb_MessageValue default_val; memset(&default_val, 0, sizeof(upb_MessageValue)); - upb_MessageValue map_entry_key; - upb_MessageValue map_entry_value; - _upb_Message_GetField(map_entry_message, map_entry_key_field, &default_val, - &map_entry_key); - _upb_Message_GetField(map_entry_message, map_entry_value_field, &default_val, - &map_entry_value); + upb_MessageValue map_entry_key = + upb_Message_GetField(map_entry_message, map_entry_key_field, default_val); + upb_MessageValue map_entry_value = upb_Message_GetField( + map_entry_message, map_entry_value_field, default_val); return upb_Map_Insert(map, map_entry_key, map_entry_value, arena); } diff --git a/upb/message/accessors.h b/upb/message/accessors.h index 3a23f2f75b..3a4d6dcc13 100644 --- a/upb/message/accessors.h +++ b/upb/message/accessors.h @@ -8,17 +8,29 @@ #ifndef UPB_MESSAGE_ACCESSORS_H_ #define UPB_MESSAGE_ACCESSORS_H_ +#include +#include +#include + #include "upb/base/descriptor_constants.h" +#include "upb/base/string_view.h" +#include "upb/mem/arena.h" #include "upb/message/array.h" #include "upb/message/internal/accessors.h" #include "upb/message/internal/array.h" #include "upb/message/internal/map.h" #include "upb/message/internal/message.h" +#include "upb/message/internal/types.h" #include "upb/message/map.h" +#include "upb/message/tagged_ptr.h" +#include "upb/message/types.h" #include "upb/mini_table/enum.h" +#include "upb/mini_table/extension.h" #include "upb/mini_table/field.h" // Must be last. +#include "upb/mini_table/internal/field.h" +#include "upb/mini_table/message.h" #include "upb/port/def.inc" #ifdef __cplusplus @@ -58,15 +70,45 @@ UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber( return _upb_Message_GetOneofCase(message, oneof_field); } +// NOTE: The default_val is only used for fields that support presence. +// For repeated/map fields, the resulting upb_Array*/upb_Map* can be NULL if a +// upb_Array/upb_Map has not been allocated yet. Array/map fields do not have +// presence, so this is semantically identical to a pointer to an empty +// array/map, and must be treated the same for all semantic purposes. +UPB_INLINE upb_MessageValue +upb_Message_GetField(const upb_Message* msg, const upb_MiniTableField* field, + upb_MessageValue default_val) { + upb_MessageValue ret; + if (upb_MiniTableField_IsExtension(field)) { + _upb_Message_GetExtensionField(msg, (upb_MiniTableExtension*)field, + &default_val, &ret); + } else { + _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); + } + return ret; +} + +UPB_INLINE bool upb_Message_SetField(upb_Message* msg, + const upb_MiniTableField* field, + upb_MessageValue val, upb_Arena* a) { + if (upb_MiniTableField_IsExtension(field)) { + const upb_MiniTableExtension* ext = (const upb_MiniTableExtension*)field; + return _upb_Message_SetExtensionField(msg, ext, &val, a); + } else { + _upb_Message_SetNonExtensionField(msg, field, &val); + return true; + } +} + UPB_API_INLINE bool upb_Message_GetBool(const upb_Message* msg, const upb_MiniTableField* field, bool default_val) { UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Bool); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - bool ret; - _upb_Message_GetField(msg, field, &default_val, &ret); - return ret; + upb_MessageValue def; + def.bool_val = default_val; + return upb_Message_GetField(msg, field, def).bool_val; } UPB_API_INLINE bool upb_Message_SetBool(upb_Message* msg, @@ -75,7 +117,9 @@ UPB_API_INLINE bool upb_Message_SetBool(upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Bool); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - return _upb_Message_SetField(msg, field, &value, a); + upb_MessageValue val; + val.bool_val = value; + return upb_Message_SetField(msg, field, val, a); } UPB_API_INLINE int32_t upb_Message_GetInt32(const upb_Message* msg, @@ -85,9 +129,10 @@ UPB_API_INLINE int32_t upb_Message_GetInt32(const upb_Message* msg, upb_MiniTableField_CType(field) == kUpb_CType_Enum); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - int32_t ret; - _upb_Message_GetField(msg, field, &default_val, &ret); - return ret; + + upb_MessageValue def; + def.int32_val = default_val; + return upb_Message_GetField(msg, field, def).int32_val; } UPB_API_INLINE bool upb_Message_SetInt32(upb_Message* msg, @@ -97,7 +142,9 @@ UPB_API_INLINE bool upb_Message_SetInt32(upb_Message* msg, upb_MiniTableField_CType(field) == kUpb_CType_Enum); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - return _upb_Message_SetField(msg, field, &value, a); + upb_MessageValue val; + val.int32_val = value; + return upb_Message_SetField(msg, field, val, a); } UPB_API_INLINE uint32_t upb_Message_GetUInt32(const upb_Message* msg, @@ -106,9 +153,10 @@ UPB_API_INLINE uint32_t upb_Message_GetUInt32(const upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt32); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - uint32_t ret; - _upb_Message_GetField(msg, field, &default_val, &ret); - return ret; + + upb_MessageValue def; + def.uint32_val = default_val; + return upb_Message_GetField(msg, field, def).uint32_val; } UPB_API_INLINE bool upb_Message_SetUInt32(upb_Message* msg, @@ -117,7 +165,9 @@ UPB_API_INLINE bool upb_Message_SetUInt32(upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt32); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - return _upb_Message_SetField(msg, field, &value, a); + upb_MessageValue val; + val.uint32_val = value; + return upb_Message_SetField(msg, field, val, a); } UPB_API_INLINE void upb_Message_SetClosedEnum( @@ -133,13 +183,14 @@ UPB_API_INLINE void upb_Message_SetClosedEnum( UPB_API_INLINE int64_t upb_Message_GetInt64(const upb_Message* msg, const upb_MiniTableField* field, - uint64_t default_val) { + int64_t default_val) { UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int64); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - int64_t ret; - _upb_Message_GetField(msg, field, &default_val, &ret); - return ret; + + upb_MessageValue def; + def.int64_val = default_val; + return upb_Message_GetField(msg, field, def).int64_val; } UPB_API_INLINE bool upb_Message_SetInt64(upb_Message* msg, @@ -148,7 +199,9 @@ UPB_API_INLINE bool upb_Message_SetInt64(upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int64); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - return _upb_Message_SetField(msg, field, &value, a); + upb_MessageValue val; + val.int64_val = value; + return upb_Message_SetField(msg, field, val, a); } UPB_API_INLINE uint64_t upb_Message_GetUInt64(const upb_Message* msg, @@ -157,9 +210,10 @@ UPB_API_INLINE uint64_t upb_Message_GetUInt64(const upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt64); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - uint64_t ret; - _upb_Message_GetField(msg, field, &default_val, &ret); - return ret; + + upb_MessageValue def; + def.uint64_val = default_val; + return upb_Message_GetField(msg, field, def).uint64_val; } UPB_API_INLINE bool upb_Message_SetUInt64(upb_Message* msg, @@ -168,7 +222,9 @@ UPB_API_INLINE bool upb_Message_SetUInt64(upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt64); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - return _upb_Message_SetField(msg, field, &value, a); + upb_MessageValue val; + val.uint64_val = value; + return upb_Message_SetField(msg, field, val, a); } UPB_API_INLINE float upb_Message_GetFloat(const upb_Message* msg, @@ -177,9 +233,10 @@ UPB_API_INLINE float upb_Message_GetFloat(const upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Float); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - float ret; - _upb_Message_GetField(msg, field, &default_val, &ret); - return ret; + + upb_MessageValue def; + def.float_val = default_val; + return upb_Message_GetField(msg, field, def).float_val; } UPB_API_INLINE bool upb_Message_SetFloat(upb_Message* msg, @@ -188,7 +245,9 @@ UPB_API_INLINE bool upb_Message_SetFloat(upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Float); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - return _upb_Message_SetField(msg, field, &value, a); + upb_MessageValue val; + val.float_val = value; + return upb_Message_SetField(msg, field, val, a); } UPB_API_INLINE double upb_Message_GetDouble(const upb_Message* msg, @@ -197,9 +256,10 @@ UPB_API_INLINE double upb_Message_GetDouble(const upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Double); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - double ret; - _upb_Message_GetField(msg, field, &default_val, &ret); - return ret; + + upb_MessageValue def; + def.double_val = default_val; + return upb_Message_GetField(msg, field, def).double_val; } UPB_API_INLINE bool upb_Message_SetDouble(upb_Message* msg, @@ -208,19 +268,22 @@ UPB_API_INLINE bool upb_Message_SetDouble(upb_Message* msg, UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Double); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - return _upb_Message_SetField(msg, field, &value, a); + upb_MessageValue val; + val.double_val = value; + return upb_Message_SetField(msg, field, val, a); } UPB_API_INLINE upb_StringView upb_Message_GetString(const upb_Message* msg, const upb_MiniTableField* field, - upb_StringView def_val) { + upb_StringView default_val) { UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_String || upb_MiniTableField_CType(field) == kUpb_CType_Bytes); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_StringView); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - upb_StringView ret; - _upb_Message_GetField(msg, field, &def_val, &ret); - return ret; + + upb_MessageValue def; + def.str_val = default_val; + return upb_Message_GetField(msg, field, def).str_val; } UPB_API_INLINE bool upb_Message_SetString(upb_Message* msg, @@ -230,7 +293,9 @@ UPB_API_INLINE bool upb_Message_SetString(upb_Message* msg, upb_MiniTableField_CType(field) == kUpb_CType_Bytes); UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_StringView); UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); - return _upb_Message_SetField(msg, field, &value, a); + upb_MessageValue val; + val.str_val = value; + return upb_Message_SetField(msg, field, val, a); } UPB_API_INLINE upb_TaggedMessagePtr upb_Message_GetTaggedMessagePtr( @@ -316,7 +381,9 @@ UPB_API_INLINE upb_Array* upb_Message_GetOrCreateMutableArray( array = _upb_Array_New(arena, 4, _upb_MiniTable_ElementSizeLg2(field)); // Check again due to: https://godbolt.org/z/7WfaoKG1r _upb_MiniTableField_CheckIsArray(field); - _upb_Message_SetField(msg, field, &array, arena); + upb_MessageValue val; + val.array_val = array; + upb_Message_SetField(msg, field, val, arena); } return array; } diff --git a/upb/message/internal/accessors.h b/upb/message/internal/accessors.h index aa39009cd0..fcf4f90c3c 100644 --- a/upb/message/internal/accessors.h +++ b/upb/message/internal/accessors.h @@ -15,6 +15,7 @@ #include "upb/base/descriptor_constants.h" #include "upb/base/string_view.h" #include "upb/mem/arena.h" +#include "upb/message/array.h" #include "upb/message/internal/extension.h" #include "upb/message/internal/map.h" #include "upb/message/internal/message.h" @@ -214,7 +215,7 @@ _upb_MiniTable_ElementSizeLg2(const upb_MiniTableField* field) { // UPB_ASSUME(field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bool); // UPB_ASSUME(!upb_MiniTableField_IsRepeatedOrMap(field)); // UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte); -// _upb_Message_SetField(msg, field, &value, a); +// upb_Message_SetField(msg, field, &value, a); // } // // As a result, we can use these universal getters/setters for *all* message @@ -269,15 +270,31 @@ UPB_INLINE void _upb_Message_GetExtensionField( } } -UPB_INLINE void _upb_Message_GetField(const upb_Message* msg, - const upb_MiniTableField* field, - const void* default_val, void* val) { +// Gets a mutable Array, Map or Message field. +// NOTE: For repeated/map fields, the resulting upb_Array*/upb_Map* can +// be NULL if a upb_Array/upb_Map has not been allocated yet. Array/map +// fields do not have presence, so this is semantically identical to a +// pointer to an empty array/map, and must be treated the same for all +// semantic purposes. +// +// For message fields, the pointer is guaranteed to be NULL iff the field +// is unset (as message fields do have presence). +UPB_INLINE upb_MutableMessageValue _upb_Message_GetMutableField( + const upb_Message* msg, const upb_MiniTableField* field) { + UPB_ASSUME(upb_MiniTableField_IsRepeatedOrMap(field) || + upb_MiniTableField_IsSubMessage(field)); + + upb_MutableMessageValue default_val; + default_val.msg = NULL; + + upb_MutableMessageValue ret; if (upb_MiniTableField_IsExtension(field)) { _upb_Message_GetExtensionField(msg, (upb_MiniTableExtension*)field, - default_val, val); + &default_val, &ret); } else { - _upb_Message_GetNonExtensionField(msg, field, default_val, val); + _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); } + return ret; } UPB_INLINE void _upb_Message_SetNonExtensionField( @@ -299,18 +316,6 @@ UPB_INLINE bool _upb_Message_SetExtensionField( return true; } -UPB_INLINE bool _upb_Message_SetField(upb_Message* msg, - const upb_MiniTableField* field, - const void* val, upb_Arena* a) { - if (upb_MiniTableField_IsExtension(field)) { - const upb_MiniTableExtension* ext = (const upb_MiniTableExtension*)field; - return _upb_Message_SetExtensionField(msg, ext, val, a); - } else { - _upb_Message_SetNonExtensionField(msg, field, val); - return true; - } -} - UPB_INLINE void _upb_Message_ClearExtensionField( upb_Message* msg, const upb_MiniTableExtension* ext_l) { upb_Message_Internal* in = upb_Message_Getinternal(msg); diff --git a/upb/reflection/message.c b/upb/reflection/message.c index dc014ae11c..2d41a95ea5 100644 --- a/upb/reflection/message.c +++ b/upb/reflection/message.c @@ -47,9 +47,7 @@ const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* msg, upb_MessageValue upb_Message_GetFieldByDef(const upb_Message* msg, const upb_FieldDef* f) { upb_MessageValue default_val = upb_FieldDef_Default(f); - upb_MessageValue ret; - _upb_Message_GetField(msg, upb_FieldDef_MiniTable(f), &default_val, &ret); - return ret; + return upb_Message_GetField(msg, upb_FieldDef_MiniTable(f), default_val); } upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg, @@ -93,7 +91,7 @@ make: bool upb_Message_SetFieldByDef(upb_Message* msg, const upb_FieldDef* f, upb_MessageValue val, upb_Arena* a) { - return _upb_Message_SetField(msg, upb_FieldDef_MiniTable(f), &val, a); + return upb_Message_SetField(msg, upb_FieldDef_MiniTable(f), val, a); } void upb_Message_ClearFieldByDef(upb_Message* msg, const upb_FieldDef* f) {