diff --git a/upb/mini_table.h b/upb/mini_table.h index 20a7146979..9e5eab27a6 100644 --- a/upb/mini_table.h +++ b/upb/mini_table.h @@ -45,6 +45,7 @@ UPB_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( return mini_table->subs[field->submsg_index].submsg; } +// Validates enum value against range defined by enum mini table. UPB_INLINE bool upb_MiniTable_Enum_CheckValue(const upb_MiniTable_Enum* e, int32_t val) { uint32_t uval = (uint32_t)val; diff --git a/upb/mini_table_accessors.c b/upb/mini_table_accessors.c index 1db65d8be0..4c892e0e9e 100644 --- a/upb/mini_table_accessors.c +++ b/upb/mini_table_accessors.c @@ -172,21 +172,6 @@ static const char* decode_tag(const char* ptr, uint32_t* val) { } } -typedef enum { - kUpb_FindUnknown_Ok, - kUpb_FindUnknown_NotPresent, - kUpb_FindUnknown_ParseError, -} upb_FindUnknown_Status; - -typedef struct { - upb_FindUnknown_Status status; - const char* ptr; - size_t len; -} find_unknown_ret; - -static find_unknown_ret UnknownFieldSet_FindField(const upb_Message* msg, - int field_number); - upb_GetExtension_Status upb_MiniTable_GetOrPromoteExtension( upb_Message* msg, const upb_MiniTable_Extension* ext_table, int decode_options, upb_Arena* arena, @@ -199,7 +184,7 @@ upb_GetExtension_Status upb_MiniTable_GetOrPromoteExtension( // Check unknown fields, if available promote. int field_number = ext_table->field.number; - find_unknown_ret result = UnknownFieldSet_FindField(msg, field_number); + upb_FindUnknownRet result = upb_MiniTable_FindUnknown(msg, field_number); if (result.status != kUpb_FindUnknown_Ok) { UPB_ASSERT(result.status != kUpb_GetExtension_ParseError); return kUpb_GetExtension_NotPresent; @@ -258,7 +243,7 @@ upb_GetExtensionAsBytes_Status upb_MiniTable_GetExtensionAsBytes( return kUpb_GetExtensionAsBytes_Ok; } int field_number = ext_table->field.number; - find_unknown_ret result = UnknownFieldSet_FindField(msg, field_number); + upb_FindUnknownRet result = upb_MiniTable_FindUnknown(msg, field_number); if (result.status != kUpb_FindUnknown_Ok) { UPB_ASSERT(result.status != kUpb_GetExtension_ParseError); return kUpb_GetExtensionAsBytes_NotPresent; @@ -329,10 +314,10 @@ enum { kUpb_MessageSet_MessageTag = (3 << 3) | kUpb_WireType_Delimited, }; -static find_unknown_ret UnknownFieldSet_FindField(const upb_Message* msg, - int field_number) { +upb_FindUnknownRet upb_MiniTable_FindUnknown(const upb_Message* msg, + uint32_t field_number) { size_t size; - find_unknown_ret ret; + upb_FindUnknownRet ret; const char* ptr = upb_Message_GetUnknown(msg, &size); if (size == 0) { diff --git a/upb/mini_table_accessors.h b/upb/mini_table_accessors.h index 750f66f207..ccc3dc5360 100644 --- a/upb/mini_table_accessors.h +++ b/upb/mini_table_accessors.h @@ -262,6 +262,23 @@ upb_GetExtensionAsBytes_Status upb_MiniTable_GetExtensionAsBytes( int encode_options, upb_Arena* arena, const char** extension_data, size_t* len); +typedef enum { + kUpb_FindUnknown_Ok, + kUpb_FindUnknown_NotPresent, + kUpb_FindUnknown_ParseError, +} upb_FindUnknown_Status; + +typedef struct { + upb_FindUnknown_Status status; + // Start of unknown field data in message arena. + const char* ptr; + // Size of unknown field data. + size_t len; +} upb_FindUnknownRet; + +upb_FindUnknownRet upb_MiniTable_FindUnknown(const upb_Message* msg, + uint32_t field_number); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/upb/mini_table_accessors_test.cc b/upb/mini_table_accessors_test.cc index d79374d32e..7f66a94ba7 100644 --- a/upb/mini_table_accessors_test.cc +++ b/upb/mini_table_accessors_test.cc @@ -376,6 +376,38 @@ TEST(GeneratedCode, GetMutableMessage) { upb_Arena_Free(arena); } +TEST(GeneratedCode, FindUnknown) { + upb_Arena* arena = upb_Arena_New(); + upb_test_ModelWithExtensions* msg = upb_test_ModelWithExtensions_new(arena); + upb_test_ModelWithExtensions_set_random_int32(msg, 10); + upb_test_ModelWithExtensions_set_random_name( + msg, upb_StringView_FromString("Hello")); + + upb_test_ModelExtension1* extension1 = upb_test_ModelExtension1_new(arena); + upb_test_ModelExtension1_set_str(extension1, + upb_StringView_FromString("World")); + + upb_test_ModelExtension1_set_model_ext(msg, extension1, arena); + + size_t serialized_size; + char* serialized = + upb_test_ModelWithExtensions_serialize(msg, arena, &serialized_size); + + upb_test_EmptyMessageWithExtensions* base_msg = + upb_test_EmptyMessageWithExtensions_parse(serialized, serialized_size, + arena); + + upb_FindUnknownRet result = upb_MiniTable_FindUnknown( + base_msg, upb_test_ModelExtension1_model_ext_ext.field.number); + EXPECT_EQ(kUpb_FindUnknown_Ok, result.status); + + result = upb_MiniTable_FindUnknown( + base_msg, upb_test_ModelExtension2_model_ext_ext.field.number); + EXPECT_EQ(kUpb_FindUnknown_NotPresent, result.status); + + upb_Arena_Free(arena); +} + TEST(GeneratedCode, Extensions) { upb_Arena* arena = upb_Arena_New(); upb_test_ModelWithExtensions* msg = upb_test_ModelWithExtensions_new(arena);