Skip to content
This repository was archived by the owner on Dec 9, 2025. It is now read-only.

Commit 067dfea

Browse files
Implement UPB OneOf MiniTable apis.
PiperOrigin-RevId: 506691706
1 parent f775d49 commit 067dfea

File tree

4 files changed

+136
-1
lines changed

4 files changed

+136
-1
lines changed

upb/mini_table/common.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,35 @@ upb_FieldType upb_MiniTableField_Type(const upb_MiniTableField* field) {
9494
}
9595
return field->descriptortype;
9696
}
97+
98+
static bool upb_MiniTable_Is_Oneof(const upb_MiniTableField* f) {
99+
return f->presence < 0;
100+
}
101+
102+
const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m,
103+
const upb_MiniTableField* f) {
104+
if (UPB_UNLIKELY(!upb_MiniTable_Is_Oneof(f))) {
105+
return NULL;
106+
}
107+
const upb_MiniTableField* ptr = &m->fields[0];
108+
const upb_MiniTableField* end = &m->fields[m->field_count];
109+
while (++ptr < end) {
110+
if (ptr->presence == (*f).presence) {
111+
return ptr;
112+
}
113+
}
114+
return NULL;
115+
}
116+
117+
bool upb_MiniTable_NextOneofField(const upb_MiniTable* m,
118+
const upb_MiniTableField** f) {
119+
const upb_MiniTableField* ptr = *f;
120+
const upb_MiniTableField* end = &m->fields[m->field_count];
121+
while (++ptr < end) {
122+
if (ptr->presence == (*f)->presence) {
123+
*f = ptr;
124+
return true;
125+
}
126+
}
127+
return false;
128+
}

upb/mini_table/common.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,26 @@ UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable(
117117
return mini_table->subs[field->submsg_index].subenum;
118118
}
119119

120+
// If this field is in a oneof, returns the first field in the oneof.
121+
//
122+
// Otherwise returns NULL.
123+
//
124+
// Usage:
125+
// const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f);
126+
// do {
127+
// ..
128+
// } while (upb_MiniTable_NextOneofField(m, &field);
129+
//
130+
const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m,
131+
const upb_MiniTableField* f);
132+
133+
// Returns the next field in the oneof. If this is the last field in the
134+
// oneof, returns NULL. The ordering of fields in the oneof is not
135+
// guaranteed.
136+
// REQUIRES: |iter| is and iterator.
137+
bool upb_MiniTable_NextOneofField(const upb_MiniTable* m,
138+
const upb_MiniTableField** f);
139+
120140
#ifdef __cplusplus
121141
} /* extern "C" */
122142
#endif

upb/test/BUILD

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ cc_test(
159159

160160
cc_test(
161161
name = "test_generated_code",
162-
srcs = ["test_generated_code.cc"],
162+
srcs = [
163+
"test_generated_code.cc",
164+
],
163165
deps = [
164166
":empty_upb_proto_reflection",
165167
":test_messages_proto2_upb_proto",
@@ -170,3 +172,20 @@ cc_test(
170172
"@com_google_googletest//:gtest_main",
171173
],
172174
)
175+
176+
cc_test(
177+
name = "test_mini_table_oneof",
178+
srcs = [
179+
"test_mini_table_oneof.cc",
180+
],
181+
deps = [
182+
":empty_upb_proto_reflection",
183+
":test_messages_proto2_upb_proto",
184+
":test_messages_proto3_upb_proto",
185+
":test_upb_proto",
186+
"//:upb",
187+
"//:mini_table_internal",
188+
"//:port",
189+
"@com_google_googletest//:gtest_main",
190+
],
191+
)

upb/test/test_mini_table_oneof.cc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2009-2021, Google LLC
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of Google LLC nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
28+
#include "gtest/gtest.h"
29+
#include "google/protobuf/test_messages_proto2.upb.h"
30+
#include "google/protobuf/test_messages_proto3.upb.h"
31+
#include "upb/mini_table/common.h"
32+
#include "upb/test/test.upb.h"
33+
#include "upb/upb.hpp"
34+
35+
// Must be last.
36+
#include "upb/port/def.inc"
37+
38+
TEST(MiniTableOneofTest, OneOfIteratorProto2) {
39+
constexpr int oneof_first_field_number = 111;
40+
constexpr int oneof_test_field_number = 116;
41+
42+
const upb_MiniTable* google_protobuf_table =
43+
&protobuf_test_messages_proto2_TestAllTypesProto2_msg_init;
44+
const upb_MiniTableField* field =
45+
upb_MiniTable_FindFieldByNumber(google_protobuf_table, oneof_test_field_number);
46+
ASSERT_TRUE(field != nullptr);
47+
const upb_MiniTableField* ptr = upb_MiniTable_GetOneof(google_protobuf_table, field);
48+
int field_num = oneof_first_field_number;
49+
do {
50+
EXPECT_EQ(ptr->number, field_num++);
51+
} while (upb_MiniTable_NextOneofField(google_protobuf_table, &ptr));
52+
}
53+
54+
TEST(MiniTableOneofTest, InitialFieldNotOneOf) {
55+
constexpr int test_field_number = 1; // optional int that is not a oneof
56+
const upb_MiniTable* google_protobuf_table =
57+
&protobuf_test_messages_proto2_TestAllTypesProto2_msg_init;
58+
const upb_MiniTableField* field =
59+
upb_MiniTable_FindFieldByNumber(google_protobuf_table, test_field_number);
60+
ASSERT_TRUE(field != nullptr);
61+
const upb_MiniTableField* first_field =
62+
upb_MiniTable_GetOneof(google_protobuf_table, field);
63+
EXPECT_EQ(first_field, nullptr);
64+
}

0 commit comments

Comments
 (0)