create _upb_EnumDef_MiniDescriptor()
delete upb_EnumDef_IsSorted()
We now have a simple internal function for returning a mini descriptor directly from an enum def.
PiperOrigin-RevId: 461208352
diff --git a/upb/def.c b/upb/def.c
index c1a9d21..4a1254d 100644
--- a/upb/def.c
+++ b/upb/def.c
@@ -322,10 +322,12 @@
return ret;
}
-int cmp_fields(const void* p1, const void* p2) {
- const upb_FieldDef* f1 = *(upb_FieldDef* const*)p1;
- const upb_FieldDef* f2 = *(upb_FieldDef* const*)p2;
- return field_rank(f1) - field_rank(f2);
+static int cmp_values(const void* a, const void* b) {
+ const upb_EnumValueDef* A = *(const upb_EnumValueDef**)a;
+ const upb_EnumValueDef* B = *(const upb_EnumValueDef**)b;
+ if ((uint32_t)A->number < (uint32_t)B->number) return -1;
+ if ((uint32_t)A->number > (uint32_t)B->number) return 1;
+ return 0;
}
static void upb_Status_setoom(upb_Status* status) {
@@ -404,8 +406,6 @@
int upb_EnumDef_ValueCount(const upb_EnumDef* e) { return e->value_count; }
-bool upb_EnumDef_IsSorted(const upb_EnumDef* e) { return e->is_sorted; }
-
const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
const upb_EnumDef* def, const char* name, size_t len) {
upb_value v;
@@ -432,6 +432,21 @@
return &e->values[i];
}
+const char* _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* a) {
+ if (e->is_sorted) return upb_MiniDescriptor_EncodeEnum(e, NULL, a);
+
+ const upb_EnumValueDef** sorted = (const upb_EnumValueDef**)upb_Arena_Malloc(
+ a, e->value_count * sizeof(void*));
+ if (!sorted) return NULL;
+
+ for (size_t i = 0; i < e->value_count; i++) {
+ sorted[i] = upb_EnumDef_Value(e, i);
+ }
+ qsort(sorted, e->value_count, sizeof(void*), cmp_values);
+
+ return upb_MiniDescriptor_EncodeEnum(e, sorted, a);
+}
+
/* upb_EnumValueDef ***********************************************************/
const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
@@ -2459,26 +2474,22 @@
static upb_MiniTable_Enum* create_enumlayout(symtab_addctx* ctx,
const upb_EnumDef* e) {
- char* data;
- size_t size;
- bool ok = upb_MiniDescriptor_EncodeEnum(e, &data, &size, ctx->tmp_arena);
- CHK_OOM(ok);
+ const char* desc = _upb_EnumDef_MiniDescriptor(e, ctx->tmp_arena);
+ if (!desc) symtab_errf(ctx, "OOM while building enum MiniDescriptor");
upb_Status status;
upb_MiniTable_Enum* layout =
- upb_MiniTable_BuildEnum(data, size, ctx->arena, &status);
+ upb_MiniTable_BuildEnum(desc, strlen(desc), ctx->arena, &status);
if (!layout)
symtab_errf(ctx, "Error building enum MiniTable: %s", status.msg);
return layout;
}
-static void create_enumvaldef(
- symtab_addctx* ctx, const char* prefix,
- const google_protobuf_EnumValueDescriptorProto* val_proto, upb_EnumDef* e,
- int i) {
+static void create_enumvaldef(symtab_addctx* ctx, const char* prefix,
+ const google_protobuf_EnumValueDescriptorProto* val_proto,
+ upb_EnumDef* e, int i) {
upb_EnumValueDef* val = (upb_EnumValueDef*)&e->values[i];
- upb_StringView name =
- google_protobuf_EnumValueDescriptorProto_name(val_proto);
+ upb_StringView name = google_protobuf_EnumValueDescriptorProto_name(val_proto);
upb_value v = upb_value_constptr(val);
val->parent = e; /* Must happen prior to symtab_add(). */
diff --git a/upb/def.h b/upb/def.h
index 8dd696d..5fd5fb7 100644
--- a/upb/def.h
+++ b/upb/def.h
@@ -268,7 +268,6 @@
const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e);
int32_t upb_EnumDef_Default(const upb_EnumDef* e);
int upb_EnumDef_ValueCount(const upb_EnumDef* e);
-bool upb_EnumDef_IsSorted(const upb_EnumDef* e);
const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i);
const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
@@ -283,6 +282,9 @@
return upb_EnumDef_FindValueByNameWithSize(e, name, strlen(name));
}
+// Builds and returns a mini descriptor, or NULL if OOM.
+const char* _upb_EnumDef_MiniDescriptor(const upb_EnumDef* e, upb_Arena* a);
+
/* upb_EnumValueDef ***********************************************************/
const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
diff --git a/upb/mini_descriptor.c b/upb/mini_descriptor.c
index ba2f022..9be560a 100644
--- a/upb/mini_descriptor.c
+++ b/upb/mini_descriptor.c
@@ -113,19 +113,6 @@
/******************************************************************************/
-// Sort by enum value.
-static int upb_MiniDescriptor_CompareEnums(const void* a, const void* b) {
- const upb_EnumValueDef* A = *(void**)a;
- const upb_EnumValueDef* B = *(void**)b;
- if ((uint32_t)upb_EnumValueDef_Number(A) <
- (uint32_t)upb_EnumValueDef_Number(B))
- return -1;
- if ((uint32_t)upb_EnumValueDef_Number(A) >
- (uint32_t)upb_EnumValueDef_Number(B))
- return 1;
- return 0;
-}
-
// Sort by field number.
static int upb_MiniDescriptor_CompareFields(const void* a, const void* b) {
const upb_FieldDef* A = *(void**)a;
@@ -135,55 +122,39 @@
return 0;
}
-bool upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, char** data,
- size_t* size, upb_Arena* a) {
- const size_t len = upb_EnumDef_ValueCount(e);
-
+const char* upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e,
+ const upb_EnumValueDef** sorted,
+ upb_Arena* a) {
DescState s;
upb_DescState_Init(&s);
+ upb_MtDataEncoder_StartEnum(&s.e);
+
+ const size_t value_count = upb_EnumDef_ValueCount(e);
+
// Duplicate values are allowed but we only encode each value once.
uint32_t previous = 0;
- upb_MtDataEncoder_StartEnum(&s.e);
+ for (size_t i = 0; i < value_count; i++) {
+ const uint32_t current =
+ upb_EnumValueDef_Number(sorted ? sorted[i] : upb_EnumDef_Value(e, i));
+ if (i != 0 && previous == current) continue;
- if (upb_EnumDef_IsSorted(e)) {
- // The enum is well behaved so no need to copy/sort the pointers here.
- for (size_t i = 0; i < len; i++) {
- const uint32_t current = upb_EnumValueDef_Number(upb_EnumDef_Value(e, i));
- if (i != 0 && previous == current) continue;
-
- if (!upb_DescState_Grow(&s, a)) return false;
- s.ptr = upb_MtDataEncoder_PutEnumValue(&s.e, s.ptr, current);
- previous = current;
- }
- } else {
- // The enum fields are unsorted.
- const upb_EnumValueDef** sorted =
- (const upb_EnumValueDef**)upb_Arena_Malloc(a, len * sizeof(void*));
- if (!sorted) return false;
-
- for (size_t i = 0; i < len; i++) {
- sorted[i] = upb_EnumDef_Value(e, i);
- }
- qsort(sorted, len, sizeof(void*), upb_MiniDescriptor_CompareEnums);
-
- for (size_t i = 0; i < len; i++) {
- const uint32_t current = upb_EnumValueDef_Number(sorted[i]);
- if (i != 0 && previous == current) continue;
-
- if (!upb_DescState_Grow(&s, a)) return false;
- s.ptr = upb_MtDataEncoder_PutEnumValue(&s.e, s.ptr, current);
- previous = current;
- }
+ if (!upb_DescState_Grow(&s, a)) return false;
+ s.ptr = upb_MtDataEncoder_PutEnumValue(&s.e, s.ptr, current);
+ previous = current;
}
if (!upb_DescState_Grow(&s, a)) return false;
s.ptr = upb_MtDataEncoder_EndEnum(&s.e, s.ptr);
- *data = s.buf;
- *size = s.ptr - s.buf;
- return true;
+ // NULL-terminate the mini descriptor so we can return it as a C string.
+ // There will always be room for this in the encoder buffer because
+ // kUpb_MtDataEncoder_MinSize is overkill for upb_MtDataEncoder_EndEnum().
+ UPB_ASSERT(s.ptr < s.buf + s.bufsize);
+ *s.ptr++ = '\0';
+
+ return s.buf;
}
bool upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, char** data,
@@ -213,23 +184,23 @@
upb_DescState_Init(&s);
// Make a copy.
- const size_t len = upb_MessageDef_FieldCount(m);
+ const size_t field_count = upb_MessageDef_FieldCount(m);
const upb_FieldDef** sorted =
- (const upb_FieldDef**)upb_Arena_Malloc(a, len * sizeof(void*));
+ (const upb_FieldDef**)upb_Arena_Malloc(a, field_count * sizeof(void*));
if (!sorted) return false;
// Sort the copy.
- for (size_t i = 0; i < len; i++) {
+ for (size_t i = 0; i < field_count; i++) {
sorted[i] = upb_MessageDef_Field(m, i);
}
- qsort(sorted, len, sizeof(void*), upb_MiniDescriptor_CompareFields);
+ qsort(sorted, field_count, sizeof(void*), upb_MiniDescriptor_CompareFields);
// Start encoding.
if (!upb_DescState_Grow(&s, a)) return false;
upb_MtDataEncoder_StartMessage(&s.e, s.ptr, upb_Message_Modifiers(m));
// Encode the fields.
- for (size_t i = 0; i < len; i++) {
+ for (size_t i = 0; i < field_count; i++) {
const upb_FieldDef* field_def = sorted[i];
const upb_FieldType type = upb_FieldDef_Type(field_def);
const int number = upb_FieldDef_Number(field_def);
diff --git a/upb/mini_descriptor.h b/upb/mini_descriptor.h
index 73fbae3..50f55f3 100644
--- a/upb/mini_descriptor.h
+++ b/upb/mini_descriptor.h
@@ -40,15 +40,21 @@
/** upb_MiniDescriptor ********************************************************/
-// All of these functions return true on success, false on failure.
-// Failure always means an OOM error.
+// Creates and returns a mini descriptor string for an enum, or NULL on error.
+// If the values in the enum happen to be defined in ascending order (when cast
+// to uint32_t) then |sorted| should be NULL. Otherwise it must point to an
+// array containing pointers to the enum values in sorted order.
+const char* upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e,
+ const upb_EnumValueDef** sorted,
+ upb_Arena* a);
-bool upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, char** data,
- size_t* size, upb_Arena* a);
+// TODO(salo): Change the following two functions to match the above function.
+// Returns true on success, false on error (OOM).
bool upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, char** data,
size_t* size, upb_Arena* a);
+// Returns true on success, false on error (OOM).
bool upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, char** data,
size_t* size, upb_Arena* a);
diff --git a/upbc/code_generator_request.c b/upbc/code_generator_request.c
index 1ac0c4e..54f05d0 100644
--- a/upbc/code_generator_request.c
+++ b/upbc/code_generator_request.c
@@ -85,12 +85,10 @@
static void upbc_Scrape_Message(upbc_State*, const upb_MessageDef*);
static void upbc_Scrape_Enum(upbc_State* s, const upb_EnumDef* e) {
- char* data;
- size_t size;
- bool ok = upb_MiniDescriptor_EncodeEnum(e, &data, &size, s->arena);
- if (!ok) upbc_Error(s, __func__, "could not encode enum");
+ const char* desc = _upb_EnumDef_MiniDescriptor(e, s->arena);
+ if (!desc) upbc_Error(s, __func__, "could not encode enum");
- upbc_State_Emit(s, upb_EnumDef_FullName(e), data, size);
+ upbc_State_Emit(s, upb_EnumDef_FullName(e), desc, strlen(desc));
}
static void upbc_Scrape_Extension(upbc_State* s, const upb_FieldDef* f) {