Skip to content

Commit e712d27

Browse files
adazhcopybara-github
authored andcommitted
Add upb_Message_NextSerializableField and unify field presence checks.
PiperOrigin-RevId: 968809631
1 parent 718a3e5 commit e712d27

5 files changed

Lines changed: 376 additions & 34 deletions

File tree

upb/message/internal/accessors.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,44 @@ upb_Message_GetOrCreateMutableMessage(struct upb_Message* msg,
547547
return sub_message;
548548
}
549549

550+
UPB_INLINE bool UPB_PRIVATE(_upb_Message_FieldIsSet)(
551+
const struct upb_Message* msg, const upb_MiniTableField* f) {
552+
if (f->presence == 0) {
553+
// Proto3 presence or map/array.
554+
const void* mem = UPB_PTR_AT(msg, f->UPB_PRIVATE(offset), void);
555+
switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) {
556+
case kUpb_FieldRep_1Byte: {
557+
char ch;
558+
memcpy(&ch, mem, 1);
559+
return ch != 0;
560+
}
561+
case kUpb_FieldRep_4Byte: {
562+
uint32_t u32;
563+
memcpy(&u32, mem, 4);
564+
return u32 != 0;
565+
}
566+
case kUpb_FieldRep_8Byte: {
567+
uint64_t u64;
568+
memcpy(&u64, mem, 8);
569+
return u64 != 0;
570+
}
571+
case kUpb_FieldRep_StringView: {
572+
const upb_StringView* str = (const upb_StringView*)mem;
573+
return str->size != 0;
574+
}
575+
default:
576+
UPB_UNREACHABLE();
577+
}
578+
} else if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
579+
// Proto2 presence: hasbit.
580+
return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, f);
581+
} else {
582+
// Field is in a oneof.
583+
return UPB_PRIVATE(_upb_Message_GetOneofCase)(msg, f) ==
584+
upb_MiniTableField_Number(f);
585+
}
586+
}
587+
550588
UPB_API_INLINE upb_StringView
551589
upb_Message_GetString(const struct upb_Message* msg,
552590
const upb_MiniTableField* f, upb_StringView default_val) {

upb/message/message.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,22 @@ void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) {
257257
}
258258
}
259259
}
260+
261+
bool upb_Message_NextSerializableField(const upb_Message* msg,
262+
const upb_MiniTable* mt,
263+
const upb_MiniTableField** f,
264+
uintptr_t* iter) {
265+
const size_t field_count = upb_MiniTable_FieldCount(mt);
266+
uintptr_t i = *iter;
267+
while (i < field_count) {
268+
const upb_MiniTableField* field = upb_MiniTable_GetFieldByIndex(mt, i);
269+
if (UPB_PRIVATE(_upb_Message_FieldIsSet)(msg, field)) {
270+
*f = field;
271+
*iter = i + 1;
272+
return true;
273+
}
274+
i++;
275+
}
276+
*iter = i;
277+
return false;
278+
}

upb/message/message.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "upb/message/internal/message.h"
2222
#include "upb/message/internal/types.h"
2323
#include "upb/mini_table/extension.h"
24+
#include "upb/mini_table/field.h"
2425
#include "upb/mini_table/message.h"
2526

2627
// Must be last.
@@ -83,6 +84,29 @@ UPB_INLINE bool UPB_PRIVATE(_upb_Message_NextExtensionReverse)(
8384
const struct upb_Message* msg, const upb_MiniTableExtension** out_e,
8485
upb_MessageValue* out_v, uintptr_t* iter);
8586

87+
#define kUpb_Message_SerializableFieldBegin 0
88+
89+
// Iterates over all fields in the message that are set/present.
90+
//
91+
// NOTE: Unset/NULL repeated fields and maps are not considered set and will be
92+
// ignored. However, allocated repeated fields and maps (non-NULL pointer) with
93+
// zero elements are considered set/present and will be returned by this
94+
// iterator. Callers that need to skip empty collections should check their
95+
// sizes explicitly.
96+
//
97+
// To start iterating, set `iter = kUpb_Message_SerializableFieldBegin`.
98+
// Returns true if a serializable field was found, sets `*f` to that field,
99+
// and updates `*iter`. Returns false when iteration is complete.
100+
//
101+
// const upb_MiniTableField* f;
102+
// uintptr_t iter = kUpb_Message_SerializableFieldBegin;
103+
// while (upb_Message_NextSerializableField(msg, mt, &f, &iter)) {
104+
// // ...
105+
// }
106+
UPB_NODISCARD UPB_API bool upb_Message_NextSerializableField(
107+
const upb_Message* msg, const upb_MiniTable* mt,
108+
const upb_MiniTableField** f, uintptr_t* iter);
109+
86110
// Mark a message and all of its descendents as frozen/immutable.
87111
UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m);
88112

0 commit comments

Comments
 (0)