From b8bec58e016d5b59ad539bceaf10366a11689e8d Mon Sep 17 00:00:00 2001 From: Eric Salo Date: Fri, 30 Sep 2022 11:22:10 -0700 Subject: [PATCH] pull the mini descriptor encoders into their proper .c files Performance neutral but it simplifies the code, shrinks the public surface, and makes logical sense PiperOrigin-RevId: 478038589 --- BUILD | 4 +- upb/reflection/desc_state.c | 53 +++++ ...{mini_descriptor_encode.h => desc_state.h} | 34 +-- upb/reflection/enum_def.c | 45 +++- upb/reflection/enum_def.h | 7 +- upb/reflection/field_def.c | 28 ++- upb/reflection/field_def.h | 6 + upb/reflection/message_def.c | 55 ++++- upb/reflection/message_def.h | 8 +- upb/reflection/mini_descriptor_encode.c | 202 ------------------ upbc/code_generator_request.c | 7 +- 11 files changed, 212 insertions(+), 237 deletions(-) create mode 100644 upb/reflection/desc_state.c rename upb/reflection/{mini_descriptor_encode.h => desc_state.h} (67%) delete mode 100644 upb/reflection/mini_descriptor_encode.c diff --git a/BUILD b/BUILD index fd16a0aecb..7504a6182f 100644 --- a/BUILD +++ b/BUILD @@ -399,6 +399,8 @@ cc_library( "upb/reflection/def_pool.h", "upb/reflection/def_type.c", "upb/reflection/def_type.h", + "upb/reflection/desc_state.c", + "upb/reflection/desc_state.h", "upb/reflection/enum_def.c", "upb/reflection/enum_def.h", "upb/reflection/enum_value_def.c", @@ -414,7 +416,6 @@ cc_library( "upb/reflection/message_def.h", "upb/reflection/method_def.c", "upb/reflection/method_def.h", - "upb/reflection/mini_descriptor_encode.c", "upb/reflection/oneof_def.c", "upb/reflection/oneof_def.h", "upb/reflection/service_def.c", @@ -429,7 +430,6 @@ cc_library( "upb/reflection/def.hpp", "upb/reflection/message.h", "upb/reflection/message.hpp", - "upb/reflection/mini_descriptor_encode.h", ], copts = UPB_DEFAULT_COPTS, visibility = ["//visibility:public"], diff --git a/upb/reflection/desc_state.c b/upb/reflection/desc_state.c new file mode 100644 index 0000000000..ea404082da --- /dev/null +++ b/upb/reflection/desc_state.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2009-2022, Google LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google LLC nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "upb/reflection/desc_state.h" + +// Must be last. +#include "upb/port_def.inc" + +bool _upb_DescState_Grow(upb_DescState* d, upb_Arena* a) { + const size_t oldbufsize = d->bufsize; + const int used = d->ptr - d->buf; + + if (!d->buf) { + d->buf = upb_Arena_Malloc(a, d->bufsize); + if (!d->buf) return false; + d->ptr = d->buf; + d->e.end = d->buf + d->bufsize; + } + + if (oldbufsize - used < kUpb_MtDataEncoder_MinSize) { + d->bufsize *= 2; + d->buf = upb_Arena_Realloc(a, d->buf, oldbufsize, d->bufsize); + if (!d->buf) return false; + d->ptr = d->buf + used; + d->e.end = d->buf + d->bufsize; + } + + return true; +} diff --git a/upb/reflection/mini_descriptor_encode.h b/upb/reflection/desc_state.h similarity index 67% rename from upb/reflection/mini_descriptor_encode.h rename to upb/reflection/desc_state.h index dcb42a4604..a4dffd4d1c 100644 --- a/upb/reflection/mini_descriptor_encode.h +++ b/upb/reflection/desc_state.h @@ -25,30 +25,34 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef UPB_REFLECTION_MINI_DESCRIPTOR_ENCODE_H_ -#define UPB_REFLECTION_MINI_DESCRIPTOR_ENCODE_H_ +#ifndef UPB_REFLECTION_DESC_STATE_H_ +#define UPB_REFLECTION_DESC_STATE_H_ -#include "upb/reflection/common.h" -#include "upb/string_view.h" +#include "upb/mini_table.h" // Must be last. #include "upb/port_def.inc" +// Manages the storage for mini descriptor strings as they are being encoded. +// TODO(b/234740652): Move some of this state directly into the encoder, maybe. +typedef struct { + upb_MtDataEncoder e; + size_t bufsize; + char* buf; + char* ptr; +} upb_DescState; + #ifdef __cplusplus extern "C" { #endif -// Creates a mini descriptor string for an enum, returns true on success. -bool upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, upb_Arena* a, - upb_StringView* out); - -// Creates a mini descriptor string for a field, returns true on success. -bool upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a, - upb_StringView* out); +UPB_INLINE void _upb_DescState_Init(upb_DescState* d) { + d->bufsize = kUpb_MtDataEncoder_MinSize * 2; + d->buf = NULL; + d->ptr = NULL; +} -// Creates a mini descriptor string for a message, returns true on success. -bool upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_Arena* a, - upb_StringView* out); +bool _upb_DescState_Grow(upb_DescState* d, upb_Arena* a); #ifdef __cplusplus } /* extern "C" */ @@ -56,4 +60,4 @@ bool upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_Arena* a, #include "upb/port_undef.inc" -#endif /* UPB_REFLECTION_MINI_DESCRIPTOR_ENCODE_H_ */ +#endif /* UPB_REFLECTION_DESC_STATE_H_ */ diff --git a/upb/reflection/enum_def.c b/upb/reflection/enum_def.c index 7bb7cf8cbb..3d3d0cedc8 100644 --- a/upb/reflection/enum_def.c +++ b/upb/reflection/enum_def.c @@ -32,10 +32,10 @@ #include "upb/mini_table.h" #include "upb/reflection/def_builder.h" #include "upb/reflection/def_type.h" +#include "upb/reflection/desc_state.h" #include "upb/reflection/enum_value_def.h" #include "upb/reflection/file_def.h" #include "upb/reflection/message_def.h" -#include "upb/reflection/mini_descriptor_encode.h" // Must be last. #include "upb/port_def.inc" @@ -85,8 +85,6 @@ bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a) { return true; } -bool _upb_EnumDef_IsSorted(const upb_EnumDef* e) { return e->is_sorted; } - const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) { return e->opts; } @@ -145,10 +143,49 @@ const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i) { return _upb_EnumValueDef_At(e->values, i); } +bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a, + upb_StringView* out) { + upb_DescState s; + _upb_DescState_Init(&s); + + const upb_EnumValueDef** sorted = NULL; + if (!e->is_sorted) { + sorted = _upb_EnumValueDefs_Sorted(e->values, e->value_count, a); + if (!sorted) return false; + } + + upb_MtDataEncoder_StartEnum(&s.e); + + // Duplicate values are allowed but we only encode each value once. + uint32_t previous = 0; + + for (size_t i = 0; i < e->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_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); + + // There will always be room for this '\0' 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'; + + out->data = s.buf; + out->size = s.ptr - s.buf; + return true; +} + static upb_MiniTable_Enum* create_enumlayout(upb_DefBuilder* ctx, const upb_EnumDef* e) { upb_StringView sv; - bool ok = upb_MiniDescriptor_EncodeEnum(e, ctx->tmp_arena, &sv); + bool ok = upb_EnumDef_MiniDescriptorEncode(e, ctx->tmp_arena, &sv); if (!ok) _upb_DefBuilder_Errf(ctx, "OOM while building enum MiniDescriptor"); upb_Status status; diff --git a/upb/reflection/enum_def.h b/upb/reflection/enum_def.h index c85026152d..1dd12e65dc 100644 --- a/upb/reflection/enum_def.h +++ b/upb/reflection/enum_def.h @@ -31,6 +31,7 @@ #define UPB_REFLECTION_ENUM_DEF_H_ #include "upb/reflection/common.h" +#include "upb/string_view.h" // Must be last. #include "upb/port_def.inc" @@ -51,6 +52,11 @@ const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e, int32_t num); const char* upb_EnumDef_FullName(const upb_EnumDef* e); bool upb_EnumDef_HasOptions(const upb_EnumDef* e); + +// Creates a mini descriptor string for an enum, returns true on success. +bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a, + upb_StringView* out); + const char* upb_EnumDef_Name(const upb_EnumDef* e); const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e); const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i); @@ -60,7 +66,6 @@ int upb_EnumDef_ValueCount(const upb_EnumDef* e); upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i); bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a); -bool _upb_EnumDef_IsSorted(const upb_EnumDef* e); const upb_MiniTable_Enum* _upb_EnumDef_MiniTable(const upb_EnumDef* e); // Allocate and initialize an array of |n| enum defs. diff --git a/upb/reflection/field_def.c b/upb/reflection/field_def.c index f7ac728445..f2c7676892 100644 --- a/upb/reflection/field_def.c +++ b/upb/reflection/field_def.c @@ -34,12 +34,12 @@ #include "upb/reflection/def_builder.h" #include "upb/reflection/def_pool.h" #include "upb/reflection/def_type.h" +#include "upb/reflection/desc_state.h" #include "upb/reflection/enum_def.h" #include "upb/reflection/enum_value_def.h" #include "upb/reflection/extension_range.h" #include "upb/reflection/file_def.h" #include "upb/reflection/message_def.h" -#include "upb/reflection/mini_descriptor_encode.h" #include "upb/reflection/oneof_def.h" // Must be last. @@ -817,6 +817,30 @@ const upb_FieldDef** _upb_FieldDefs_Sorted(const upb_FieldDef* f, int n, return (const upb_FieldDef**)out; } +bool upb_FieldDef_MiniDescriptorEncode(const upb_FieldDef* f, upb_Arena* a, + upb_StringView* out) { + UPB_ASSERT(f->is_extension_); + + upb_DescState s; + _upb_DescState_Init(&s); + + if (!_upb_DescState_Grow(&s, a)) return false; + s.ptr = upb_MtDataEncoder_StartMessage(&s.e, s.ptr, 0); + + const int number = upb_FieldDef_Number(f); + const uint64_t modifiers = _upb_FieldDef_Modifiers(f); + + if (!_upb_DescState_Grow(&s, a)) return false; + s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, f->type_, number, modifiers); + + if (!_upb_DescState_Grow(&s, a)) return false; + *s.ptr = '\0'; + + out->data = s.buf; + out->size = s.ptr - s.buf; + return true; +} + static void resolve_extension(upb_DefBuilder* ctx, const char* prefix, upb_FieldDef* f, const google_protobuf_FieldDescriptorProto* field_proto) { @@ -843,7 +867,7 @@ static void resolve_extension(upb_DefBuilder* ctx, const char* prefix, UPB_ASSERT(upb_FieldDef_Number(f) == ext->field.number); } else { upb_StringView desc; - if (!upb_MiniDescriptor_EncodeField(f, ctx->tmp_arena, &desc)) { + if (!upb_FieldDef_MiniDescriptorEncode(f, ctx->tmp_arena, &desc)) { _upb_DefBuilder_OomErr(ctx); } diff --git a/upb/reflection/field_def.h b/upb/reflection/field_def.h index dbfa5e70ec..4d0b4fc8db 100644 --- a/upb/reflection/field_def.h +++ b/upb/reflection/field_def.h @@ -31,6 +31,7 @@ #define UPB_REFLECTION_FIELD_DEF_H_ #include "upb/reflection/common.h" +#include "upb/string_view.h" // Must be last. #include "upb/port_def.inc" @@ -68,6 +69,11 @@ bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f); const char* upb_FieldDef_JsonName(const upb_FieldDef* f); upb_Label upb_FieldDef_Label(const upb_FieldDef* f); const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f); + +// Creates a mini descriptor string for a field, returns true on success. +bool upb_FieldDef_MiniDescriptorEncode(const upb_FieldDef* f, upb_Arena* a, + upb_StringView* out); + const upb_MiniTable_Field* upb_FieldDef_MiniTable(const upb_FieldDef* f); const char* upb_FieldDef_Name(const upb_FieldDef* f); uint32_t upb_FieldDef_Number(const upb_FieldDef* f); diff --git a/upb/reflection/message_def.c b/upb/reflection/message_def.c index 3e4ce06a63..bf17b2b961 100644 --- a/upb/reflection/message_def.c +++ b/upb/reflection/message_def.c @@ -30,11 +30,11 @@ #include "upb/mini_table.h" #include "upb/reflection/def_builder.h" #include "upb/reflection/def_type.h" +#include "upb/reflection/desc_state.h" #include "upb/reflection/enum_def.h" #include "upb/reflection/extension_range.h" #include "upb/reflection/field_def.h" #include "upb/reflection/file_def.h" -#include "upb/reflection/mini_descriptor_encode.h" #include "upb/reflection/oneof_def.h" // Must be last. @@ -132,8 +132,6 @@ bool _upb_MessageDef_IsValidExtensionNumber(const upb_MessageDef* m, int n) { return false; } -bool _upb_MessageDef_IsSorted(const upb_MessageDef* m) { return m->is_sorted; } - const google_protobuf_MessageOptions* upb_MessageDef_Options( const upb_MessageDef* m) { return m->opts; @@ -344,7 +342,7 @@ static upb_MiniTable* _upb_MessageDef_MakeMiniTable(upb_DefBuilder* ctx, } upb_StringView desc; - bool ok = upb_MiniDescriptor_EncodeMessage(m, ctx->tmp_arena, &desc); + bool ok = upb_MessageDef_MiniDescriptorEncode(m, ctx->tmp_arena, &desc); if (!ok) _upb_DefBuilder_OomErr(ctx); void** scratch_data = _upb_DefPool_ScratchData(ctx->symtab); @@ -458,7 +456,7 @@ void _upb_MessageDef_LinkMiniTable(upb_DefBuilder* ctx, } } -uint64_t _upb_MessageDef_Modifiers(const upb_MessageDef* m) { +static uint64_t _upb_MessageDef_Modifiers(const upb_MessageDef* m) { uint64_t out = 0; if (upb_FileDef_Syntax(m->file) == kUpb_Syntax_Proto3) { out |= kUpb_MessageModifier_ValidateUtf8; @@ -470,6 +468,53 @@ uint64_t _upb_MessageDef_Modifiers(const upb_MessageDef* m) { return out; } +bool upb_MessageDef_MiniDescriptorEncode(const upb_MessageDef* m, upb_Arena* a, + upb_StringView* out) { + upb_DescState s; + _upb_DescState_Init(&s); + + const upb_FieldDef** sorted = NULL; + if (!m->is_sorted) { + sorted = _upb_FieldDefs_Sorted(m->fields, m->field_count, a); + if (!sorted) return false; + } + + if (!_upb_DescState_Grow(&s, a)) return false; + s.ptr = + upb_MtDataEncoder_StartMessage(&s.e, s.ptr, _upb_MessageDef_Modifiers(m)); + + for (int i = 0; i < m->field_count; i++) { + const upb_FieldDef* f = sorted ? sorted[i] : upb_MessageDef_Field(m, i); + const upb_FieldType type = upb_FieldDef_Type(f); + const int number = upb_FieldDef_Number(f); + const uint64_t modifiers = _upb_FieldDef_Modifiers(f); + + if (!_upb_DescState_Grow(&s, a)) return false; + s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers); + } + + for (int i = 0; i < m->oneof_count; i++) { + if (!_upb_DescState_Grow(&s, a)) return false; + s.ptr = upb_MtDataEncoder_StartOneof(&s.e, s.ptr); + + const upb_OneofDef* o = upb_MessageDef_Oneof(m, i); + const int field_count = upb_OneofDef_FieldCount(o); + for (int j = 0; j < field_count; j++) { + const int number = upb_FieldDef_Number(upb_OneofDef_Field(o, j)); + + if (!_upb_DescState_Grow(&s, a)) return false; + s.ptr = upb_MtDataEncoder_PutOneofField(&s.e, s.ptr, number); + } + } + + if (!_upb_DescState_Grow(&s, a)) return false; + *s.ptr = '\0'; + + out->data = s.buf; + out->size = s.ptr - s.buf; + return true; +} + static void create_msgdef(upb_DefBuilder* ctx, const char* prefix, const google_protobuf_DescriptorProto* msg_proto, const upb_MessageDef* containing_type, diff --git a/upb/reflection/message_def.h b/upb/reflection/message_def.h index d9924c92e3..74738abae0 100644 --- a/upb/reflection/message_def.h +++ b/upb/reflection/message_def.h @@ -31,6 +31,7 @@ #define UPB_REFLECTION_MESSAGE_DEF_H_ #include "upb/reflection/common.h" +#include "upb/string_view.h" // Must be last. #include "upb/port_def.inc" @@ -129,6 +130,11 @@ const char* upb_MessageDef_FullName(const upb_MessageDef* m); bool upb_MessageDef_HasOptions(const upb_MessageDef* m); bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m); bool upb_MessageDef_IsMessageSet(const upb_MessageDef* m); + +// Creates a mini descriptor string for a message, returns true on success. +bool upb_MessageDef_MiniDescriptorEncode(const upb_MessageDef* m, upb_Arena* a, + upb_StringView* out); + const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m); const char* upb_MessageDef_Name(const upb_MessageDef* m); @@ -157,11 +163,9 @@ bool _upb_MessageDef_Insert(upb_MessageDef* m, const char* name, size_t size, upb_value v, upb_Arena* a); void _upb_MessageDef_InsertField(upb_DefBuilder* ctx, upb_MessageDef* m, const upb_FieldDef* f); -bool _upb_MessageDef_IsSorted(const upb_MessageDef* m); bool _upb_MessageDef_IsValidExtensionNumber(const upb_MessageDef* m, int n); void _upb_MessageDef_LinkMiniTable(upb_DefBuilder* ctx, const upb_MessageDef* m); -uint64_t _upb_MessageDef_Modifiers(const upb_MessageDef* m); void _upb_MessageDef_Resolve(upb_DefBuilder* ctx, upb_MessageDef* m); // Allocate and initialize an array of |n| message defs. diff --git a/upb/reflection/mini_descriptor_encode.c b/upb/reflection/mini_descriptor_encode.c deleted file mode 100644 index ce2e7a86a3..0000000000 --- a/upb/reflection/mini_descriptor_encode.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2009-2022, Google LLC - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Google LLC nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "upb/reflection/mini_descriptor_encode.h" - -#include "upb/mini_table.h" -#include "upb/reflection/def_builder.h" -#include "upb/reflection/def_type.h" -#include "upb/reflection/enum_def.h" -#include "upb/reflection/enum_value_def.h" -#include "upb/reflection/field_def.h" -#include "upb/reflection/file_def.h" -#include "upb/reflection/message_def.h" -#include "upb/reflection/oneof_def.h" - -// Must be last. -#include "upb/port_def.inc" - -/* DescState ******************************************************************/ - -// Manages the storage for mini descriptor strings as they are being encoded. -// TODO(b/234740652): Move some of this state directly into the encoder, maybe. - -typedef struct { - upb_MtDataEncoder e; - size_t bufsize; - char* buf; - char* ptr; -} DescState; - -static void upb_DescState_Init(DescState* d) { - d->bufsize = kUpb_MtDataEncoder_MinSize * 2; - d->buf = NULL; - d->ptr = NULL; -} - -static bool upb_DescState_Grow(DescState* d, upb_Arena* a) { - const size_t oldbufsize = d->bufsize; - const int used = d->ptr - d->buf; - - if (!d->buf) { - d->buf = upb_Arena_Malloc(a, d->bufsize); - if (!d->buf) return false; - d->ptr = d->buf; - d->e.end = d->buf + d->bufsize; - } - - if (oldbufsize - used < kUpb_MtDataEncoder_MinSize) { - d->bufsize *= 2; - d->buf = upb_Arena_Realloc(a, d->buf, oldbufsize, d->bufsize); - if (!d->buf) return false; - d->ptr = d->buf + used; - d->e.end = d->buf + d->bufsize; - } - - return true; -} - -/******************************************************************************/ - -bool upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* e, upb_Arena* a, - upb_StringView* out) { - DescState s; - upb_DescState_Init(&s); - - const upb_EnumValueDef** sorted = NULL; - if (!_upb_EnumDef_IsSorted(e)) { - sorted = _upb_EnumValueDefs_Sorted(upb_EnumDef_Value(e, 0), - upb_EnumDef_ValueCount(e), a); - if (!sorted) return false; - } - - upb_MtDataEncoder_StartEnum(&s.e); - - // Duplicate values are allowed but we only encode each value once. - uint32_t previous = 0; - - const size_t value_count = upb_EnumDef_ValueCount(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_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); - - // There will always be room for this '\0' 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'; - - out->data = s.buf; - out->size = s.ptr - s.buf; - return true; -} - -bool upb_MiniDescriptor_EncodeField(const upb_FieldDef* f, upb_Arena* a, - upb_StringView* out) { - UPB_ASSERT(upb_FieldDef_IsExtension(f)); - - DescState s; - upb_DescState_Init(&s); - - if (!upb_DescState_Grow(&s, a)) return false; - s.ptr = upb_MtDataEncoder_StartMessage(&s.e, s.ptr, 0); - - const upb_FieldType type = upb_FieldDef_Type(f); - const int number = upb_FieldDef_Number(f); - const uint64_t modifiers = _upb_FieldDef_Modifiers(f); - - if (!upb_DescState_Grow(&s, a)) return false; - s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers); - - if (!upb_DescState_Grow(&s, a)) return false; - *s.ptr = '\0'; - - out->data = s.buf; - out->size = s.ptr - s.buf; - return true; -} - -// If the field numbers happen to be defined in ascending order then |sorted| -// should be NULL. Otherwise it must point to an array containing pointers to -// the field defs in sorted order. -bool upb_MiniDescriptor_EncodeMessage(const upb_MessageDef* m, upb_Arena* a, - upb_StringView* out) { - DescState s; - upb_DescState_Init(&s); - - const upb_FieldDef** sorted = NULL; - if (!_upb_MessageDef_IsSorted(m)) { - sorted = _upb_FieldDefs_Sorted(upb_MessageDef_Field(m, 0), - upb_MessageDef_FieldCount(m), a); - if (!sorted) return false; - } - - if (!upb_DescState_Grow(&s, a)) return false; - s.ptr = - upb_MtDataEncoder_StartMessage(&s.e, s.ptr, _upb_MessageDef_Modifiers(m)); - - const int field_count = upb_MessageDef_FieldCount(m); - for (int i = 0; i < field_count; i++) { - const upb_FieldDef* f = sorted ? sorted[i] : upb_MessageDef_Field(m, i); - const upb_FieldType type = upb_FieldDef_Type(f); - const int number = upb_FieldDef_Number(f); - const uint64_t modifiers = _upb_FieldDef_Modifiers(f); - - if (!upb_DescState_Grow(&s, a)) return false; - s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifiers); - } - - const int oneof_count = upb_MessageDef_OneofCount(m); - for (int i = 0; i < oneof_count; i++) { - if (!upb_DescState_Grow(&s, a)) return false; - s.ptr = upb_MtDataEncoder_StartOneof(&s.e, s.ptr); - - const upb_OneofDef* o = upb_MessageDef_Oneof(m, i); - const int field_count = upb_OneofDef_FieldCount(o); - for (int j = 0; j < field_count; j++) { - const int number = upb_FieldDef_Number(upb_OneofDef_Field(o, j)); - - if (!upb_DescState_Grow(&s, a)) return false; - s.ptr = upb_MtDataEncoder_PutOneofField(&s.e, s.ptr, number); - } - } - - if (!upb_DescState_Grow(&s, a)) return false; - *s.ptr = '\0'; - - out->data = s.buf; - out->size = s.ptr - s.buf; - return true; -} diff --git a/upbc/code_generator_request.c b/upbc/code_generator_request.c index e3eca5a4c3..00254855ec 100644 --- a/upbc/code_generator_request.c +++ b/upbc/code_generator_request.c @@ -33,7 +33,6 @@ #include "google/protobuf/compiler/plugin.upb.h" #include "upb/mini_table.h" #include "upb/reflection/def.h" -#include "upb/reflection/mini_descriptor_encode.h" // Must be last. #include "upb/port_def.inc" @@ -86,7 +85,7 @@ static void upbc_Scrape_Message(upbc_State*, const upb_MessageDef*); static void upbc_Scrape_Enum(upbc_State* s, const upb_EnumDef* e) { upb_StringView desc; - bool ok = upb_MiniDescriptor_EncodeEnum(e, s->arena, &desc); + bool ok = upb_EnumDef_MiniDescriptorEncode(e, s->arena, &desc); if (!ok) upbc_Error(s, __func__, "could not encode enum"); upbc_State_Emit(s, upb_EnumDef_FullName(e), desc); @@ -94,7 +93,7 @@ static void upbc_Scrape_Enum(upbc_State* s, const upb_EnumDef* e) { static void upbc_Scrape_Extension(upbc_State* s, const upb_FieldDef* f) { upb_StringView desc; - bool ok = upb_MiniDescriptor_EncodeField(f, s->arena, &desc); + bool ok = upb_FieldDef_MiniDescriptorEncode(f, s->arena, &desc); if (!ok) upbc_Error(s, __func__, "could not encode extension"); upbc_State_Emit(s, upb_FieldDef_FullName(f), desc); @@ -173,7 +172,7 @@ static void upbc_Scrape_NestedMessages(upbc_State* s, const upb_MessageDef* m) { static void upbc_Scrape_Message(upbc_State* s, const upb_MessageDef* m) { upb_StringView desc; - bool ok = upb_MiniDescriptor_EncodeMessage(m, s->arena, &desc); + bool ok = upb_MessageDef_MiniDescriptorEncode(m, s->arena, &desc); if (!ok) upbc_Error(s, __func__, "could not encode message"); upbc_State_Emit(s, upb_MessageDef_FullName(m), desc);