Skip to content

Commit

Permalink
Add upb_Message_ClearOneof
Browse files Browse the repository at this point in the history
upb users currently need to manually fetch a oneof field in order to clear it.
In this CL, we add a convenience method to do that in one fell swoop.

PiperOrigin-RevId: 629782904
  • Loading branch information
honglooker authored and copybara-github committed May 1, 2024
1 parent c4bf83b commit 7a09c45
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
8 changes: 3 additions & 5 deletions upb/message/accessors.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,9 @@ UPB_API_INLINE bool upb_Message_SetExtension(upb_Message* msg,
const upb_MiniTableExtension* e,
const void* val, upb_Arena* a);

UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber(
const upb_Message* message, const upb_MiniTableField* oneof_field) {
UPB_ASSUME(upb_MiniTableField_IsInOneof(oneof_field));
return UPB_PRIVATE(_upb_Message_GetOneofCase)(message, oneof_field);
}
UPB_API_INLINE void upb_Message_ClearOneof(upb_Message* msg,
const upb_MiniTable* m,
const upb_MiniTableField* f);

// 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
Expand Down
23 changes: 23 additions & 0 deletions upb/message/accessors_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -477,5 +477,28 @@ TEST(GeneratedCode, EnumClosedCheck) {
EXPECT_TRUE(upb_MiniTableField_IsClosedEnum(closedEnumField));
upb_Arena_Free(arena);
}
TEST(GeneratedCode, OneofClear) {
upb_Arena* arena = upb_Arena_New();

protobuf_test_messages_proto2_TestAllTypesProto2* msg =
protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);

const upb_MiniTable* table =
&protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init;

// oneof_uint32
const upb_MiniTableField* oneofField =
upb_MiniTable_FindFieldByNumber(table, 111);
EXPECT_TRUE(upb_MiniTableField_IsInOneof(oneofField));
protobuf_test_messages_proto2_TestAllTypesProto2_set_oneof_uint32(msg, 522);
EXPECT_TRUE(
protobuf_test_messages_proto2_TestAllTypesProto2_has_oneof_uint32(msg));

upb_Message_ClearOneof((upb_Message*)msg, table, oneofField);
EXPECT_FALSE(
protobuf_test_messages_proto2_TestAllTypesProto2_has_oneof_uint32(msg));

upb_Arena_Free(arena);
}

} // namespace
21 changes: 21 additions & 0 deletions upb/message/internal/accessors.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,27 @@ UPB_API_INLINE void upb_Message_ClearExtension(
}
}

UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber(
const struct upb_Message* message, const upb_MiniTableField* oneof_field) {
UPB_ASSUME(upb_MiniTableField_IsInOneof(oneof_field));
return UPB_PRIVATE(_upb_Message_GetOneofCase)(message, oneof_field);
}

UPB_API_INLINE void upb_Message_ClearOneof(struct upb_Message* msg,
const upb_MiniTable* m,
const upb_MiniTableField* f) {
UPB_ASSERT(!upb_Message_IsFrozen(msg));
uint32_t field_number = upb_Message_WhichOneofFieldNumber(msg, f);
if (field_number == 0) {
// No field in the oneof is set.
return;
}

const upb_MiniTableField* field =
upb_MiniTable_FindFieldByNumber(m, field_number);
upb_Message_ClearBaseField(msg, field);
}

UPB_INLINE void _upb_Message_AssertMapIsUntagged(
const struct upb_Message* msg, const upb_MiniTableField* field) {
UPB_UNUSED(msg);
Expand Down

0 comments on commit 7a09c45

Please sign in to comment.