diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h index 1b8bbe94da..8d4e18ed7a 100644 --- a/php/ext/google/protobuf/php-upb.h +++ b/php/ext/google/protobuf/php-upb.h @@ -369,6 +369,8 @@ void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt, #ifndef UPB_COLLECTIONS_ARRAY_H_ #define UPB_COLLECTIONS_ARRAY_H_ +#include + #ifndef UPB_BASE_DESCRIPTOR_CONSTANTS_H_ #define UPB_BASE_DESCRIPTOR_CONSTANTS_H_ @@ -446,12 +448,204 @@ UPB_INLINE bool upb_FieldType_IsPackable(upb_FieldType type) { #endif /* UPB_BASE_DESCRIPTOR_CONSTANTS_H_ */ +/* upb_Arena is a specific allocator implementation that uses arena allocation. + * The user provides an allocator that will be used to allocate the underlying + * arena blocks. Arenas by nature do not require the individual allocations + * to be freed. However the Arena does allow users to register cleanup + * functions that will run when the arena is destroyed. + * + * A upb_Arena is *not* thread-safe. + * + * You could write a thread-safe arena allocator that satisfies the + * upb_alloc interface, but it would not be as efficient for the + * single-threaded case. */ + +#ifndef UPB_MEM_ARENA_H_ +#define UPB_MEM_ARENA_H_ + +#include +#include +#include + + +#ifndef UPB_MEM_ALLOC_H_ +#define UPB_MEM_ALLOC_H_ + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct upb_alloc upb_alloc; + +/* A combined `malloc()`/`free()` function. + * If `size` is 0 then the function acts like `free()`, otherwise it acts like + * `realloc()`. Only `oldsize` bytes from a previous allocation are + * preserved. */ +typedef void* upb_alloc_func(upb_alloc* alloc, void* ptr, size_t oldsize, + size_t size); + +/* A upb_alloc is a possibly-stateful allocator object. + * + * It could either be an arena allocator (which doesn't require individual + * `free()` calls) or a regular `malloc()` (which does). The client must + * therefore free memory unless it knows that the allocator is an arena + * allocator. */ +struct upb_alloc { + upb_alloc_func* func; +}; + +UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, NULL, 0, size); +} + +UPB_INLINE void* upb_realloc(upb_alloc* alloc, void* ptr, size_t oldsize, + size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, ptr, oldsize, size); +} + +UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) { + UPB_ASSERT(alloc); + alloc->func(alloc, ptr, 0, 0); +} + +// The global allocator used by upb. Uses the standard malloc()/free(). + +extern upb_alloc upb_alloc_global; + +/* Functions that hard-code the global malloc. + * + * We still get benefit because we can put custom logic into our global + * allocator, like injecting out-of-memory faults in debug/testing builds. */ + +UPB_INLINE void* upb_gmalloc(size_t size) { + return upb_malloc(&upb_alloc_global, size); +} + +UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) { + return upb_realloc(&upb_alloc_global, ptr, oldsize, size); +} + +UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); } + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MEM_ALLOC_H_ */ + +// Must be last. + +typedef struct upb_Arena upb_Arena; + +typedef struct { + char *ptr, *end; +} _upb_ArenaHead; + +#ifdef __cplusplus +extern "C" { +#endif + +// Creates an arena from the given initial block (if any -- n may be 0). +// Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this +// is a fixed-size arena and cannot grow. +UPB_API upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc); + +UPB_API void upb_Arena_Free(upb_Arena* a); +UPB_API bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b); + +void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size); +size_t upb_Arena_SpaceAllocated(upb_Arena* arena); +uint32_t upb_Arena_DebugRefCount(upb_Arena* arena); + +UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) { + _upb_ArenaHead* h = (_upb_ArenaHead*)a; + return (size_t)(h->end - h->ptr); +} + +UPB_API_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) { + size = UPB_ALIGN_MALLOC(size); + size_t span = size + UPB_ASAN_GUARD_SIZE; + if (UPB_UNLIKELY(_upb_ArenaHas(a) < span)) { + return _upb_Arena_SlowMalloc(a, size); + } + + // We have enough space to do a fast malloc. + _upb_ArenaHead* h = (_upb_ArenaHead*)a; + void* ret = h->ptr; + UPB_ASSERT(UPB_ALIGN_MALLOC((uintptr_t)ret) == (uintptr_t)ret); + UPB_ASSERT(UPB_ALIGN_MALLOC(size) == size); + UPB_UNPOISON_MEMORY_REGION(ret, size); + + h->ptr += span; + + return ret; +} + +// Shrinks the last alloc from arena. +// REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena. +// We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if +// this was not the last alloc. +UPB_API_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, + size_t oldsize, size_t size) { + _upb_ArenaHead* h = (_upb_ArenaHead*)a; + oldsize = UPB_ALIGN_MALLOC(oldsize); + size = UPB_ALIGN_MALLOC(size); + // Must be the last alloc. + UPB_ASSERT((char*)ptr + oldsize == h->ptr - UPB_ASAN_GUARD_SIZE); + UPB_ASSERT(size <= oldsize); + h->ptr = (char*)ptr + size; +} + +UPB_API_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize, + size_t size) { + _upb_ArenaHead* h = (_upb_ArenaHead*)a; + oldsize = UPB_ALIGN_MALLOC(oldsize); + size = UPB_ALIGN_MALLOC(size); + bool is_most_recent_alloc = (uintptr_t)ptr + oldsize == (uintptr_t)h->ptr; + + if (is_most_recent_alloc) { + ptrdiff_t diff = size - oldsize; + if ((ptrdiff_t)_upb_ArenaHas(a) >= diff) { + h->ptr += diff; + return ptr; + } + } else if (size <= oldsize) { + return ptr; + } + + void* ret = upb_Arena_Malloc(a, size); + + if (ret && oldsize > 0) { + memcpy(ret, ptr, UPB_MIN(oldsize, size)); + } + + return ret; +} + +UPB_API_INLINE upb_Arena* upb_Arena_New(void) { + return upb_Arena_Init(NULL, 0, &upb_alloc_global); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MEM_ARENA_H_ */ + // Users should include array.h or map.h instead. // IWYU pragma: private, include "upb/upb/collections/array.h" #ifndef UPB_MESSAGE_VALUE_H_ #define UPB_MESSAGE_VALUE_H_ +#include + #ifndef UPB_BASE_STRING_VIEW_H_ #define UPB_BASE_STRING_VIEW_H_ @@ -571,181 +765,183 @@ UPB_INLINE upb_Message* _upb_TaggedMessagePtr_GetEmptyMessage( #endif /* UPB_MINI_TABLE_TYPES_H_ */ -#ifndef UPB_MINI_TABLE_MESSAGE_H_ -#define UPB_MINI_TABLE_MESSAGE_H_ - - -#ifndef UPB_MINI_TABLE_ENUM_H_ -#define UPB_MINI_TABLE_ENUM_H_ +typedef union { + bool bool_val; + float float_val; + double double_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + const struct upb_Array* array_val; + const struct upb_Map* map_val; + const upb_Message* msg_val; + upb_StringView str_val; + // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of + // msg_val if unlinked sub-messages may possibly be in use. See the + // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more + // information. + upb_TaggedMessagePtr tagged_msg_val; +} upb_MessageValue; -#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_ -#define UPB_MINI_TABLE_INTERNAL_ENUM_H_ +typedef union { + struct upb_Array* array; + struct upb_Map* map; + upb_Message* msg; +} upb_MutableMessageValue; -#include +#endif /* UPB_MESSAGE_VALUE_H_ */ // Must be last. -struct upb_MiniTableEnum { - uint32_t mask_limit; // Limit enum value that can be tested with mask. - uint32_t value_count; // Number of values after the bitfield. - uint32_t data[]; // Bitmask + enumerated values follow. -}; - -typedef enum { - _kUpb_FastEnumCheck_ValueIsInEnum = 0, - _kUpb_FastEnumCheck_ValueIsNotInEnum = 1, - _kUpb_FastEnumCheck_CannotCheckFast = 2, -} _kUpb_FastEnumCheck_Status; +typedef struct upb_Array upb_Array; #ifdef __cplusplus extern "C" { #endif -UPB_INLINE _kUpb_FastEnumCheck_Status _upb_MiniTable_CheckEnumValueFast( - const struct upb_MiniTableEnum* e, uint32_t val) { - if (UPB_UNLIKELY(val >= 64)) return _kUpb_FastEnumCheck_CannotCheckFast; - uint64_t mask = e->data[0] | ((uint64_t)e->data[1] << 32); - return (mask & (1ULL << val)) ? _kUpb_FastEnumCheck_ValueIsInEnum - : _kUpb_FastEnumCheck_ValueIsNotInEnum; -} - -UPB_INLINE bool _upb_MiniTable_CheckEnumValueSlow( - const struct upb_MiniTableEnum* e, uint32_t val) { - if (val < e->mask_limit) return e->data[val / 32] & (1ULL << (val % 32)); - // OPT: binary search long lists? - const uint32_t* start = &e->data[e->mask_limit / 32]; - const uint32_t* limit = &e->data[(e->mask_limit / 32) + e->value_count]; - for (const uint32_t* p = start; p < limit; p++) { - if (*p == val) return true; - } - return false; -} +// Creates a new array on the given arena that holds elements of this type. +UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type); -#ifdef __cplusplus -} /* extern "C" */ -#endif +// Returns the number of elements in the array. +UPB_API size_t upb_Array_Size(const upb_Array* arr); +// Returns the given element, which must be within the array's current size. +UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i); -#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */ +// Sets the given element, which must be within the array's current size. +UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val); -// Must be last +// Appends an element to the array. Returns false on allocation failure. +UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val, + upb_Arena* arena); -typedef struct upb_MiniTableEnum upb_MiniTableEnum; +// Moves elements within the array using memmove(). +// Like memmove(), the source and destination elements may be overlapping. +UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx, + size_t count); -// Validates enum value against range defined by enum mini table. -UPB_INLINE bool upb_MiniTableEnum_CheckValue(const struct upb_MiniTableEnum* e, - uint32_t val) { - _kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, val); - if (UPB_UNLIKELY(status == _kUpb_FastEnumCheck_CannotCheckFast)) { - return _upb_MiniTable_CheckEnumValueSlow(e, val); - } - return status == _kUpb_FastEnumCheck_ValueIsInEnum ? true : false; -} +// Inserts one or more empty elements into the array. +// Existing elements are shifted right. +// The new elements have undefined state and must be set with `upb_Array_Set()`. +// REQUIRES: `i <= upb_Array_Size(arr)` +UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count, + upb_Arena* arena); +// Deletes one or more elements from the array. +// Existing elements are shifted left. +// REQUIRES: `i + count <= upb_Array_Size(arr)` +UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count); -#endif /* UPB_MINI_TABLE_ENUM_H_ */ +// Changes the size of a vector. New elements are initialized to NULL/0. +// Returns false on allocation failure. +UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena); -#ifndef UPB_MINI_TABLE_FIELD_H_ -#define UPB_MINI_TABLE_FIELD_H_ +// Returns pointer to array data. +UPB_API const void* upb_Array_DataPtr(const upb_Array* arr); +// Returns mutable pointer to array data. +UPB_API void* upb_Array_MutableDataPtr(upb_Array* arr); -#ifndef UPB_MINI_TABLE_INTERNAL_FIELD_H_ -#define UPB_MINI_TABLE_INTERNAL_FIELD_H_ +#ifdef __cplusplus +} /* extern "C" */ +#endif -#include +#endif /* UPB_COLLECTIONS_ARRAY_H_ */ // Must be last. -struct upb_MiniTableField { - uint32_t number; - uint16_t offset; - int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index - - // Indexes into `upb_MiniTable.subs` - // Will be set to `kUpb_NoSub` if `descriptortype` != MESSAGE/GROUP/ENUM - uint16_t UPB_PRIVATE(submsg_index); - - uint8_t UPB_PRIVATE(descriptortype); +#ifdef __cplusplus +extern "C" { +#endif - // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift) - uint8_t mode; +// LINT.IfChange(struct_definition) +// Our internal representation for repeated fields. +struct upb_Array { + uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */ + size_t size; /* The number of elements in the array. */ + size_t capacity; /* Allocated storage. Measured in elements. */ }; +// LINT.ThenChange(GoogleInternalName1) -#define kUpb_NoSub ((uint16_t)-1) - -typedef enum { - kUpb_FieldMode_Map = 0, - kUpb_FieldMode_Array = 1, - kUpb_FieldMode_Scalar = 2, -} upb_FieldMode; +UPB_INLINE size_t _upb_Array_ElementSizeLg2(const upb_Array* arr) { + size_t ret = arr->data & 7; + UPB_ASSERT(ret <= 4); + return ret; +} -// Mask to isolate the upb_FieldMode from field.mode. -#define kUpb_FieldMode_Mask 3 +UPB_INLINE const void* _upb_array_constptr(const upb_Array* arr) { + _upb_Array_ElementSizeLg2(arr); // Check assertion. + return (void*)(arr->data & ~(uintptr_t)7); +} -// Extra flags on the mode field. -typedef enum { - kUpb_LabelFlags_IsPacked = 4, - kUpb_LabelFlags_IsExtension = 8, - // Indicates that this descriptor type is an "alternate type": - // - for Int32, this indicates that the actual type is Enum (but was - // rewritten to Int32 because it is an open enum that requires no check). - // - for Bytes, this indicates that the actual type is String (but does - // not require any UTF-8 check). - kUpb_LabelFlags_IsAlternate = 16, -} upb_LabelFlags; +UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + return (uintptr_t)ptr | elem_size_lg2; +} -// Note: we sort by this number when calculating layout order. -typedef enum { - kUpb_FieldRep_1Byte = 0, - kUpb_FieldRep_4Byte = 1, - kUpb_FieldRep_StringView = 2, - kUpb_FieldRep_8Byte = 3, +UPB_INLINE void* _upb_array_ptr(upb_Array* arr) { + return (void*)_upb_array_constptr(arr); +} - kUpb_FieldRep_NativePointer = - UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte), - kUpb_FieldRep_Max = kUpb_FieldRep_8Byte, -} upb_FieldRep; +UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + UPB_ASSERT(((uintptr_t)ptr & 7) == 0); + return (uintptr_t)ptr | (unsigned)elem_size_lg2; +} -#define kUpb_FieldRep_Shift 6 +extern const char _upb_Array_CTypeSizeLg2Table[]; -UPB_INLINE upb_FieldRep -_upb_MiniTableField_GetRep(const struct upb_MiniTableField* field) { - return (upb_FieldRep)(field->mode >> kUpb_FieldRep_Shift); +UPB_INLINE size_t _upb_Array_CTypeSizeLg2(upb_CType ctype) { + return _upb_Array_CTypeSizeLg2Table[ctype]; } -#ifdef __cplusplus -extern "C" { -#endif - -UPB_INLINE upb_FieldMode -upb_FieldMode_Get(const struct upb_MiniTableField* field) { - return (upb_FieldMode)(field->mode & 3); +UPB_INLINE upb_Array* _upb_Array_New(upb_Arena* a, size_t init_capacity, + int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_Array), UPB_MALLOC_ALIGN); + const size_t bytes = arr_size + (init_capacity << elem_size_lg2); + upb_Array* arr = (upb_Array*)upb_Arena_Malloc(a, bytes); + if (!arr) return NULL; + arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2); + arr->size = 0; + arr->capacity = init_capacity; + return arr; } -UPB_INLINE void _upb_MiniTableField_CheckIsArray( - const struct upb_MiniTableField* field) { - UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_NativePointer); - UPB_ASSUME(upb_FieldMode_Get(field) == kUpb_FieldMode_Array); - UPB_ASSUME(field->presence == 0); +// Resizes the capacity of the array to be at least min_size. +bool _upb_array_realloc(upb_Array* arr, size_t min_size, upb_Arena* arena); + +UPB_INLINE bool _upb_array_reserve(upb_Array* arr, size_t size, + upb_Arena* arena) { + if (arr->capacity < size) return _upb_array_realloc(arr, size, arena); + return true; } -UPB_INLINE void _upb_MiniTableField_CheckIsMap( - const struct upb_MiniTableField* field) { - UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_NativePointer); - UPB_ASSUME(upb_FieldMode_Get(field) == kUpb_FieldMode_Map); - UPB_ASSUME(field->presence == 0); +// Resize without initializing new elements. +UPB_INLINE bool _upb_Array_ResizeUninitialized(upb_Array* arr, size_t size, + upb_Arena* arena) { + UPB_ASSERT(size <= arr->size || arena); // Allow NULL arena when shrinking. + if (!_upb_array_reserve(arr, size, arena)) return false; + arr->size = size; + return true; } -UPB_INLINE bool upb_IsRepeatedOrMap(const struct upb_MiniTableField* field) { - // This works because upb_FieldMode has no value 3. - return !(field->mode & kUpb_FieldMode_Scalar); +// This function is intended for situations where elem_size is compile-time +// constant or a known expression of the form (1 << lg2), so that the expression +// i*elem_size does not result in an actual multiplication. +UPB_INLINE void _upb_Array_Set(upb_Array* arr, size_t i, const void* data, + size_t elem_size) { + UPB_ASSERT(i < arr->size); + UPB_ASSERT(elem_size == 1U << _upb_Array_ElementSizeLg2(arr)); + char* arr_data = (char*)_upb_array_ptr(arr); + memcpy(arr_data + (i * elem_size), data, elem_size); } -UPB_INLINE bool upb_IsSubMessage(const struct upb_MiniTableField* field) { - return field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message || - field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group; +UPB_INLINE void _upb_array_detach(const void* msg, size_t ofs) { + *UPB_PTR_AT(msg, ofs, upb_Array*) = NULL; } #ifdef __cplusplus @@ -753,1247 +949,1055 @@ UPB_INLINE bool upb_IsSubMessage(const struct upb_MiniTableField* field) { #endif -#endif /* UPB_MINI_TABLE_INTERNAL_FIELD_H_ */ +#endif /* UPB_COLLECTIONS_INTERNAL_ARRAY_H_ */ -#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ -#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ +#ifndef UPB_COLLECTIONS_MAP_H_ +#define UPB_COLLECTIONS_MAP_H_ + +#include // Must be last. -struct upb_Decoder; -typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr, - upb_Message* msg, intptr_t table, - uint64_t hasbits, uint64_t data); -typedef struct { - uint64_t field_data; - _upb_FieldParser* field_parser; -} _upb_FastTable_Entry; +typedef struct upb_Map upb_Map; -typedef enum { - kUpb_ExtMode_NonExtendable = 0, // Non-extendable message. - kUpb_ExtMode_Extendable = 1, // Normal extendable message. - kUpb_ExtMode_IsMessageSet = 2, // MessageSet message. - kUpb_ExtMode_IsMessageSet_ITEM = - 3, // MessageSet item (temporary only, see decode.c) +#ifdef __cplusplus +extern "C" { +#endif - // During table building we steal a bit to indicate that the message is a map - // entry. *Only* used during table building! - kUpb_ExtMode_IsMapEntry = 4, -} upb_ExtMode; +// Creates a new map on the given arena with the given key/value size. +UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, + upb_CType value_type); -union upb_MiniTableSub; +// Returns the number of entries in the map. +UPB_API size_t upb_Map_Size(const upb_Map* map); -// upb_MiniTable represents the memory layout of a given upb_MessageDef. -// The members are public so generated code can initialize them, -// but users MUST NOT directly read or write any of its members. -struct upb_MiniTable { - const union upb_MiniTableSub* subs; - const struct upb_MiniTableField* fields; +// Stores a value for the given key into |*val| (or the zero value if the key is +// not present). Returns whether the key was present. The |val| pointer may be +// NULL, in which case the function tests whether the given key is present. +UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, + upb_MessageValue* val); - // Must be aligned to sizeof(void*). Doesn't include internal members like - // unknown fields, extension dict, pointer to msglayout, etc. - uint16_t size; +// Removes all entries in the map. +UPB_API void upb_Map_Clear(upb_Map* map); - uint16_t field_count; - uint8_t ext; // upb_ExtMode, declared as uint8_t so sizeof(ext) == 1 - uint8_t dense_below; - uint8_t table_mask; - uint8_t required_count; // Required fields have the lowest hasbits. +typedef enum { + kUpb_MapInsertStatus_Inserted = 0, + kUpb_MapInsertStatus_Replaced = 1, + kUpb_MapInsertStatus_OutOfMemory = 2, +} upb_MapInsertStatus; - // To statically initialize the tables of variable length, we need a flexible - // array member, and we need to compile in gnu99 mode (constant initialization - // of flexible array members is a GNU extension, not in C99 unfortunately. - _upb_FastTable_Entry fasttable[]; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -// A MiniTable for an empty message, used for unlinked sub-messages. -extern const struct upb_MiniTable _kUpb_MiniTable_Empty; +// Sets the given key to the given value, returning whether the key was inserted +// or replaced. If the key was inserted, then any existing iterators will be +// invalidated. +UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, + upb_Arena* arena); -// Computes a bitmask in which the |l->required_count| lowest bits are set, -// except that we skip the lowest bit (because upb never uses hasbit 0). -// -// Sample output: -// requiredmask(1) => 0b10 (0x2) -// requiredmask(5) => 0b111110 (0x3e) -UPB_INLINE uint64_t upb_MiniTable_requiredmask(const struct upb_MiniTable* l) { - int n = l->required_count; - assert(0 < n && n <= 63); - return ((1ULL << n) - 1) << 1; +// Sets the given key to the given value. Returns false if memory allocation +// failed. If the key is newly inserted, then any existing iterators will be +// invalidated. +UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, upb_Arena* arena) { + return upb_Map_Insert(map, key, val, arena) != + kUpb_MapInsertStatus_OutOfMemory; } -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ */ - -#ifndef UPB_MINI_TABLE_INTERNAL_SUB_H_ -#define UPB_MINI_TABLE_INTERNAL_SUB_H_ - +// Deletes this key from the table. Returns true if the key was present. +// If present and |val| is non-NULL, stores the deleted value. +UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, + upb_MessageValue* val); -union upb_MiniTableSub { - const struct upb_MiniTable* submsg; - const struct upb_MiniTableEnum* subenum; -}; +// (DEPRECATED and going away soon. Do not use.) +UPB_INLINE bool upb_Map_Delete2(upb_Map* map, upb_MessageValue key, + upb_MessageValue* val) { + return upb_Map_Delete(map, key, val); +} -#endif /* UPB_MINI_TABLE_INTERNAL_SUB_H_ */ +// Map iteration: +// +// size_t iter = kUpb_Map_Begin; +// upb_MessageValue key, val; +// while (upb_Map_Next(map, &key, &val, &iter)) { +// ... +// } -// Must be last. +#define kUpb_Map_Begin ((size_t)-1) -#ifdef __cplusplus -extern "C" { -#endif +// Advances to the next entry. Returns false if no more entries are present. +// Otherwise returns true and populates both *key and *value. +UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, + upb_MessageValue* val, size_t* iter); -typedef struct upb_MiniTableField upb_MiniTableField; +// Sets the value for the entry pointed to by iter. +// WARNING: this does not currently work for string values! +UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, + upb_MessageValue val); -UPB_API_INLINE upb_FieldType -upb_MiniTableField_Type(const upb_MiniTableField* field) { - if (field->mode & kUpb_LabelFlags_IsAlternate) { - if (field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Int32) { - return kUpb_FieldType_Enum; - } else if (field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bytes) { - return kUpb_FieldType_String; - } else { - UPB_ASSERT(false); - } - } - return (upb_FieldType)field->UPB_PRIVATE(descriptortype); -} +// DEPRECATED iterator, slated for removal. -UPB_API_INLINE upb_CType upb_MiniTableField_CType(const upb_MiniTableField* f) { - switch (upb_MiniTableField_Type(f)) { - case kUpb_FieldType_Double: - return kUpb_CType_Double; - case kUpb_FieldType_Float: - return kUpb_CType_Float; - case kUpb_FieldType_Int64: - case kUpb_FieldType_SInt64: - case kUpb_FieldType_SFixed64: - return kUpb_CType_Int64; - case kUpb_FieldType_Int32: - case kUpb_FieldType_SFixed32: - case kUpb_FieldType_SInt32: - return kUpb_CType_Int32; - case kUpb_FieldType_UInt64: - case kUpb_FieldType_Fixed64: - return kUpb_CType_UInt64; - case kUpb_FieldType_UInt32: - case kUpb_FieldType_Fixed32: - return kUpb_CType_UInt32; - case kUpb_FieldType_Enum: - return kUpb_CType_Enum; - case kUpb_FieldType_Bool: - return kUpb_CType_Bool; - case kUpb_FieldType_String: - return kUpb_CType_String; - case kUpb_FieldType_Bytes: - return kUpb_CType_Bytes; - case kUpb_FieldType_Group: - case kUpb_FieldType_Message: - return kUpb_CType_Message; - } - UPB_UNREACHABLE(); -} +/* Map iteration: + * + * size_t iter = kUpb_Map_Begin; + * while (upb_MapIterator_Next(map, &iter)) { + * upb_MessageValue key = upb_MapIterator_Key(map, iter); + * upb_MessageValue val = upb_MapIterator_Value(map, iter); + * } + */ -UPB_API_INLINE bool upb_MiniTableField_IsExtension( - const upb_MiniTableField* field) { - return field->mode & kUpb_LabelFlags_IsExtension; -} +// Advances to the next entry. Returns false if no more entries are present. +UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter); -UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( - const upb_MiniTableField* field) { - return field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum; -} +// Returns true if the iterator still points to a valid entry, or false if the +// iterator is past the last element. It is an error to call this function with +// kUpb_Map_Begin (you must call next() at least once first). +UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter); -UPB_API_INLINE bool upb_MiniTableField_HasPresence( - const upb_MiniTableField* field) { - if (upb_MiniTableField_IsExtension(field)) { - return !upb_IsRepeatedOrMap(field); - } else { - return field->presence != 0; - } -} +// Returns the key and value for this entry of the map. +UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter); +UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_FIELD_H_ */ +#endif /* UPB_COLLECTIONS_MAP_H_ */ -// Must be last. +// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// -#ifdef __cplusplus -extern "C" { -#endif +#ifndef UPB_COLLECTIONS_INTERNAL_MAP_H_ +#define UPB_COLLECTIONS_INTERNAL_MAP_H_ -typedef struct upb_MiniTable upb_MiniTable; -UPB_API const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( - const upb_MiniTable* table, uint32_t number); +#ifndef UPB_HASH_STR_TABLE_H_ +#define UPB_HASH_STR_TABLE_H_ -UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_GetFieldByIndex( - const upb_MiniTable* t, uint32_t index) { - return &t->fields[index]; -} -// Returns the MiniTable for this message field. If the field is unlinked, -// returns NULL. -UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( - const upb_MiniTable* mini_table, const upb_MiniTableField* field) { - UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Message); - const upb_MiniTable* ret = - mini_table->subs[field->UPB_PRIVATE(submsg_index)].submsg; - UPB_ASSUME(ret); - return ret == &_kUpb_MiniTable_Empty ? NULL : ret; -} +/* + * upb_table + * + * This header is INTERNAL-ONLY! Its interfaces are not public or stable! + * This file defines very fast int->upb_value (inttable) and string->upb_value + * (strtable) hash tables. + * + * The table uses chained scatter with Brent's variation (inspired by the Lua + * implementation of hash tables). The hash function for strings is Austin + * Appleby's "MurmurHash." + * + * The inttable uses uintptr_t as its key, which guarantees it can be used to + * store pointers or integers of at least 32 bits (upb isn't really useful on + * systems where sizeof(void*) < 4). + * + * The table must be homogeneous (all values of the same type). In debug + * mode, we check this on insert and lookup. + */ -// Returns the MiniTableEnum for this enum field. If the field is unlinked, -// returns NULL. -UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( - const upb_MiniTable* mini_table, const upb_MiniTableField* field) { - UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Enum); - return mini_table->subs[field->UPB_PRIVATE(submsg_index)].subenum; -} +#ifndef UPB_HASH_COMMON_H_ +#define UPB_HASH_COMMON_H_ -// Returns true if this MiniTable field is linked to a MiniTable for the -// sub-message. -UPB_API_INLINE bool upb_MiniTable_MessageFieldIsLinked( - const upb_MiniTable* mini_table, const upb_MiniTableField* field) { - return upb_MiniTable_GetSubMessageTable(mini_table, field) != NULL; -} +#include -// If this field is in a oneof, returns the first field in the oneof. -// -// Otherwise returns NULL. -// -// Usage: -// const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f); -// do { -// .. -// } while (upb_MiniTable_NextOneofField(m, &field); -// -const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, - const upb_MiniTableField* f); -// Iterates to the next field in the oneof. If this is the last field in the -// oneof, returns false. The ordering of fields in the oneof is not -// guaranteed. -// REQUIRES: |f| is the field initialized by upb_MiniTable_GetOneof and updated -// by prior upb_MiniTable_NextOneofField calls. -bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, - const upb_MiniTableField** f); +// Must be last. #ifdef __cplusplus -} /* extern "C" */ +extern "C" { #endif +/* upb_value ******************************************************************/ -#endif /* UPB_MINI_TABLE_MESSAGE_H_ */ - -// Must be last. - -typedef struct upb_Array upb_Array; -typedef struct upb_Map upb_Map; - -typedef union { - bool bool_val; - float float_val; - double double_val; - int32_t int32_val; - int64_t int64_val; - uint32_t uint32_val; - uint64_t uint64_val; - const upb_Array* array_val; - const upb_Map* map_val; - const upb_Message* msg_val; - upb_StringView str_val; - - // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of - // msg_val if unlinked sub-messages may possibly be in use. See the - // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more - // information. - upb_TaggedMessagePtr tagged_msg_val; -} upb_MessageValue; - -typedef union { - upb_Array* array; - upb_Map* map; - upb_Message* msg; -} upb_MutableMessageValue; - +typedef struct { + uint64_t val; +} upb_value; -#endif /* UPB_MESSAGE_VALUE_H_ */ +UPB_INLINE void _upb_value_setval(upb_value* v, uint64_t val) { v->val = val; } -/* upb_Arena is a specific allocator implementation that uses arena allocation. - * The user provides an allocator that will be used to allocate the underlying - * arena blocks. Arenas by nature do not require the individual allocations - * to be freed. However the Arena does allow users to register cleanup - * functions that will run when the arena is destroyed. +/* For each value ctype, define the following set of functions: * - * A upb_Arena is *not* thread-safe. + * // Get/set an int32 from a upb_value. + * int32_t upb_value_getint32(upb_value val); + * void upb_value_setint32(upb_value *val, int32_t cval); * - * You could write a thread-safe arena allocator that satisfies the - * upb_alloc interface, but it would not be as efficient for the - * single-threaded case. */ - -#ifndef UPB_MEM_ARENA_H_ -#define UPB_MEM_ARENA_H_ + * // Construct a new upb_value from an int32. + * upb_value upb_value_int32(int32_t val); */ +#define FUNCS(name, membername, type_t, converter) \ + UPB_INLINE void upb_value_set##name(upb_value* val, type_t cval) { \ + val->val = (converter)cval; \ + } \ + UPB_INLINE upb_value upb_value_##name(type_t val) { \ + upb_value ret; \ + upb_value_set##name(&ret, val); \ + return ret; \ + } \ + UPB_INLINE type_t upb_value_get##name(upb_value val) { \ + return (type_t)(converter)val.val; \ + } -#include -#include -#include +FUNCS(int32, int32, int32_t, int32_t) +FUNCS(int64, int64, int64_t, int64_t) +FUNCS(uint32, uint32, uint32_t, uint32_t) +FUNCS(uint64, uint64, uint64_t, uint64_t) +FUNCS(bool, _bool, bool, bool) +FUNCS(cstr, cstr, char*, uintptr_t) +FUNCS(uintptr, uptr, uintptr_t, uintptr_t) +FUNCS(ptr, ptr, void*, uintptr_t) +FUNCS(constptr, constptr, const void*, uintptr_t) +#undef FUNCS -#ifndef UPB_MEM_ALLOC_H_ -#define UPB_MEM_ALLOC_H_ +UPB_INLINE void upb_value_setfloat(upb_value* val, float cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} -// Must be last. +UPB_INLINE void upb_value_setdouble(upb_value* val, double cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_INLINE upb_value upb_value_float(float cval) { + upb_value ret; + upb_value_setfloat(&ret, cval); + return ret; +} -typedef struct upb_alloc upb_alloc; +UPB_INLINE upb_value upb_value_double(double cval) { + upb_value ret; + upb_value_setdouble(&ret, cval); + return ret; +} -/* A combined `malloc()`/`free()` function. - * If `size` is 0 then the function acts like `free()`, otherwise it acts like - * `realloc()`. Only `oldsize` bytes from a previous allocation are - * preserved. */ -typedef void* upb_alloc_func(upb_alloc* alloc, void* ptr, size_t oldsize, - size_t size); +/* upb_tabkey *****************************************************************/ -/* A upb_alloc is a possibly-stateful allocator object. +/* Either: + * 1. an actual integer key, or + * 2. a pointer to a string prefixed by its uint32_t length, owned by us. * - * It could either be an arena allocator (which doesn't require individual - * `free()` calls) or a regular `malloc()` (which does). The client must - * therefore free memory unless it knows that the allocator is an arena - * allocator. */ -struct upb_alloc { - upb_alloc_func* func; -}; + * ...depending on whether this is a string table or an int table. We would + * make this a union of those two types, but C89 doesn't support statically + * initializing a non-first union member. */ +typedef uintptr_t upb_tabkey; -UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, NULL, 0, size); +UPB_INLINE char* upb_tabstr(upb_tabkey key, uint32_t* len) { + char* mem = (char*)key; + if (len) memcpy(len, mem, sizeof(*len)); + return mem + sizeof(*len); } -UPB_INLINE void* upb_realloc(upb_alloc* alloc, void* ptr, size_t oldsize, - size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, ptr, oldsize, size); +UPB_INLINE upb_StringView upb_tabstrview(upb_tabkey key) { + upb_StringView ret; + uint32_t len; + ret.data = upb_tabstr(key, &len); + ret.size = len; + return ret; } -UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) { - UPB_ASSERT(alloc); - alloc->func(alloc, ptr, 0, 0); -} +/* upb_tabval *****************************************************************/ -// The global allocator used by upb. Uses the standard malloc()/free(). +typedef struct upb_tabval { + uint64_t val; +} upb_tabval; -extern upb_alloc upb_alloc_global; +#define UPB_TABVALUE_EMPTY_INIT \ + { -1 } -/* Functions that hard-code the global malloc. - * - * We still get benefit because we can put custom logic into our global - * allocator, like injecting out-of-memory faults in debug/testing builds. */ +/* upb_table ******************************************************************/ -UPB_INLINE void* upb_gmalloc(size_t size) { - return upb_malloc(&upb_alloc_global, size); -} +typedef struct _upb_tabent { + upb_tabkey key; + upb_tabval val; -UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) { - return upb_realloc(&upb_alloc_global, ptr, oldsize, size); + /* Internal chaining. This is const so we can create static initializers for + * tables. We cast away const sometimes, but *only* when the containing + * upb_table is known to be non-const. This requires a bit of care, but + * the subtlety is confined to table.c. */ + const struct _upb_tabent* next; +} upb_tabent; + +typedef struct { + size_t count; /* Number of entries in the hash part. */ + uint32_t mask; /* Mask to turn hash value -> bucket. */ + uint32_t max_count; /* Max count before we hit our load limit. */ + uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ + upb_tabent* entries; +} upb_table; + +UPB_INLINE size_t upb_table_size(const upb_table* t) { + return t->size_lg2 ? 1 << t->size_lg2 : 0; } -UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); } +// Internal-only functions, in .h file only out of necessity. + +UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; } + +uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MEM_ALLOC_H_ */ +#endif /* UPB_HASH_COMMON_H_ */ // Must be last. -typedef struct upb_Arena upb_Arena; - typedef struct { - char *ptr, *end; -} _upb_ArenaHead; + upb_table t; +} upb_strtable; #ifdef __cplusplus extern "C" { #endif -// Creates an arena from the given initial block (if any -- n may be 0). -// Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this -// is a fixed-size arena and cannot grow. -UPB_API upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc); - -UPB_API void upb_Arena_Free(upb_Arena* a); -UPB_API bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b); - -void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size); -size_t upb_Arena_SpaceAllocated(upb_Arena* arena); -uint32_t upb_Arena_DebugRefCount(upb_Arena* arena); +// Initialize a table. If memory allocation failed, false is returned and +// the table is uninitialized. +bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a); -UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) { - _upb_ArenaHead* h = (_upb_ArenaHead*)a; - return (size_t)(h->end - h->ptr); +// Returns the number of values in the table. +UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) { + return t->t.count; } -UPB_API_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) { - size = UPB_ALIGN_MALLOC(size); - size_t span = size + UPB_ASAN_GUARD_SIZE; - if (UPB_UNLIKELY(_upb_ArenaHas(a) < span)) { - return _upb_Arena_SlowMalloc(a, size); - } - - // We have enough space to do a fast malloc. - _upb_ArenaHead* h = (_upb_ArenaHead*)a; - void* ret = h->ptr; - UPB_ASSERT(UPB_ALIGN_MALLOC((uintptr_t)ret) == (uintptr_t)ret); - UPB_ASSERT(UPB_ALIGN_MALLOC(size) == size); - UPB_UNPOISON_MEMORY_REGION(ret, size); +void upb_strtable_clear(upb_strtable* t); - h->ptr += span; +// Inserts the given key into the hashtable with the given value. +// The key must not already exist in the hash table. The key is not required +// to be NULL-terminated, and the table will make an internal copy of the key. +// +// If a table resize was required but memory allocation failed, false is +// returned and the table is unchanged. */ +bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len, + upb_value val, upb_Arena* a); - return ret; -} +// Looks up key in this table, returning "true" if the key was found. +// If v is non-NULL, copies the value for this key into *v. +bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len, + upb_value* v); -// Shrinks the last alloc from arena. -// REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena. -// We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if -// this was not the last alloc. -UPB_API_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, - size_t oldsize, size_t size) { - _upb_ArenaHead* h = (_upb_ArenaHead*)a; - oldsize = UPB_ALIGN_MALLOC(oldsize); - size = UPB_ALIGN_MALLOC(size); - // Must be the last alloc. - UPB_ASSERT((char*)ptr + oldsize == h->ptr - UPB_ASAN_GUARD_SIZE); - UPB_ASSERT(size <= oldsize); - h->ptr = (char*)ptr + size; +// For NULL-terminated strings. +UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key, + upb_value* v) { + return upb_strtable_lookup2(t, key, strlen(key), v); } -UPB_API_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize, - size_t size) { - _upb_ArenaHead* h = (_upb_ArenaHead*)a; - oldsize = UPB_ALIGN_MALLOC(oldsize); - size = UPB_ALIGN_MALLOC(size); - bool is_most_recent_alloc = (uintptr_t)ptr + oldsize == (uintptr_t)h->ptr; - - if (is_most_recent_alloc) { - ptrdiff_t diff = size - oldsize; - if ((ptrdiff_t)_upb_ArenaHas(a) >= diff) { - h->ptr += diff; - return ptr; - } - } else if (size <= oldsize) { - return ptr; - } - - void* ret = upb_Arena_Malloc(a, size); - - if (ret && oldsize > 0) { - memcpy(ret, ptr, UPB_MIN(oldsize, size)); - } - - return ret; -} +// Removes an item from the table. Returns true if the remove was successful, +// and stores the removed item in *val if non-NULL. +bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len, + upb_value* val); -UPB_API_INLINE upb_Arena* upb_Arena_New(void) { - return upb_Arena_Init(NULL, 0, &upb_alloc_global); +UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key, + upb_value* v) { + return upb_strtable_remove2(t, key, strlen(key), v); } -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_MEM_ARENA_H_ */ - -// Must be last. - -#ifdef __cplusplus -extern "C" { -#endif - -// Creates a new array on the given arena that holds elements of this type. -UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type); - -// Returns the number of elements in the array. -UPB_API size_t upb_Array_Size(const upb_Array* arr); - -// Returns the given element, which must be within the array's current size. -UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i); +// Exposed for testing only. +bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a); -// Sets the given element, which must be within the array's current size. -UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val); +/* Iteration over strtable: + * + * intptr_t iter = UPB_STRTABLE_BEGIN; + * upb_StringView key; + * upb_value val; + * while (upb_strtable_next2(t, &key, &val, &iter)) { + * // ... + * } + */ -// Appends an element to the array. Returns false on allocation failure. -UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val, - upb_Arena* arena); +#define UPB_STRTABLE_BEGIN -1 -// Moves elements within the array using memmove(). -// Like memmove(), the source and destination elements may be overlapping. -UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx, - size_t count); +bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, + upb_value* val, intptr_t* iter); +void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter); +void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v); -// Inserts one or more empty elements into the array. -// Existing elements are shifted right. -// The new elements have undefined state and must be set with `upb_Array_Set()`. -// REQUIRES: `i <= upb_Array_Size(arr)` -UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count, - upb_Arena* arena); +/* DEPRECATED iterators, slated for removal. + * + * Iterators for string tables. We are subject to some kind of unusual + * design constraints: + * + * For high-level languages: + * - we must be able to guarantee that we don't crash or corrupt memory even if + * the program accesses an invalidated iterator. + * + * For C++11 range-based for: + * - iterators must be copyable + * - iterators must be comparable + * - it must be possible to construct an "end" value. + * + * Iteration order is undefined. + * + * Modifying the table invalidates iterators. upb_{str,int}table_done() is + * guaranteed to work even on an invalidated iterator, as long as the table it + * is iterating over has not been freed. Calling next() or accessing data from + * an invalidated iterator yields unspecified elements from the table, but it is + * guaranteed not to crash and to return real table elements (except when done() + * is true). */ +/* upb_strtable_iter **********************************************************/ -// Deletes one or more elements from the array. -// Existing elements are shifted left. -// REQUIRES: `i + count <= upb_Array_Size(arr)` -UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count); +/* upb_strtable_iter i; + * upb_strtable_begin(&i, t); + * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + * const char *key = upb_strtable_iter_key(&i); + * const upb_value val = upb_strtable_iter_value(&i); + * // ... + * } + */ -// Changes the size of a vector. New elements are initialized to NULL/0. -// Returns false on allocation failure. -UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena); +typedef struct { + const upb_strtable* t; + size_t index; +} upb_strtable_iter; -// Returns pointer to array data. -UPB_API const void* upb_Array_DataPtr(const upb_Array* arr); +UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) { + return &i->t->t.entries[i->index]; +} -// Returns mutable pointer to array data. -UPB_API void* upb_Array_MutableDataPtr(upb_Array* arr); +void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t); +void upb_strtable_next(upb_strtable_iter* i); +bool upb_strtable_done(const upb_strtable_iter* i); +upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i); +upb_value upb_strtable_iter_value(const upb_strtable_iter* i); +void upb_strtable_iter_setdone(upb_strtable_iter* i); +bool upb_strtable_iter_isequal(const upb_strtable_iter* i1, + const upb_strtable_iter* i2); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_COLLECTIONS_ARRAY_H_ */ +#endif /* UPB_HASH_STR_TABLE_H_ */ // Must be last. +struct upb_Map { + // Size of key and val, based on the map type. + // Strings are represented as '0' because they must be handled specially. + char key_size; + char val_size; + + upb_strtable table; +}; + #ifdef __cplusplus extern "C" { #endif -// LINT.IfChange(struct_definition) -// Our internal representation for repeated fields. -struct upb_Array { - uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */ - size_t size; /* The number of elements in the array. */ - size_t capacity; /* Allocated storage. Measured in elements. */ -}; -// LINT.ThenChange(GoogleInternalName1) +// Converting between internal table representation and user values. +// +// _upb_map_tokey() and _upb_map_fromkey() are inverses. +// _upb_map_tovalue() and _upb_map_fromvalue() are inverses. +// +// These functions account for the fact that strings are treated differently +// from other types when stored in a map. -UPB_INLINE size_t _upb_Array_ElementSizeLg2(const upb_Array* arr) { - size_t ret = arr->data & 7; - UPB_ASSERT(ret <= 4); - return ret; +UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + return *(upb_StringView*)key; + } else { + return upb_StringView_FromDataAndSize((const char*)key, size); + } } -UPB_INLINE const void* _upb_array_constptr(const upb_Array* arr) { - _upb_Array_ElementSizeLg2(arr); // Check assertion. - return (void*)(arr->data & ~(uintptr_t)7); +UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + memcpy(out, &key, sizeof(key)); + } else { + memcpy(out, key.data, size); + } } -UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) { - UPB_ASSERT(elem_size_lg2 <= 4); - return (uintptr_t)ptr | elem_size_lg2; +UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size, + upb_value* msgval, upb_Arena* a) { + if (size == UPB_MAPTYPE_STRING) { + upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp)); + if (!strp) return false; + *strp = *(upb_StringView*)val; + *msgval = upb_value_ptr(strp); + } else { + memcpy(msgval, val, size); + } + return true; } -UPB_INLINE void* _upb_array_ptr(upb_Array* arr) { - return (void*)_upb_array_constptr(arr); +UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val); + memcpy(out, strp, sizeof(upb_StringView)); + } else { + memcpy(out, &val, size); + } } -UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) { - UPB_ASSERT(elem_size_lg2 <= 4); - UPB_ASSERT(((uintptr_t)ptr & 7) == 0); - return (uintptr_t)ptr | (unsigned)elem_size_lg2; +UPB_INLINE void* _upb_map_next(const upb_Map* map, size_t* iter) { + upb_strtable_iter it; + it.t = &map->table; + it.index = *iter; + upb_strtable_next(&it); + *iter = it.index; + if (upb_strtable_done(&it)) return NULL; + return (void*)str_tabent(&it); } -extern const char _upb_Array_CTypeSizeLg2Table[]; - -UPB_INLINE size_t _upb_Array_CTypeSizeLg2(upb_CType ctype) { - return _upb_Array_CTypeSizeLg2Table[ctype]; +UPB_INLINE void _upb_Map_Clear(upb_Map* map) { + upb_strtable_clear(&map->table); } -UPB_INLINE upb_Array* _upb_Array_New(upb_Arena* a, size_t init_capacity, - int elem_size_lg2) { - UPB_ASSERT(elem_size_lg2 <= 4); - const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_Array), UPB_MALLOC_ALIGN); - const size_t bytes = arr_size + (init_capacity << elem_size_lg2); - upb_Array* arr = (upb_Array*)upb_Arena_Malloc(a, bytes); - if (!arr) return NULL; - arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2); - arr->size = 0; - arr->capacity = init_capacity; - return arr; +UPB_INLINE bool _upb_Map_Delete(upb_Map* map, const void* key, size_t key_size, + upb_value* val) { + upb_StringView k = _upb_map_tokey(key, key_size); + return upb_strtable_remove2(&map->table, k.data, k.size, val); } -// Resizes the capacity of the array to be at least min_size. -bool _upb_array_realloc(upb_Array* arr, size_t min_size, upb_Arena* arena); - -UPB_INLINE bool _upb_array_reserve(upb_Array* arr, size_t size, - upb_Arena* arena) { - if (arr->capacity < size) return _upb_array_realloc(arr, size, arena); - return true; +UPB_INLINE bool _upb_Map_Get(const upb_Map* map, const void* key, + size_t key_size, void* val, size_t val_size) { + upb_value tabval; + upb_StringView k = _upb_map_tokey(key, key_size); + bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); + if (ret && val) { + _upb_map_fromvalue(tabval, val, val_size); + } + return ret; } -// Resize without initializing new elements. -UPB_INLINE bool _upb_Array_ResizeUninitialized(upb_Array* arr, size_t size, - upb_Arena* arena) { - UPB_ASSERT(size <= arr->size || arena); // Allow NULL arena when shrinking. - if (!_upb_array_reserve(arr, size, arena)) return false; - arr->size = size; - return true; -} +UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(upb_Map* map, const void* key, + size_t key_size, void* val, + size_t val_size, upb_Arena* a) { + upb_StringView strkey = _upb_map_tokey(key, key_size); + upb_value tabval = {0}; + if (!_upb_map_tovalue(val, val_size, &tabval, a)) { + return kUpb_MapInsertStatus_OutOfMemory; + } -// This function is intended for situations where elem_size is compile-time -// constant or a known expression of the form (1 << lg2), so that the expression -// i*elem_size does not result in an actual multiplication. -UPB_INLINE void _upb_Array_Set(upb_Array* arr, size_t i, const void* data, - size_t elem_size) { - UPB_ASSERT(i < arr->size); - UPB_ASSERT(elem_size == 1U << _upb_Array_ElementSizeLg2(arr)); - char* arr_data = (char*)_upb_array_ptr(arr); - memcpy(arr_data + (i * elem_size), data, elem_size); + // TODO(haberman): add overwrite operation to minimize number of lookups. + bool removed = + upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL); + if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) { + return kUpb_MapInsertStatus_OutOfMemory; + } + return removed ? kUpb_MapInsertStatus_Replaced + : kUpb_MapInsertStatus_Inserted; } -UPB_INLINE void _upb_array_detach(const void* msg, size_t ofs) { - *UPB_PTR_AT(msg, ofs, upb_Array*) = NULL; +UPB_INLINE size_t _upb_Map_Size(const upb_Map* map) { + return map->table.t.count; } -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_COLLECTIONS_INTERNAL_ARRAY_H_ */ - -#ifndef UPB_COLLECTIONS_MAP_H_ -#define UPB_COLLECTIONS_MAP_H_ +// Strings/bytes are special-cased in maps. +extern char _upb_Map_CTypeSizeTable[12]; +UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) { + return _upb_Map_CTypeSizeTable[ctype]; +} -// Must be last. +// Creates a new map on the given arena with this key/value type. +upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size); #ifdef __cplusplus -extern "C" { +} /* extern "C" */ #endif -// Creates a new map on the given arena with the given key/value size. -UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, - upb_CType value_type); - -// Returns the number of entries in the map. -UPB_API size_t upb_Map_Size(const upb_Map* map); - -// Stores a value for the given key into |*val| (or the zero value if the key is -// not present). Returns whether the key was present. The |val| pointer may be -// NULL, in which case the function tests whether the given key is present. -UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, - upb_MessageValue* val); -// Removes all entries in the map. -UPB_API void upb_Map_Clear(upb_Map* map); +#endif /* UPB_COLLECTIONS_INTERNAL_MAP_H_ */ -typedef enum { - kUpb_MapInsertStatus_Inserted = 0, - kUpb_MapInsertStatus_Replaced = 1, - kUpb_MapInsertStatus_OutOfMemory = 2, -} upb_MapInsertStatus; +// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// -// Sets the given key to the given value, returning whether the key was inserted -// or replaced. If the key was inserted, then any existing iterators will be -// invalidated. -UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, - upb_Arena* arena); +#ifndef UPB_COLLECTIONS_INTERNAL_MAP_SORTER_H_ +#define UPB_COLLECTIONS_INTERNAL_MAP_SORTER_H_ -// Sets the given key to the given value. Returns false if memory allocation -// failed. If the key is newly inserted, then any existing iterators will be -// invalidated. -UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, upb_Arena* arena) { - return upb_Map_Insert(map, key, val, arena) != - kUpb_MapInsertStatus_OutOfMemory; -} +#include -// Deletes this key from the table. Returns true if the key was present. -// If present and |val| is non-NULL, stores the deleted value. -UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, - upb_MessageValue* val); -// (DEPRECATED and going away soon. Do not use.) -UPB_INLINE bool upb_Map_Delete2(upb_Map* map, upb_MessageValue key, - upb_MessageValue* val) { - return upb_Map_Delete(map, key, val); -} +#ifndef UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ +#define UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ -// Map iteration: -// -// size_t iter = kUpb_Map_Begin; -// upb_MessageValue key, val; -// while (upb_Map_Next(map, &key, &val, &iter)) { -// ... -// } -#define kUpb_Map_Begin ((size_t)-1) +#ifndef UPB_MINI_TABLE_INTERNAL_TYPES_H_ +#define UPB_MINI_TABLE_INTERNAL_TYPES_H_ -// Advances to the next entry. Returns false if no more entries are present. -// Otherwise returns true and populates both *key and *value. -UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, - upb_MessageValue* val, size_t* iter); +typedef struct upb_Message_InternalData upb_Message_InternalData; -// Sets the value for the entry pointed to by iter. -// WARNING: this does not currently work for string values! -UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, - upb_MessageValue val); +typedef struct { + union { + upb_Message_InternalData* internal; -// DEPRECATED iterator, slated for removal. + // Force 8-byte alignment, since the data members may contain members that + // require 8-byte alignment. + double d; + }; +} upb_Message_Internal; -/* Map iteration: - * - * size_t iter = kUpb_Map_Begin; - * while (upb_MapIterator_Next(map, &iter)) { - * upb_MessageValue key = upb_MapIterator_Key(map, iter); - * upb_MessageValue val = upb_MapIterator_Value(map, iter); - * } - */ +#endif // UPB_MINI_TABLE_INTERNAL_TYPES_H_ -// Advances to the next entry. Returns false if no more entries are present. -UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter); +// Map entries aren't actually stored for map fields, they are only used during +// parsing. For parsing, it helps a lot if all map entry messages have the same +// layout. The layout code in mini_table/decode.c will ensure that all map +// entries have this layout. +// +// Note that users can and do create map entries directly, which will also use +// this layout. +// +// NOTE: sync with wire/decode.c. +typedef struct { + // We only need 2 hasbits max, but due to alignment we'll use 8 bytes here, + // and the uint64_t helps make this clear. + uint64_t hasbits; + union { + upb_StringView str; // For str/bytes. + upb_value val; // For all other types. + } k; + union { + upb_StringView str; // For str/bytes. + upb_value val; // For all other types. + } v; +} upb_MapEntryData; -// Returns true if the iterator still points to a valid entry, or false if the -// iterator is past the last element. It is an error to call this function with -// kUpb_Map_Begin (you must call next() at least once first). -UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter); +typedef struct { + upb_Message_Internal internal; + upb_MapEntryData data; +} upb_MapEntry; -// Returns the key and value for this entry of the map. -UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter); -UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter); +#endif // UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ -#ifdef __cplusplus -} /* extern "C" */ -#endif +#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_ +#define UPB_MESSAGE_INTERNAL_EXTENSION_H_ -#endif /* UPB_COLLECTIONS_MAP_H_ */ +// Public APIs for message operations that do not depend on the schema. +// +// MiniTable-based accessors live in accessors.h. -// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// +#ifndef UPB_MESSAGE_MESSAGE_H_ +#define UPB_MESSAGE_MESSAGE_H_ -#ifndef UPB_COLLECTIONS_INTERNAL_MAP_H_ -#define UPB_COLLECTIONS_INTERNAL_MAP_H_ +#include -#ifndef UPB_HASH_STR_TABLE_H_ -#define UPB_HASH_STR_TABLE_H_ +#ifndef UPB_MINI_TABLE_MESSAGE_H_ +#define UPB_MINI_TABLE_MESSAGE_H_ -/* - * upb_table - * - * This header is INTERNAL-ONLY! Its interfaces are not public or stable! - * This file defines very fast int->upb_value (inttable) and string->upb_value - * (strtable) hash tables. - * - * The table uses chained scatter with Brent's variation (inspired by the Lua - * implementation of hash tables). The hash function for strings is Austin - * Appleby's "MurmurHash." - * - * The inttable uses uintptr_t as its key, which guarantees it can be used to - * store pointers or integers of at least 32 bits (upb isn't really useful on - * systems where sizeof(void*) < 4). - * - * The table must be homogeneous (all values of the same type). In debug - * mode, we check this on insert and lookup. - */ +#ifndef UPB_MINI_TABLE_ENUM_H_ +#define UPB_MINI_TABLE_ENUM_H_ -#ifndef UPB_HASH_COMMON_H_ -#define UPB_HASH_COMMON_H_ -#include +#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_ +#define UPB_MINI_TABLE_INTERNAL_ENUM_H_ +#include // Must be last. +struct upb_MiniTableEnum { + uint32_t mask_limit; // Limit enum value that can be tested with mask. + uint32_t value_count; // Number of values after the bitfield. + uint32_t data[]; // Bitmask + enumerated values follow. +}; + +typedef enum { + _kUpb_FastEnumCheck_ValueIsInEnum = 0, + _kUpb_FastEnumCheck_ValueIsNotInEnum = 1, + _kUpb_FastEnumCheck_CannotCheckFast = 2, +} _kUpb_FastEnumCheck_Status; + #ifdef __cplusplus extern "C" { #endif -/* upb_value ******************************************************************/ - -typedef struct { - uint64_t val; -} upb_value; - -UPB_INLINE void _upb_value_setval(upb_value* v, uint64_t val) { v->val = val; } +UPB_INLINE _kUpb_FastEnumCheck_Status _upb_MiniTable_CheckEnumValueFast( + const struct upb_MiniTableEnum* e, uint32_t val) { + if (UPB_UNLIKELY(val >= 64)) return _kUpb_FastEnumCheck_CannotCheckFast; + uint64_t mask = e->data[0] | ((uint64_t)e->data[1] << 32); + return (mask & (1ULL << val)) ? _kUpb_FastEnumCheck_ValueIsInEnum + : _kUpb_FastEnumCheck_ValueIsNotInEnum; +} -/* For each value ctype, define the following set of functions: - * - * // Get/set an int32 from a upb_value. - * int32_t upb_value_getint32(upb_value val); - * void upb_value_setint32(upb_value *val, int32_t cval); - * - * // Construct a new upb_value from an int32. - * upb_value upb_value_int32(int32_t val); */ -#define FUNCS(name, membername, type_t, converter) \ - UPB_INLINE void upb_value_set##name(upb_value* val, type_t cval) { \ - val->val = (converter)cval; \ - } \ - UPB_INLINE upb_value upb_value_##name(type_t val) { \ - upb_value ret; \ - upb_value_set##name(&ret, val); \ - return ret; \ - } \ - UPB_INLINE type_t upb_value_get##name(upb_value val) { \ - return (type_t)(converter)val.val; \ +UPB_INLINE bool _upb_MiniTable_CheckEnumValueSlow( + const struct upb_MiniTableEnum* e, uint32_t val) { + if (val < e->mask_limit) return e->data[val / 32] & (1ULL << (val % 32)); + // OPT: binary search long lists? + const uint32_t* start = &e->data[e->mask_limit / 32]; + const uint32_t* limit = &e->data[(e->mask_limit / 32) + e->value_count]; + for (const uint32_t* p = start; p < limit; p++) { + if (*p == val) return true; } + return false; +} -FUNCS(int32, int32, int32_t, int32_t) -FUNCS(int64, int64, int64_t, int64_t) -FUNCS(uint32, uint32, uint32_t, uint32_t) -FUNCS(uint64, uint64, uint64_t, uint64_t) -FUNCS(bool, _bool, bool, bool) -FUNCS(cstr, cstr, char*, uintptr_t) -FUNCS(uintptr, uptr, uintptr_t, uintptr_t) -FUNCS(ptr, ptr, void*, uintptr_t) -FUNCS(constptr, constptr, const void*, uintptr_t) +#ifdef __cplusplus +} /* extern "C" */ +#endif -#undef FUNCS -UPB_INLINE void upb_value_setfloat(upb_value* val, float cval) { - memcpy(&val->val, &cval, sizeof(cval)); -} +#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */ -UPB_INLINE void upb_value_setdouble(upb_value* val, double cval) { - memcpy(&val->val, &cval, sizeof(cval)); -} +// Must be last -UPB_INLINE upb_value upb_value_float(float cval) { - upb_value ret; - upb_value_setfloat(&ret, cval); - return ret; -} +typedef struct upb_MiniTableEnum upb_MiniTableEnum; -UPB_INLINE upb_value upb_value_double(double cval) { - upb_value ret; - upb_value_setdouble(&ret, cval); - return ret; +// Validates enum value against range defined by enum mini table. +UPB_INLINE bool upb_MiniTableEnum_CheckValue(const struct upb_MiniTableEnum* e, + uint32_t val) { + _kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, val); + if (UPB_UNLIKELY(status == _kUpb_FastEnumCheck_CannotCheckFast)) { + return _upb_MiniTable_CheckEnumValueSlow(e, val); + } + return status == _kUpb_FastEnumCheck_ValueIsInEnum ? true : false; } -/* upb_tabkey *****************************************************************/ -/* Either: - * 1. an actual integer key, or - * 2. a pointer to a string prefixed by its uint32_t length, owned by us. - * - * ...depending on whether this is a string table or an int table. We would - * make this a union of those two types, but C89 doesn't support statically - * initializing a non-first union member. */ -typedef uintptr_t upb_tabkey; +#endif /* UPB_MINI_TABLE_ENUM_H_ */ -UPB_INLINE char* upb_tabstr(upb_tabkey key, uint32_t* len) { - char* mem = (char*)key; - if (len) memcpy(len, mem, sizeof(*len)); - return mem + sizeof(*len); -} +#ifndef UPB_MINI_TABLE_FIELD_H_ +#define UPB_MINI_TABLE_FIELD_H_ -UPB_INLINE upb_StringView upb_tabstrview(upb_tabkey key) { - upb_StringView ret; - uint32_t len; - ret.data = upb_tabstr(key, &len); - ret.size = len; - return ret; -} -/* upb_tabval *****************************************************************/ +#ifndef UPB_MINI_TABLE_INTERNAL_FIELD_H_ +#define UPB_MINI_TABLE_INTERNAL_FIELD_H_ -typedef struct upb_tabval { - uint64_t val; -} upb_tabval; +#include -#define UPB_TABVALUE_EMPTY_INIT \ - { -1 } -/* upb_table ******************************************************************/ +// Must be last. -typedef struct _upb_tabent { - upb_tabkey key; - upb_tabval val; +struct upb_MiniTableField { + uint32_t number; + uint16_t offset; + int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index - /* Internal chaining. This is const so we can create static initializers for - * tables. We cast away const sometimes, but *only* when the containing - * upb_table is known to be non-const. This requires a bit of care, but - * the subtlety is confined to table.c. */ - const struct _upb_tabent* next; -} upb_tabent; + // Indexes into `upb_MiniTable.subs` + // Will be set to `kUpb_NoSub` if `descriptortype` != MESSAGE/GROUP/ENUM + uint16_t UPB_PRIVATE(submsg_index); -typedef struct { - size_t count; /* Number of entries in the hash part. */ - uint32_t mask; /* Mask to turn hash value -> bucket. */ - uint32_t max_count; /* Max count before we hit our load limit. */ - uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ - upb_tabent* entries; -} upb_table; + uint8_t UPB_PRIVATE(descriptortype); -UPB_INLINE size_t upb_table_size(const upb_table* t) { - return t->size_lg2 ? 1 << t->size_lg2 : 0; -} + // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift) + uint8_t mode; +}; -// Internal-only functions, in .h file only out of necessity. +#define kUpb_NoSub ((uint16_t)-1) -UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; } +typedef enum { + kUpb_FieldMode_Map = 0, + kUpb_FieldMode_Array = 1, + kUpb_FieldMode_Scalar = 2, +} upb_FieldMode; -uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed); +// Mask to isolate the upb_FieldMode from field.mode. +#define kUpb_FieldMode_Mask 3 -#ifdef __cplusplus -} /* extern "C" */ -#endif +// Extra flags on the mode field. +typedef enum { + kUpb_LabelFlags_IsPacked = 4, + kUpb_LabelFlags_IsExtension = 8, + // Indicates that this descriptor type is an "alternate type": + // - for Int32, this indicates that the actual type is Enum (but was + // rewritten to Int32 because it is an open enum that requires no check). + // - for Bytes, this indicates that the actual type is String (but does + // not require any UTF-8 check). + kUpb_LabelFlags_IsAlternate = 16, +} upb_LabelFlags; +// Note: we sort by this number when calculating layout order. +typedef enum { + kUpb_FieldRep_1Byte = 0, + kUpb_FieldRep_4Byte = 1, + kUpb_FieldRep_StringView = 2, + kUpb_FieldRep_8Byte = 3, -#endif /* UPB_HASH_COMMON_H_ */ + kUpb_FieldRep_NativePointer = + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte), + kUpb_FieldRep_Max = kUpb_FieldRep_8Byte, +} upb_FieldRep; -// Must be last. +#define kUpb_FieldRep_Shift 6 -typedef struct { - upb_table t; -} upb_strtable; +UPB_INLINE upb_FieldRep +_upb_MiniTableField_GetRep(const struct upb_MiniTableField* field) { + return (upb_FieldRep)(field->mode >> kUpb_FieldRep_Shift); +} #ifdef __cplusplus extern "C" { #endif -// Initialize a table. If memory allocation failed, false is returned and -// the table is uninitialized. -bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a); - -// Returns the number of values in the table. -UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) { - return t->t.count; +UPB_INLINE upb_FieldMode +upb_FieldMode_Get(const struct upb_MiniTableField* field) { + return (upb_FieldMode)(field->mode & 3); } -void upb_strtable_clear(upb_strtable* t); - -// Inserts the given key into the hashtable with the given value. -// The key must not already exist in the hash table. The key is not required -// to be NULL-terminated, and the table will make an internal copy of the key. -// -// If a table resize was required but memory allocation failed, false is -// returned and the table is unchanged. */ -bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len, - upb_value val, upb_Arena* a); - -// Looks up key in this table, returning "true" if the key was found. -// If v is non-NULL, copies the value for this key into *v. -bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len, - upb_value* v); +UPB_INLINE void _upb_MiniTableField_CheckIsArray( + const struct upb_MiniTableField* field) { + UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_FieldMode_Get(field) == kUpb_FieldMode_Array); + UPB_ASSUME(field->presence == 0); +} -// For NULL-terminated strings. -UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key, - upb_value* v) { - return upb_strtable_lookup2(t, key, strlen(key), v); +UPB_INLINE void _upb_MiniTableField_CheckIsMap( + const struct upb_MiniTableField* field) { + UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_FieldMode_Get(field) == kUpb_FieldMode_Map); + UPB_ASSUME(field->presence == 0); } -// Removes an item from the table. Returns true if the remove was successful, -// and stores the removed item in *val if non-NULL. -bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len, - upb_value* val); +UPB_INLINE bool upb_IsRepeatedOrMap(const struct upb_MiniTableField* field) { + // This works because upb_FieldMode has no value 3. + return !(field->mode & kUpb_FieldMode_Scalar); +} -UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key, - upb_value* v) { - return upb_strtable_remove2(t, key, strlen(key), v); +UPB_INLINE bool upb_IsSubMessage(const struct upb_MiniTableField* field) { + return field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message || + field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group; } -// Exposed for testing only. -bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a); +#ifdef __cplusplus +} /* extern "C" */ +#endif -/* Iteration over strtable: - * - * intptr_t iter = UPB_STRTABLE_BEGIN; - * upb_StringView key; - * upb_value val; - * while (upb_strtable_next2(t, &key, &val, &iter)) { - * // ... - * } - */ -#define UPB_STRTABLE_BEGIN -1 +#endif /* UPB_MINI_TABLE_INTERNAL_FIELD_H_ */ -bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, - upb_value* val, intptr_t* iter); -void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter); -void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v); +#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ +#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ -/* DEPRECATED iterators, slated for removal. - * - * Iterators for string tables. We are subject to some kind of unusual - * design constraints: - * - * For high-level languages: - * - we must be able to guarantee that we don't crash or corrupt memory even if - * the program accesses an invalidated iterator. - * - * For C++11 range-based for: - * - iterators must be copyable - * - iterators must be comparable - * - it must be possible to construct an "end" value. - * - * Iteration order is undefined. - * - * Modifying the table invalidates iterators. upb_{str,int}table_done() is - * guaranteed to work even on an invalidated iterator, as long as the table it - * is iterating over has not been freed. Calling next() or accessing data from - * an invalidated iterator yields unspecified elements from the table, but it is - * guaranteed not to crash and to return real table elements (except when done() - * is true). */ -/* upb_strtable_iter **********************************************************/ -/* upb_strtable_iter i; - * upb_strtable_begin(&i, t); - * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - * const char *key = upb_strtable_iter_key(&i); - * const upb_value val = upb_strtable_iter_value(&i); - * // ... - * } - */ +// Must be last. +struct upb_Decoder; +typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr, + upb_Message* msg, intptr_t table, + uint64_t hasbits, uint64_t data); typedef struct { - const upb_strtable* t; - size_t index; -} upb_strtable_iter; - -UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) { - return &i->t->t.entries[i->index]; -} + uint64_t field_data; + _upb_FieldParser* field_parser; +} _upb_FastTable_Entry; -void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t); -void upb_strtable_next(upb_strtable_iter* i); -bool upb_strtable_done(const upb_strtable_iter* i); -upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i); -upb_value upb_strtable_iter_value(const upb_strtable_iter* i); -void upb_strtable_iter_setdone(upb_strtable_iter* i); -bool upb_strtable_iter_isequal(const upb_strtable_iter* i1, - const upb_strtable_iter* i2); +typedef enum { + kUpb_ExtMode_NonExtendable = 0, // Non-extendable message. + kUpb_ExtMode_Extendable = 1, // Normal extendable message. + kUpb_ExtMode_IsMessageSet = 2, // MessageSet message. + kUpb_ExtMode_IsMessageSet_ITEM = + 3, // MessageSet item (temporary only, see decode.c) -#ifdef __cplusplus -} /* extern "C" */ -#endif + // During table building we steal a bit to indicate that the message is a map + // entry. *Only* used during table building! + kUpb_ExtMode_IsMapEntry = 4, +} upb_ExtMode; +union upb_MiniTableSub; -#endif /* UPB_HASH_STR_TABLE_H_ */ +// upb_MiniTable represents the memory layout of a given upb_MessageDef. +// The members are public so generated code can initialize them, +// but users MUST NOT directly read or write any of its members. +struct upb_MiniTable { + const union upb_MiniTableSub* subs; + const struct upb_MiniTableField* fields; -// Must be last. + // Must be aligned to sizeof(void*). Doesn't include internal members like + // unknown fields, extension dict, pointer to msglayout, etc. + uint16_t size; -struct upb_Map { - // Size of key and val, based on the map type. - // Strings are represented as '0' because they must be handled specially. - char key_size; - char val_size; + uint16_t field_count; + uint8_t ext; // upb_ExtMode, declared as uint8_t so sizeof(ext) == 1 + uint8_t dense_below; + uint8_t table_mask; + uint8_t required_count; // Required fields have the lowest hasbits. - upb_strtable table; + // To statically initialize the tables of variable length, we need a flexible + // array member, and we need to compile in gnu99 mode (constant initialization + // of flexible array members is a GNU extension, not in C99 unfortunately. + _upb_FastTable_Entry fasttable[]; }; #ifdef __cplusplus extern "C" { #endif -// Converting between internal table representation and user values. -// -// _upb_map_tokey() and _upb_map_fromkey() are inverses. -// _upb_map_tovalue() and _upb_map_fromvalue() are inverses. -// -// These functions account for the fact that strings are treated differently -// from other types when stored in a map. - -UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - return *(upb_StringView*)key; - } else { - return upb_StringView_FromDataAndSize((const char*)key, size); - } -} - -UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - memcpy(out, &key, sizeof(key)); - } else { - memcpy(out, key.data, size); - } -} +// A MiniTable for an empty message, used for unlinked sub-messages. +extern const struct upb_MiniTable _kUpb_MiniTable_Empty; -UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size, - upb_value* msgval, upb_Arena* a) { - if (size == UPB_MAPTYPE_STRING) { - upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp)); - if (!strp) return false; - *strp = *(upb_StringView*)val; - *msgval = upb_value_ptr(strp); - } else { - memcpy(msgval, val, size); - } - return true; +// Computes a bitmask in which the |l->required_count| lowest bits are set, +// except that we skip the lowest bit (because upb never uses hasbit 0). +// +// Sample output: +// requiredmask(1) => 0b10 (0x2) +// requiredmask(5) => 0b111110 (0x3e) +UPB_INLINE uint64_t upb_MiniTable_requiredmask(const struct upb_MiniTable* l) { + int n = l->required_count; + assert(0 < n && n <= 63); + return ((1ULL << n) - 1) << 1; } -UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val); - memcpy(out, strp, sizeof(upb_StringView)); - } else { - memcpy(out, &val, size); - } -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_INLINE void* _upb_map_next(const upb_Map* map, size_t* iter) { - upb_strtable_iter it; - it.t = &map->table; - it.index = *iter; - upb_strtable_next(&it); - *iter = it.index; - if (upb_strtable_done(&it)) return NULL; - return (void*)str_tabent(&it); -} -UPB_INLINE void _upb_Map_Clear(upb_Map* map) { - upb_strtable_clear(&map->table); -} +#endif /* UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ */ -UPB_INLINE bool _upb_Map_Delete(upb_Map* map, const void* key, size_t key_size, - upb_value* val) { - upb_StringView k = _upb_map_tokey(key, key_size); - return upb_strtable_remove2(&map->table, k.data, k.size, val); -} +#ifndef UPB_MINI_TABLE_INTERNAL_SUB_H_ +#define UPB_MINI_TABLE_INTERNAL_SUB_H_ -UPB_INLINE bool _upb_Map_Get(const upb_Map* map, const void* key, - size_t key_size, void* val, size_t val_size) { - upb_value tabval; - upb_StringView k = _upb_map_tokey(key, key_size); - bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); - if (ret && val) { - _upb_map_fromvalue(tabval, val, val_size); - } - return ret; -} -UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(upb_Map* map, const void* key, - size_t key_size, void* val, - size_t val_size, upb_Arena* a) { - upb_StringView strkey = _upb_map_tokey(key, key_size); - upb_value tabval = {0}; - if (!_upb_map_tovalue(val, val_size, &tabval, a)) { - return kUpb_MapInsertStatus_OutOfMemory; - } +union upb_MiniTableSub { + const struct upb_MiniTable* submsg; + const struct upb_MiniTableEnum* subenum; +}; - // TODO(haberman): add overwrite operation to minimize number of lookups. - bool removed = - upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL); - if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) { - return kUpb_MapInsertStatus_OutOfMemory; +#endif /* UPB_MINI_TABLE_INTERNAL_SUB_H_ */ + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct upb_MiniTableField upb_MiniTableField; + +UPB_API_INLINE upb_FieldType +upb_MiniTableField_Type(const upb_MiniTableField* field) { + if (field->mode & kUpb_LabelFlags_IsAlternate) { + if (field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Int32) { + return kUpb_FieldType_Enum; + } else if (field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bytes) { + return kUpb_FieldType_String; + } else { + UPB_ASSERT(false); + } } - return removed ? kUpb_MapInsertStatus_Replaced - : kUpb_MapInsertStatus_Inserted; + return (upb_FieldType)field->UPB_PRIVATE(descriptortype); } -UPB_INLINE size_t _upb_Map_Size(const upb_Map* map) { - return map->table.t.count; +UPB_API_INLINE upb_CType upb_MiniTableField_CType(const upb_MiniTableField* f) { + switch (upb_MiniTableField_Type(f)) { + case kUpb_FieldType_Double: + return kUpb_CType_Double; + case kUpb_FieldType_Float: + return kUpb_CType_Float; + case kUpb_FieldType_Int64: + case kUpb_FieldType_SInt64: + case kUpb_FieldType_SFixed64: + return kUpb_CType_Int64; + case kUpb_FieldType_Int32: + case kUpb_FieldType_SFixed32: + case kUpb_FieldType_SInt32: + return kUpb_CType_Int32; + case kUpb_FieldType_UInt64: + case kUpb_FieldType_Fixed64: + return kUpb_CType_UInt64; + case kUpb_FieldType_UInt32: + case kUpb_FieldType_Fixed32: + return kUpb_CType_UInt32; + case kUpb_FieldType_Enum: + return kUpb_CType_Enum; + case kUpb_FieldType_Bool: + return kUpb_CType_Bool; + case kUpb_FieldType_String: + return kUpb_CType_String; + case kUpb_FieldType_Bytes: + return kUpb_CType_Bytes; + case kUpb_FieldType_Group: + case kUpb_FieldType_Message: + return kUpb_CType_Message; + } + UPB_UNREACHABLE(); } -// Strings/bytes are special-cased in maps. -extern char _upb_Map_CTypeSizeTable[12]; +UPB_API_INLINE bool upb_MiniTableField_IsExtension( + const upb_MiniTableField* field) { + return field->mode & kUpb_LabelFlags_IsExtension; +} -UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) { - return _upb_Map_CTypeSizeTable[ctype]; +UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( + const upb_MiniTableField* field) { + return field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum; } -// Creates a new map on the given arena with this key/value type. -upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size); +UPB_API_INLINE bool upb_MiniTableField_HasPresence( + const upb_MiniTableField* field) { + if (upb_MiniTableField_IsExtension(field)) { + return !upb_IsRepeatedOrMap(field); + } else { + return field->presence != 0; + } +} #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_COLLECTIONS_INTERNAL_MAP_H_ */ - -// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// - -#ifndef UPB_COLLECTIONS_INTERNAL_MAP_SORTER_H_ -#define UPB_COLLECTIONS_INTERNAL_MAP_SORTER_H_ - -#include +#endif /* UPB_MINI_TABLE_FIELD_H_ */ +// Must be last. -#ifndef UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ -#define UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ +#ifdef __cplusplus +extern "C" { +#endif +typedef struct upb_MiniTable upb_MiniTable; -#ifndef UPB_MINI_TABLE_INTERNAL_TYPES_H_ -#define UPB_MINI_TABLE_INTERNAL_TYPES_H_ +UPB_API const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( + const upb_MiniTable* table, uint32_t number); -typedef struct upb_Message_InternalData upb_Message_InternalData; +UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_GetFieldByIndex( + const upb_MiniTable* t, uint32_t index) { + return &t->fields[index]; +} -typedef struct { - union { - upb_Message_InternalData* internal; +// Returns the MiniTable for this message field. If the field is unlinked, +// returns NULL. +UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( + const upb_MiniTable* mini_table, const upb_MiniTableField* field) { + UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Message); + const upb_MiniTable* ret = + mini_table->subs[field->UPB_PRIVATE(submsg_index)].submsg; + UPB_ASSUME(ret); + return ret == &_kUpb_MiniTable_Empty ? NULL : ret; +} - // Force 8-byte alignment, since the data members may contain members that - // require 8-byte alignment. - double d; - }; -} upb_Message_Internal; +// Returns the MiniTableEnum for this enum field. If the field is unlinked, +// returns NULL. +UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( + const upb_MiniTable* mini_table, const upb_MiniTableField* field) { + UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Enum); + return mini_table->subs[field->UPB_PRIVATE(submsg_index)].subenum; +} -#endif // UPB_MINI_TABLE_INTERNAL_TYPES_H_ +// Returns true if this MiniTable field is linked to a MiniTable for the +// sub-message. +UPB_API_INLINE bool upb_MiniTable_MessageFieldIsLinked( + const upb_MiniTable* mini_table, const upb_MiniTableField* field) { + return upb_MiniTable_GetSubMessageTable(mini_table, field) != NULL; +} -// Map entries aren't actually stored for map fields, they are only used during -// parsing. For parsing, it helps a lot if all map entry messages have the same -// layout. The layout code in mini_table/decode.c will ensure that all map -// entries have this layout. +// If this field is in a oneof, returns the first field in the oneof. // -// Note that users can and do create map entries directly, which will also use -// this layout. +// Otherwise returns NULL. // -// NOTE: sync with wire/decode.c. -typedef struct { - // We only need 2 hasbits max, but due to alignment we'll use 8 bytes here, - // and the uint64_t helps make this clear. - uint64_t hasbits; - union { - upb_StringView str; // For str/bytes. - upb_value val; // For all other types. - } k; - union { - upb_StringView str; // For str/bytes. - upb_value val; // For all other types. - } v; -} upb_MapEntryData; - -typedef struct { - upb_Message_Internal internal; - upb_MapEntryData data; -} upb_MapEntry; - -#endif // UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ - -#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_ -#define UPB_MESSAGE_INTERNAL_EXTENSION_H_ - - -// Public APIs for message operations that do not depend on the schema. +// Usage: +// const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f); +// do { +// .. +// } while (upb_MiniTable_NextOneofField(m, &field); // -// MiniTable-based accessors live in accessors.h. +const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, + const upb_MiniTableField* f); -#ifndef UPB_MESSAGE_MESSAGE_H_ -#define UPB_MESSAGE_MESSAGE_H_ +// Iterates to the next field in the oneof. If this is the last field in the +// oneof, returns false. The ordering of fields in the oneof is not +// guaranteed. +// REQUIRES: |f| is the field initialized by upb_MiniTable_GetOneof and updated +// by prior upb_MiniTable_NextOneofField calls. +bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, + const upb_MiniTableField** f); -#include +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* UPB_MINI_TABLE_MESSAGE_H_ */ + // Must be last. #ifdef __cplusplus @@ -11684,6 +11688,8 @@ int upb_Unicode_ToUTF8(uint32_t cp, char* out); #ifndef UPB_REFLECTION_MESSAGE_H_ #define UPB_REFLECTION_MESSAGE_H_ +#include + // Must be last. diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h index de81125e98..1c13c8df39 100755 --- a/ruby/ext/google/protobuf_c/ruby-upb.h +++ b/ruby/ext/google/protobuf_c/ruby-upb.h @@ -371,6 +371,8 @@ void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt, #ifndef UPB_COLLECTIONS_ARRAY_H_ #define UPB_COLLECTIONS_ARRAY_H_ +#include + #ifndef UPB_BASE_DESCRIPTOR_CONSTANTS_H_ #define UPB_BASE_DESCRIPTOR_CONSTANTS_H_ @@ -448,12 +450,204 @@ UPB_INLINE bool upb_FieldType_IsPackable(upb_FieldType type) { #endif /* UPB_BASE_DESCRIPTOR_CONSTANTS_H_ */ +/* upb_Arena is a specific allocator implementation that uses arena allocation. + * The user provides an allocator that will be used to allocate the underlying + * arena blocks. Arenas by nature do not require the individual allocations + * to be freed. However the Arena does allow users to register cleanup + * functions that will run when the arena is destroyed. + * + * A upb_Arena is *not* thread-safe. + * + * You could write a thread-safe arena allocator that satisfies the + * upb_alloc interface, but it would not be as efficient for the + * single-threaded case. */ + +#ifndef UPB_MEM_ARENA_H_ +#define UPB_MEM_ARENA_H_ + +#include +#include +#include + + +#ifndef UPB_MEM_ALLOC_H_ +#define UPB_MEM_ALLOC_H_ + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct upb_alloc upb_alloc; + +/* A combined `malloc()`/`free()` function. + * If `size` is 0 then the function acts like `free()`, otherwise it acts like + * `realloc()`. Only `oldsize` bytes from a previous allocation are + * preserved. */ +typedef void* upb_alloc_func(upb_alloc* alloc, void* ptr, size_t oldsize, + size_t size); + +/* A upb_alloc is a possibly-stateful allocator object. + * + * It could either be an arena allocator (which doesn't require individual + * `free()` calls) or a regular `malloc()` (which does). The client must + * therefore free memory unless it knows that the allocator is an arena + * allocator. */ +struct upb_alloc { + upb_alloc_func* func; +}; + +UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, NULL, 0, size); +} + +UPB_INLINE void* upb_realloc(upb_alloc* alloc, void* ptr, size_t oldsize, + size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, ptr, oldsize, size); +} + +UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) { + UPB_ASSERT(alloc); + alloc->func(alloc, ptr, 0, 0); +} + +// The global allocator used by upb. Uses the standard malloc()/free(). + +extern upb_alloc upb_alloc_global; + +/* Functions that hard-code the global malloc. + * + * We still get benefit because we can put custom logic into our global + * allocator, like injecting out-of-memory faults in debug/testing builds. */ + +UPB_INLINE void* upb_gmalloc(size_t size) { + return upb_malloc(&upb_alloc_global, size); +} + +UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) { + return upb_realloc(&upb_alloc_global, ptr, oldsize, size); +} + +UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); } + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MEM_ALLOC_H_ */ + +// Must be last. + +typedef struct upb_Arena upb_Arena; + +typedef struct { + char *ptr, *end; +} _upb_ArenaHead; + +#ifdef __cplusplus +extern "C" { +#endif + +// Creates an arena from the given initial block (if any -- n may be 0). +// Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this +// is a fixed-size arena and cannot grow. +UPB_API upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc); + +UPB_API void upb_Arena_Free(upb_Arena* a); +UPB_API bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b); + +void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size); +size_t upb_Arena_SpaceAllocated(upb_Arena* arena); +uint32_t upb_Arena_DebugRefCount(upb_Arena* arena); + +UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) { + _upb_ArenaHead* h = (_upb_ArenaHead*)a; + return (size_t)(h->end - h->ptr); +} + +UPB_API_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) { + size = UPB_ALIGN_MALLOC(size); + size_t span = size + UPB_ASAN_GUARD_SIZE; + if (UPB_UNLIKELY(_upb_ArenaHas(a) < span)) { + return _upb_Arena_SlowMalloc(a, size); + } + + // We have enough space to do a fast malloc. + _upb_ArenaHead* h = (_upb_ArenaHead*)a; + void* ret = h->ptr; + UPB_ASSERT(UPB_ALIGN_MALLOC((uintptr_t)ret) == (uintptr_t)ret); + UPB_ASSERT(UPB_ALIGN_MALLOC(size) == size); + UPB_UNPOISON_MEMORY_REGION(ret, size); + + h->ptr += span; + + return ret; +} + +// Shrinks the last alloc from arena. +// REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena. +// We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if +// this was not the last alloc. +UPB_API_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, + size_t oldsize, size_t size) { + _upb_ArenaHead* h = (_upb_ArenaHead*)a; + oldsize = UPB_ALIGN_MALLOC(oldsize); + size = UPB_ALIGN_MALLOC(size); + // Must be the last alloc. + UPB_ASSERT((char*)ptr + oldsize == h->ptr - UPB_ASAN_GUARD_SIZE); + UPB_ASSERT(size <= oldsize); + h->ptr = (char*)ptr + size; +} + +UPB_API_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize, + size_t size) { + _upb_ArenaHead* h = (_upb_ArenaHead*)a; + oldsize = UPB_ALIGN_MALLOC(oldsize); + size = UPB_ALIGN_MALLOC(size); + bool is_most_recent_alloc = (uintptr_t)ptr + oldsize == (uintptr_t)h->ptr; + + if (is_most_recent_alloc) { + ptrdiff_t diff = size - oldsize; + if ((ptrdiff_t)_upb_ArenaHas(a) >= diff) { + h->ptr += diff; + return ptr; + } + } else if (size <= oldsize) { + return ptr; + } + + void* ret = upb_Arena_Malloc(a, size); + + if (ret && oldsize > 0) { + memcpy(ret, ptr, UPB_MIN(oldsize, size)); + } + + return ret; +} + +UPB_API_INLINE upb_Arena* upb_Arena_New(void) { + return upb_Arena_Init(NULL, 0, &upb_alloc_global); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MEM_ARENA_H_ */ + // Users should include array.h or map.h instead. // IWYU pragma: private, include "upb/upb/collections/array.h" #ifndef UPB_MESSAGE_VALUE_H_ #define UPB_MESSAGE_VALUE_H_ +#include + #ifndef UPB_BASE_STRING_VIEW_H_ #define UPB_BASE_STRING_VIEW_H_ @@ -573,181 +767,183 @@ UPB_INLINE upb_Message* _upb_TaggedMessagePtr_GetEmptyMessage( #endif /* UPB_MINI_TABLE_TYPES_H_ */ -#ifndef UPB_MINI_TABLE_MESSAGE_H_ -#define UPB_MINI_TABLE_MESSAGE_H_ - - -#ifndef UPB_MINI_TABLE_ENUM_H_ -#define UPB_MINI_TABLE_ENUM_H_ +typedef union { + bool bool_val; + float float_val; + double double_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + const struct upb_Array* array_val; + const struct upb_Map* map_val; + const upb_Message* msg_val; + upb_StringView str_val; + // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of + // msg_val if unlinked sub-messages may possibly be in use. See the + // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more + // information. + upb_TaggedMessagePtr tagged_msg_val; +} upb_MessageValue; -#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_ -#define UPB_MINI_TABLE_INTERNAL_ENUM_H_ +typedef union { + struct upb_Array* array; + struct upb_Map* map; + upb_Message* msg; +} upb_MutableMessageValue; -#include +#endif /* UPB_MESSAGE_VALUE_H_ */ // Must be last. -struct upb_MiniTableEnum { - uint32_t mask_limit; // Limit enum value that can be tested with mask. - uint32_t value_count; // Number of values after the bitfield. - uint32_t data[]; // Bitmask + enumerated values follow. -}; - -typedef enum { - _kUpb_FastEnumCheck_ValueIsInEnum = 0, - _kUpb_FastEnumCheck_ValueIsNotInEnum = 1, - _kUpb_FastEnumCheck_CannotCheckFast = 2, -} _kUpb_FastEnumCheck_Status; +typedef struct upb_Array upb_Array; #ifdef __cplusplus extern "C" { #endif -UPB_INLINE _kUpb_FastEnumCheck_Status _upb_MiniTable_CheckEnumValueFast( - const struct upb_MiniTableEnum* e, uint32_t val) { - if (UPB_UNLIKELY(val >= 64)) return _kUpb_FastEnumCheck_CannotCheckFast; - uint64_t mask = e->data[0] | ((uint64_t)e->data[1] << 32); - return (mask & (1ULL << val)) ? _kUpb_FastEnumCheck_ValueIsInEnum - : _kUpb_FastEnumCheck_ValueIsNotInEnum; -} - -UPB_INLINE bool _upb_MiniTable_CheckEnumValueSlow( - const struct upb_MiniTableEnum* e, uint32_t val) { - if (val < e->mask_limit) return e->data[val / 32] & (1ULL << (val % 32)); - // OPT: binary search long lists? - const uint32_t* start = &e->data[e->mask_limit / 32]; - const uint32_t* limit = &e->data[(e->mask_limit / 32) + e->value_count]; - for (const uint32_t* p = start; p < limit; p++) { - if (*p == val) return true; - } - return false; -} +// Creates a new array on the given arena that holds elements of this type. +UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type); -#ifdef __cplusplus -} /* extern "C" */ -#endif +// Returns the number of elements in the array. +UPB_API size_t upb_Array_Size(const upb_Array* arr); +// Returns the given element, which must be within the array's current size. +UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i); -#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */ +// Sets the given element, which must be within the array's current size. +UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val); -// Must be last +// Appends an element to the array. Returns false on allocation failure. +UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val, + upb_Arena* arena); -typedef struct upb_MiniTableEnum upb_MiniTableEnum; +// Moves elements within the array using memmove(). +// Like memmove(), the source and destination elements may be overlapping. +UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx, + size_t count); -// Validates enum value against range defined by enum mini table. -UPB_INLINE bool upb_MiniTableEnum_CheckValue(const struct upb_MiniTableEnum* e, - uint32_t val) { - _kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, val); - if (UPB_UNLIKELY(status == _kUpb_FastEnumCheck_CannotCheckFast)) { - return _upb_MiniTable_CheckEnumValueSlow(e, val); - } - return status == _kUpb_FastEnumCheck_ValueIsInEnum ? true : false; -} +// Inserts one or more empty elements into the array. +// Existing elements are shifted right. +// The new elements have undefined state and must be set with `upb_Array_Set()`. +// REQUIRES: `i <= upb_Array_Size(arr)` +UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count, + upb_Arena* arena); +// Deletes one or more elements from the array. +// Existing elements are shifted left. +// REQUIRES: `i + count <= upb_Array_Size(arr)` +UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count); -#endif /* UPB_MINI_TABLE_ENUM_H_ */ +// Changes the size of a vector. New elements are initialized to NULL/0. +// Returns false on allocation failure. +UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena); -#ifndef UPB_MINI_TABLE_FIELD_H_ -#define UPB_MINI_TABLE_FIELD_H_ +// Returns pointer to array data. +UPB_API const void* upb_Array_DataPtr(const upb_Array* arr); +// Returns mutable pointer to array data. +UPB_API void* upb_Array_MutableDataPtr(upb_Array* arr); -#ifndef UPB_MINI_TABLE_INTERNAL_FIELD_H_ -#define UPB_MINI_TABLE_INTERNAL_FIELD_H_ +#ifdef __cplusplus +} /* extern "C" */ +#endif -#include +#endif /* UPB_COLLECTIONS_ARRAY_H_ */ // Must be last. -struct upb_MiniTableField { - uint32_t number; - uint16_t offset; - int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index - - // Indexes into `upb_MiniTable.subs` - // Will be set to `kUpb_NoSub` if `descriptortype` != MESSAGE/GROUP/ENUM - uint16_t UPB_PRIVATE(submsg_index); - - uint8_t UPB_PRIVATE(descriptortype); +#ifdef __cplusplus +extern "C" { +#endif - // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift) - uint8_t mode; +// LINT.IfChange(struct_definition) +// Our internal representation for repeated fields. +struct upb_Array { + uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */ + size_t size; /* The number of elements in the array. */ + size_t capacity; /* Allocated storage. Measured in elements. */ }; +// LINT.ThenChange(GoogleInternalName1) -#define kUpb_NoSub ((uint16_t)-1) - -typedef enum { - kUpb_FieldMode_Map = 0, - kUpb_FieldMode_Array = 1, - kUpb_FieldMode_Scalar = 2, -} upb_FieldMode; +UPB_INLINE size_t _upb_Array_ElementSizeLg2(const upb_Array* arr) { + size_t ret = arr->data & 7; + UPB_ASSERT(ret <= 4); + return ret; +} -// Mask to isolate the upb_FieldMode from field.mode. -#define kUpb_FieldMode_Mask 3 +UPB_INLINE const void* _upb_array_constptr(const upb_Array* arr) { + _upb_Array_ElementSizeLg2(arr); // Check assertion. + return (void*)(arr->data & ~(uintptr_t)7); +} -// Extra flags on the mode field. -typedef enum { - kUpb_LabelFlags_IsPacked = 4, - kUpb_LabelFlags_IsExtension = 8, - // Indicates that this descriptor type is an "alternate type": - // - for Int32, this indicates that the actual type is Enum (but was - // rewritten to Int32 because it is an open enum that requires no check). - // - for Bytes, this indicates that the actual type is String (but does - // not require any UTF-8 check). - kUpb_LabelFlags_IsAlternate = 16, -} upb_LabelFlags; +UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + return (uintptr_t)ptr | elem_size_lg2; +} -// Note: we sort by this number when calculating layout order. -typedef enum { - kUpb_FieldRep_1Byte = 0, - kUpb_FieldRep_4Byte = 1, - kUpb_FieldRep_StringView = 2, - kUpb_FieldRep_8Byte = 3, +UPB_INLINE void* _upb_array_ptr(upb_Array* arr) { + return (void*)_upb_array_constptr(arr); +} - kUpb_FieldRep_NativePointer = - UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte), - kUpb_FieldRep_Max = kUpb_FieldRep_8Byte, -} upb_FieldRep; +UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + UPB_ASSERT(((uintptr_t)ptr & 7) == 0); + return (uintptr_t)ptr | (unsigned)elem_size_lg2; +} -#define kUpb_FieldRep_Shift 6 +extern const char _upb_Array_CTypeSizeLg2Table[]; -UPB_INLINE upb_FieldRep -_upb_MiniTableField_GetRep(const struct upb_MiniTableField* field) { - return (upb_FieldRep)(field->mode >> kUpb_FieldRep_Shift); +UPB_INLINE size_t _upb_Array_CTypeSizeLg2(upb_CType ctype) { + return _upb_Array_CTypeSizeLg2Table[ctype]; } -#ifdef __cplusplus -extern "C" { -#endif - -UPB_INLINE upb_FieldMode -upb_FieldMode_Get(const struct upb_MiniTableField* field) { - return (upb_FieldMode)(field->mode & 3); +UPB_INLINE upb_Array* _upb_Array_New(upb_Arena* a, size_t init_capacity, + int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_Array), UPB_MALLOC_ALIGN); + const size_t bytes = arr_size + (init_capacity << elem_size_lg2); + upb_Array* arr = (upb_Array*)upb_Arena_Malloc(a, bytes); + if (!arr) return NULL; + arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2); + arr->size = 0; + arr->capacity = init_capacity; + return arr; } -UPB_INLINE void _upb_MiniTableField_CheckIsArray( - const struct upb_MiniTableField* field) { - UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_NativePointer); - UPB_ASSUME(upb_FieldMode_Get(field) == kUpb_FieldMode_Array); - UPB_ASSUME(field->presence == 0); +// Resizes the capacity of the array to be at least min_size. +bool _upb_array_realloc(upb_Array* arr, size_t min_size, upb_Arena* arena); + +UPB_INLINE bool _upb_array_reserve(upb_Array* arr, size_t size, + upb_Arena* arena) { + if (arr->capacity < size) return _upb_array_realloc(arr, size, arena); + return true; } -UPB_INLINE void _upb_MiniTableField_CheckIsMap( - const struct upb_MiniTableField* field) { - UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_NativePointer); - UPB_ASSUME(upb_FieldMode_Get(field) == kUpb_FieldMode_Map); - UPB_ASSUME(field->presence == 0); +// Resize without initializing new elements. +UPB_INLINE bool _upb_Array_ResizeUninitialized(upb_Array* arr, size_t size, + upb_Arena* arena) { + UPB_ASSERT(size <= arr->size || arena); // Allow NULL arena when shrinking. + if (!_upb_array_reserve(arr, size, arena)) return false; + arr->size = size; + return true; } -UPB_INLINE bool upb_IsRepeatedOrMap(const struct upb_MiniTableField* field) { - // This works because upb_FieldMode has no value 3. - return !(field->mode & kUpb_FieldMode_Scalar); +// This function is intended for situations where elem_size is compile-time +// constant or a known expression of the form (1 << lg2), so that the expression +// i*elem_size does not result in an actual multiplication. +UPB_INLINE void _upb_Array_Set(upb_Array* arr, size_t i, const void* data, + size_t elem_size) { + UPB_ASSERT(i < arr->size); + UPB_ASSERT(elem_size == 1U << _upb_Array_ElementSizeLg2(arr)); + char* arr_data = (char*)_upb_array_ptr(arr); + memcpy(arr_data + (i * elem_size), data, elem_size); } -UPB_INLINE bool upb_IsSubMessage(const struct upb_MiniTableField* field) { - return field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message || - field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group; +UPB_INLINE void _upb_array_detach(const void* msg, size_t ofs) { + *UPB_PTR_AT(msg, ofs, upb_Array*) = NULL; } #ifdef __cplusplus @@ -755,1247 +951,1055 @@ UPB_INLINE bool upb_IsSubMessage(const struct upb_MiniTableField* field) { #endif -#endif /* UPB_MINI_TABLE_INTERNAL_FIELD_H_ */ +#endif /* UPB_COLLECTIONS_INTERNAL_ARRAY_H_ */ -#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ -#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ +#ifndef UPB_COLLECTIONS_MAP_H_ +#define UPB_COLLECTIONS_MAP_H_ + +#include // Must be last. -struct upb_Decoder; -typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr, - upb_Message* msg, intptr_t table, - uint64_t hasbits, uint64_t data); -typedef struct { - uint64_t field_data; - _upb_FieldParser* field_parser; -} _upb_FastTable_Entry; +typedef struct upb_Map upb_Map; -typedef enum { - kUpb_ExtMode_NonExtendable = 0, // Non-extendable message. - kUpb_ExtMode_Extendable = 1, // Normal extendable message. - kUpb_ExtMode_IsMessageSet = 2, // MessageSet message. - kUpb_ExtMode_IsMessageSet_ITEM = - 3, // MessageSet item (temporary only, see decode.c) +#ifdef __cplusplus +extern "C" { +#endif - // During table building we steal a bit to indicate that the message is a map - // entry. *Only* used during table building! - kUpb_ExtMode_IsMapEntry = 4, -} upb_ExtMode; +// Creates a new map on the given arena with the given key/value size. +UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, + upb_CType value_type); -union upb_MiniTableSub; +// Returns the number of entries in the map. +UPB_API size_t upb_Map_Size(const upb_Map* map); -// upb_MiniTable represents the memory layout of a given upb_MessageDef. -// The members are public so generated code can initialize them, -// but users MUST NOT directly read or write any of its members. -struct upb_MiniTable { - const union upb_MiniTableSub* subs; - const struct upb_MiniTableField* fields; +// Stores a value for the given key into |*val| (or the zero value if the key is +// not present). Returns whether the key was present. The |val| pointer may be +// NULL, in which case the function tests whether the given key is present. +UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, + upb_MessageValue* val); - // Must be aligned to sizeof(void*). Doesn't include internal members like - // unknown fields, extension dict, pointer to msglayout, etc. - uint16_t size; +// Removes all entries in the map. +UPB_API void upb_Map_Clear(upb_Map* map); - uint16_t field_count; - uint8_t ext; // upb_ExtMode, declared as uint8_t so sizeof(ext) == 1 - uint8_t dense_below; - uint8_t table_mask; - uint8_t required_count; // Required fields have the lowest hasbits. +typedef enum { + kUpb_MapInsertStatus_Inserted = 0, + kUpb_MapInsertStatus_Replaced = 1, + kUpb_MapInsertStatus_OutOfMemory = 2, +} upb_MapInsertStatus; - // To statically initialize the tables of variable length, we need a flexible - // array member, and we need to compile in gnu99 mode (constant initialization - // of flexible array members is a GNU extension, not in C99 unfortunately. - _upb_FastTable_Entry fasttable[]; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -// A MiniTable for an empty message, used for unlinked sub-messages. -extern const struct upb_MiniTable _kUpb_MiniTable_Empty; +// Sets the given key to the given value, returning whether the key was inserted +// or replaced. If the key was inserted, then any existing iterators will be +// invalidated. +UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, + upb_Arena* arena); -// Computes a bitmask in which the |l->required_count| lowest bits are set, -// except that we skip the lowest bit (because upb never uses hasbit 0). -// -// Sample output: -// requiredmask(1) => 0b10 (0x2) -// requiredmask(5) => 0b111110 (0x3e) -UPB_INLINE uint64_t upb_MiniTable_requiredmask(const struct upb_MiniTable* l) { - int n = l->required_count; - assert(0 < n && n <= 63); - return ((1ULL << n) - 1) << 1; +// Sets the given key to the given value. Returns false if memory allocation +// failed. If the key is newly inserted, then any existing iterators will be +// invalidated. +UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, upb_Arena* arena) { + return upb_Map_Insert(map, key, val, arena) != + kUpb_MapInsertStatus_OutOfMemory; } -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ */ - -#ifndef UPB_MINI_TABLE_INTERNAL_SUB_H_ -#define UPB_MINI_TABLE_INTERNAL_SUB_H_ - +// Deletes this key from the table. Returns true if the key was present. +// If present and |val| is non-NULL, stores the deleted value. +UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, + upb_MessageValue* val); -union upb_MiniTableSub { - const struct upb_MiniTable* submsg; - const struct upb_MiniTableEnum* subenum; -}; +// (DEPRECATED and going away soon. Do not use.) +UPB_INLINE bool upb_Map_Delete2(upb_Map* map, upb_MessageValue key, + upb_MessageValue* val) { + return upb_Map_Delete(map, key, val); +} -#endif /* UPB_MINI_TABLE_INTERNAL_SUB_H_ */ +// Map iteration: +// +// size_t iter = kUpb_Map_Begin; +// upb_MessageValue key, val; +// while (upb_Map_Next(map, &key, &val, &iter)) { +// ... +// } -// Must be last. +#define kUpb_Map_Begin ((size_t)-1) -#ifdef __cplusplus -extern "C" { -#endif +// Advances to the next entry. Returns false if no more entries are present. +// Otherwise returns true and populates both *key and *value. +UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, + upb_MessageValue* val, size_t* iter); -typedef struct upb_MiniTableField upb_MiniTableField; +// Sets the value for the entry pointed to by iter. +// WARNING: this does not currently work for string values! +UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, + upb_MessageValue val); -UPB_API_INLINE upb_FieldType -upb_MiniTableField_Type(const upb_MiniTableField* field) { - if (field->mode & kUpb_LabelFlags_IsAlternate) { - if (field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Int32) { - return kUpb_FieldType_Enum; - } else if (field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bytes) { - return kUpb_FieldType_String; - } else { - UPB_ASSERT(false); - } - } - return (upb_FieldType)field->UPB_PRIVATE(descriptortype); -} +// DEPRECATED iterator, slated for removal. -UPB_API_INLINE upb_CType upb_MiniTableField_CType(const upb_MiniTableField* f) { - switch (upb_MiniTableField_Type(f)) { - case kUpb_FieldType_Double: - return kUpb_CType_Double; - case kUpb_FieldType_Float: - return kUpb_CType_Float; - case kUpb_FieldType_Int64: - case kUpb_FieldType_SInt64: - case kUpb_FieldType_SFixed64: - return kUpb_CType_Int64; - case kUpb_FieldType_Int32: - case kUpb_FieldType_SFixed32: - case kUpb_FieldType_SInt32: - return kUpb_CType_Int32; - case kUpb_FieldType_UInt64: - case kUpb_FieldType_Fixed64: - return kUpb_CType_UInt64; - case kUpb_FieldType_UInt32: - case kUpb_FieldType_Fixed32: - return kUpb_CType_UInt32; - case kUpb_FieldType_Enum: - return kUpb_CType_Enum; - case kUpb_FieldType_Bool: - return kUpb_CType_Bool; - case kUpb_FieldType_String: - return kUpb_CType_String; - case kUpb_FieldType_Bytes: - return kUpb_CType_Bytes; - case kUpb_FieldType_Group: - case kUpb_FieldType_Message: - return kUpb_CType_Message; - } - UPB_UNREACHABLE(); -} +/* Map iteration: + * + * size_t iter = kUpb_Map_Begin; + * while (upb_MapIterator_Next(map, &iter)) { + * upb_MessageValue key = upb_MapIterator_Key(map, iter); + * upb_MessageValue val = upb_MapIterator_Value(map, iter); + * } + */ -UPB_API_INLINE bool upb_MiniTableField_IsExtension( - const upb_MiniTableField* field) { - return field->mode & kUpb_LabelFlags_IsExtension; -} +// Advances to the next entry. Returns false if no more entries are present. +UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter); -UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( - const upb_MiniTableField* field) { - return field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum; -} +// Returns true if the iterator still points to a valid entry, or false if the +// iterator is past the last element. It is an error to call this function with +// kUpb_Map_Begin (you must call next() at least once first). +UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter); -UPB_API_INLINE bool upb_MiniTableField_HasPresence( - const upb_MiniTableField* field) { - if (upb_MiniTableField_IsExtension(field)) { - return !upb_IsRepeatedOrMap(field); - } else { - return field->presence != 0; - } -} +// Returns the key and value for this entry of the map. +UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter); +UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_FIELD_H_ */ +#endif /* UPB_COLLECTIONS_MAP_H_ */ -// Must be last. +// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// -#ifdef __cplusplus -extern "C" { -#endif +#ifndef UPB_COLLECTIONS_INTERNAL_MAP_H_ +#define UPB_COLLECTIONS_INTERNAL_MAP_H_ -typedef struct upb_MiniTable upb_MiniTable; -UPB_API const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( - const upb_MiniTable* table, uint32_t number); +#ifndef UPB_HASH_STR_TABLE_H_ +#define UPB_HASH_STR_TABLE_H_ -UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_GetFieldByIndex( - const upb_MiniTable* t, uint32_t index) { - return &t->fields[index]; -} -// Returns the MiniTable for this message field. If the field is unlinked, -// returns NULL. -UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( - const upb_MiniTable* mini_table, const upb_MiniTableField* field) { - UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Message); - const upb_MiniTable* ret = - mini_table->subs[field->UPB_PRIVATE(submsg_index)].submsg; - UPB_ASSUME(ret); - return ret == &_kUpb_MiniTable_Empty ? NULL : ret; -} +/* + * upb_table + * + * This header is INTERNAL-ONLY! Its interfaces are not public or stable! + * This file defines very fast int->upb_value (inttable) and string->upb_value + * (strtable) hash tables. + * + * The table uses chained scatter with Brent's variation (inspired by the Lua + * implementation of hash tables). The hash function for strings is Austin + * Appleby's "MurmurHash." + * + * The inttable uses uintptr_t as its key, which guarantees it can be used to + * store pointers or integers of at least 32 bits (upb isn't really useful on + * systems where sizeof(void*) < 4). + * + * The table must be homogeneous (all values of the same type). In debug + * mode, we check this on insert and lookup. + */ -// Returns the MiniTableEnum for this enum field. If the field is unlinked, -// returns NULL. -UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( - const upb_MiniTable* mini_table, const upb_MiniTableField* field) { - UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Enum); - return mini_table->subs[field->UPB_PRIVATE(submsg_index)].subenum; -} +#ifndef UPB_HASH_COMMON_H_ +#define UPB_HASH_COMMON_H_ -// Returns true if this MiniTable field is linked to a MiniTable for the -// sub-message. -UPB_API_INLINE bool upb_MiniTable_MessageFieldIsLinked( - const upb_MiniTable* mini_table, const upb_MiniTableField* field) { - return upb_MiniTable_GetSubMessageTable(mini_table, field) != NULL; -} +#include -// If this field is in a oneof, returns the first field in the oneof. -// -// Otherwise returns NULL. -// -// Usage: -// const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f); -// do { -// .. -// } while (upb_MiniTable_NextOneofField(m, &field); -// -const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, - const upb_MiniTableField* f); -// Iterates to the next field in the oneof. If this is the last field in the -// oneof, returns false. The ordering of fields in the oneof is not -// guaranteed. -// REQUIRES: |f| is the field initialized by upb_MiniTable_GetOneof and updated -// by prior upb_MiniTable_NextOneofField calls. -bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, - const upb_MiniTableField** f); +// Must be last. #ifdef __cplusplus -} /* extern "C" */ +extern "C" { #endif +/* upb_value ******************************************************************/ -#endif /* UPB_MINI_TABLE_MESSAGE_H_ */ - -// Must be last. - -typedef struct upb_Array upb_Array; -typedef struct upb_Map upb_Map; - -typedef union { - bool bool_val; - float float_val; - double double_val; - int32_t int32_val; - int64_t int64_val; - uint32_t uint32_val; - uint64_t uint64_val; - const upb_Array* array_val; - const upb_Map* map_val; - const upb_Message* msg_val; - upb_StringView str_val; - - // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of - // msg_val if unlinked sub-messages may possibly be in use. See the - // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more - // information. - upb_TaggedMessagePtr tagged_msg_val; -} upb_MessageValue; - -typedef union { - upb_Array* array; - upb_Map* map; - upb_Message* msg; -} upb_MutableMessageValue; - +typedef struct { + uint64_t val; +} upb_value; -#endif /* UPB_MESSAGE_VALUE_H_ */ +UPB_INLINE void _upb_value_setval(upb_value* v, uint64_t val) { v->val = val; } -/* upb_Arena is a specific allocator implementation that uses arena allocation. - * The user provides an allocator that will be used to allocate the underlying - * arena blocks. Arenas by nature do not require the individual allocations - * to be freed. However the Arena does allow users to register cleanup - * functions that will run when the arena is destroyed. +/* For each value ctype, define the following set of functions: * - * A upb_Arena is *not* thread-safe. + * // Get/set an int32 from a upb_value. + * int32_t upb_value_getint32(upb_value val); + * void upb_value_setint32(upb_value *val, int32_t cval); * - * You could write a thread-safe arena allocator that satisfies the - * upb_alloc interface, but it would not be as efficient for the - * single-threaded case. */ - -#ifndef UPB_MEM_ARENA_H_ -#define UPB_MEM_ARENA_H_ + * // Construct a new upb_value from an int32. + * upb_value upb_value_int32(int32_t val); */ +#define FUNCS(name, membername, type_t, converter) \ + UPB_INLINE void upb_value_set##name(upb_value* val, type_t cval) { \ + val->val = (converter)cval; \ + } \ + UPB_INLINE upb_value upb_value_##name(type_t val) { \ + upb_value ret; \ + upb_value_set##name(&ret, val); \ + return ret; \ + } \ + UPB_INLINE type_t upb_value_get##name(upb_value val) { \ + return (type_t)(converter)val.val; \ + } -#include -#include -#include +FUNCS(int32, int32, int32_t, int32_t) +FUNCS(int64, int64, int64_t, int64_t) +FUNCS(uint32, uint32, uint32_t, uint32_t) +FUNCS(uint64, uint64, uint64_t, uint64_t) +FUNCS(bool, _bool, bool, bool) +FUNCS(cstr, cstr, char*, uintptr_t) +FUNCS(uintptr, uptr, uintptr_t, uintptr_t) +FUNCS(ptr, ptr, void*, uintptr_t) +FUNCS(constptr, constptr, const void*, uintptr_t) +#undef FUNCS -#ifndef UPB_MEM_ALLOC_H_ -#define UPB_MEM_ALLOC_H_ +UPB_INLINE void upb_value_setfloat(upb_value* val, float cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} -// Must be last. +UPB_INLINE void upb_value_setdouble(upb_value* val, double cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_INLINE upb_value upb_value_float(float cval) { + upb_value ret; + upb_value_setfloat(&ret, cval); + return ret; +} -typedef struct upb_alloc upb_alloc; +UPB_INLINE upb_value upb_value_double(double cval) { + upb_value ret; + upb_value_setdouble(&ret, cval); + return ret; +} -/* A combined `malloc()`/`free()` function. - * If `size` is 0 then the function acts like `free()`, otherwise it acts like - * `realloc()`. Only `oldsize` bytes from a previous allocation are - * preserved. */ -typedef void* upb_alloc_func(upb_alloc* alloc, void* ptr, size_t oldsize, - size_t size); +/* upb_tabkey *****************************************************************/ -/* A upb_alloc is a possibly-stateful allocator object. +/* Either: + * 1. an actual integer key, or + * 2. a pointer to a string prefixed by its uint32_t length, owned by us. * - * It could either be an arena allocator (which doesn't require individual - * `free()` calls) or a regular `malloc()` (which does). The client must - * therefore free memory unless it knows that the allocator is an arena - * allocator. */ -struct upb_alloc { - upb_alloc_func* func; -}; + * ...depending on whether this is a string table or an int table. We would + * make this a union of those two types, but C89 doesn't support statically + * initializing a non-first union member. */ +typedef uintptr_t upb_tabkey; -UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, NULL, 0, size); +UPB_INLINE char* upb_tabstr(upb_tabkey key, uint32_t* len) { + char* mem = (char*)key; + if (len) memcpy(len, mem, sizeof(*len)); + return mem + sizeof(*len); } -UPB_INLINE void* upb_realloc(upb_alloc* alloc, void* ptr, size_t oldsize, - size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, ptr, oldsize, size); +UPB_INLINE upb_StringView upb_tabstrview(upb_tabkey key) { + upb_StringView ret; + uint32_t len; + ret.data = upb_tabstr(key, &len); + ret.size = len; + return ret; } -UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) { - UPB_ASSERT(alloc); - alloc->func(alloc, ptr, 0, 0); -} +/* upb_tabval *****************************************************************/ -// The global allocator used by upb. Uses the standard malloc()/free(). +typedef struct upb_tabval { + uint64_t val; +} upb_tabval; -extern upb_alloc upb_alloc_global; +#define UPB_TABVALUE_EMPTY_INIT \ + { -1 } -/* Functions that hard-code the global malloc. - * - * We still get benefit because we can put custom logic into our global - * allocator, like injecting out-of-memory faults in debug/testing builds. */ +/* upb_table ******************************************************************/ -UPB_INLINE void* upb_gmalloc(size_t size) { - return upb_malloc(&upb_alloc_global, size); -} +typedef struct _upb_tabent { + upb_tabkey key; + upb_tabval val; -UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) { - return upb_realloc(&upb_alloc_global, ptr, oldsize, size); + /* Internal chaining. This is const so we can create static initializers for + * tables. We cast away const sometimes, but *only* when the containing + * upb_table is known to be non-const. This requires a bit of care, but + * the subtlety is confined to table.c. */ + const struct _upb_tabent* next; +} upb_tabent; + +typedef struct { + size_t count; /* Number of entries in the hash part. */ + uint32_t mask; /* Mask to turn hash value -> bucket. */ + uint32_t max_count; /* Max count before we hit our load limit. */ + uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ + upb_tabent* entries; +} upb_table; + +UPB_INLINE size_t upb_table_size(const upb_table* t) { + return t->size_lg2 ? 1 << t->size_lg2 : 0; } -UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); } +// Internal-only functions, in .h file only out of necessity. + +UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; } + +uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MEM_ALLOC_H_ */ +#endif /* UPB_HASH_COMMON_H_ */ // Must be last. -typedef struct upb_Arena upb_Arena; - typedef struct { - char *ptr, *end; -} _upb_ArenaHead; + upb_table t; +} upb_strtable; #ifdef __cplusplus extern "C" { #endif -// Creates an arena from the given initial block (if any -- n may be 0). -// Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this -// is a fixed-size arena and cannot grow. -UPB_API upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc); - -UPB_API void upb_Arena_Free(upb_Arena* a); -UPB_API bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b); - -void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size); -size_t upb_Arena_SpaceAllocated(upb_Arena* arena); -uint32_t upb_Arena_DebugRefCount(upb_Arena* arena); +// Initialize a table. If memory allocation failed, false is returned and +// the table is uninitialized. +bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a); -UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) { - _upb_ArenaHead* h = (_upb_ArenaHead*)a; - return (size_t)(h->end - h->ptr); +// Returns the number of values in the table. +UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) { + return t->t.count; } -UPB_API_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) { - size = UPB_ALIGN_MALLOC(size); - size_t span = size + UPB_ASAN_GUARD_SIZE; - if (UPB_UNLIKELY(_upb_ArenaHas(a) < span)) { - return _upb_Arena_SlowMalloc(a, size); - } - - // We have enough space to do a fast malloc. - _upb_ArenaHead* h = (_upb_ArenaHead*)a; - void* ret = h->ptr; - UPB_ASSERT(UPB_ALIGN_MALLOC((uintptr_t)ret) == (uintptr_t)ret); - UPB_ASSERT(UPB_ALIGN_MALLOC(size) == size); - UPB_UNPOISON_MEMORY_REGION(ret, size); +void upb_strtable_clear(upb_strtable* t); - h->ptr += span; +// Inserts the given key into the hashtable with the given value. +// The key must not already exist in the hash table. The key is not required +// to be NULL-terminated, and the table will make an internal copy of the key. +// +// If a table resize was required but memory allocation failed, false is +// returned and the table is unchanged. */ +bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len, + upb_value val, upb_Arena* a); - return ret; -} +// Looks up key in this table, returning "true" if the key was found. +// If v is non-NULL, copies the value for this key into *v. +bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len, + upb_value* v); -// Shrinks the last alloc from arena. -// REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena. -// We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if -// this was not the last alloc. -UPB_API_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, - size_t oldsize, size_t size) { - _upb_ArenaHead* h = (_upb_ArenaHead*)a; - oldsize = UPB_ALIGN_MALLOC(oldsize); - size = UPB_ALIGN_MALLOC(size); - // Must be the last alloc. - UPB_ASSERT((char*)ptr + oldsize == h->ptr - UPB_ASAN_GUARD_SIZE); - UPB_ASSERT(size <= oldsize); - h->ptr = (char*)ptr + size; +// For NULL-terminated strings. +UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key, + upb_value* v) { + return upb_strtable_lookup2(t, key, strlen(key), v); } -UPB_API_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize, - size_t size) { - _upb_ArenaHead* h = (_upb_ArenaHead*)a; - oldsize = UPB_ALIGN_MALLOC(oldsize); - size = UPB_ALIGN_MALLOC(size); - bool is_most_recent_alloc = (uintptr_t)ptr + oldsize == (uintptr_t)h->ptr; - - if (is_most_recent_alloc) { - ptrdiff_t diff = size - oldsize; - if ((ptrdiff_t)_upb_ArenaHas(a) >= diff) { - h->ptr += diff; - return ptr; - } - } else if (size <= oldsize) { - return ptr; - } - - void* ret = upb_Arena_Malloc(a, size); - - if (ret && oldsize > 0) { - memcpy(ret, ptr, UPB_MIN(oldsize, size)); - } - - return ret; -} +// Removes an item from the table. Returns true if the remove was successful, +// and stores the removed item in *val if non-NULL. +bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len, + upb_value* val); -UPB_API_INLINE upb_Arena* upb_Arena_New(void) { - return upb_Arena_Init(NULL, 0, &upb_alloc_global); +UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key, + upb_value* v) { + return upb_strtable_remove2(t, key, strlen(key), v); } -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_MEM_ARENA_H_ */ - -// Must be last. - -#ifdef __cplusplus -extern "C" { -#endif - -// Creates a new array on the given arena that holds elements of this type. -UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type); - -// Returns the number of elements in the array. -UPB_API size_t upb_Array_Size(const upb_Array* arr); - -// Returns the given element, which must be within the array's current size. -UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i); +// Exposed for testing only. +bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a); -// Sets the given element, which must be within the array's current size. -UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val); +/* Iteration over strtable: + * + * intptr_t iter = UPB_STRTABLE_BEGIN; + * upb_StringView key; + * upb_value val; + * while (upb_strtable_next2(t, &key, &val, &iter)) { + * // ... + * } + */ -// Appends an element to the array. Returns false on allocation failure. -UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val, - upb_Arena* arena); +#define UPB_STRTABLE_BEGIN -1 -// Moves elements within the array using memmove(). -// Like memmove(), the source and destination elements may be overlapping. -UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx, - size_t count); +bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, + upb_value* val, intptr_t* iter); +void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter); +void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v); -// Inserts one or more empty elements into the array. -// Existing elements are shifted right. -// The new elements have undefined state and must be set with `upb_Array_Set()`. -// REQUIRES: `i <= upb_Array_Size(arr)` -UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count, - upb_Arena* arena); +/* DEPRECATED iterators, slated for removal. + * + * Iterators for string tables. We are subject to some kind of unusual + * design constraints: + * + * For high-level languages: + * - we must be able to guarantee that we don't crash or corrupt memory even if + * the program accesses an invalidated iterator. + * + * For C++11 range-based for: + * - iterators must be copyable + * - iterators must be comparable + * - it must be possible to construct an "end" value. + * + * Iteration order is undefined. + * + * Modifying the table invalidates iterators. upb_{str,int}table_done() is + * guaranteed to work even on an invalidated iterator, as long as the table it + * is iterating over has not been freed. Calling next() or accessing data from + * an invalidated iterator yields unspecified elements from the table, but it is + * guaranteed not to crash and to return real table elements (except when done() + * is true). */ +/* upb_strtable_iter **********************************************************/ -// Deletes one or more elements from the array. -// Existing elements are shifted left. -// REQUIRES: `i + count <= upb_Array_Size(arr)` -UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count); +/* upb_strtable_iter i; + * upb_strtable_begin(&i, t); + * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + * const char *key = upb_strtable_iter_key(&i); + * const upb_value val = upb_strtable_iter_value(&i); + * // ... + * } + */ -// Changes the size of a vector. New elements are initialized to NULL/0. -// Returns false on allocation failure. -UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena); +typedef struct { + const upb_strtable* t; + size_t index; +} upb_strtable_iter; -// Returns pointer to array data. -UPB_API const void* upb_Array_DataPtr(const upb_Array* arr); +UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) { + return &i->t->t.entries[i->index]; +} -// Returns mutable pointer to array data. -UPB_API void* upb_Array_MutableDataPtr(upb_Array* arr); +void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t); +void upb_strtable_next(upb_strtable_iter* i); +bool upb_strtable_done(const upb_strtable_iter* i); +upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i); +upb_value upb_strtable_iter_value(const upb_strtable_iter* i); +void upb_strtable_iter_setdone(upb_strtable_iter* i); +bool upb_strtable_iter_isequal(const upb_strtable_iter* i1, + const upb_strtable_iter* i2); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_COLLECTIONS_ARRAY_H_ */ +#endif /* UPB_HASH_STR_TABLE_H_ */ // Must be last. +struct upb_Map { + // Size of key and val, based on the map type. + // Strings are represented as '0' because they must be handled specially. + char key_size; + char val_size; + + upb_strtable table; +}; + #ifdef __cplusplus extern "C" { #endif -// LINT.IfChange(struct_definition) -// Our internal representation for repeated fields. -struct upb_Array { - uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */ - size_t size; /* The number of elements in the array. */ - size_t capacity; /* Allocated storage. Measured in elements. */ -}; -// LINT.ThenChange(GoogleInternalName1) +// Converting between internal table representation and user values. +// +// _upb_map_tokey() and _upb_map_fromkey() are inverses. +// _upb_map_tovalue() and _upb_map_fromvalue() are inverses. +// +// These functions account for the fact that strings are treated differently +// from other types when stored in a map. -UPB_INLINE size_t _upb_Array_ElementSizeLg2(const upb_Array* arr) { - size_t ret = arr->data & 7; - UPB_ASSERT(ret <= 4); - return ret; +UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + return *(upb_StringView*)key; + } else { + return upb_StringView_FromDataAndSize((const char*)key, size); + } } -UPB_INLINE const void* _upb_array_constptr(const upb_Array* arr) { - _upb_Array_ElementSizeLg2(arr); // Check assertion. - return (void*)(arr->data & ~(uintptr_t)7); +UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + memcpy(out, &key, sizeof(key)); + } else { + memcpy(out, key.data, size); + } } -UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) { - UPB_ASSERT(elem_size_lg2 <= 4); - return (uintptr_t)ptr | elem_size_lg2; +UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size, + upb_value* msgval, upb_Arena* a) { + if (size == UPB_MAPTYPE_STRING) { + upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp)); + if (!strp) return false; + *strp = *(upb_StringView*)val; + *msgval = upb_value_ptr(strp); + } else { + memcpy(msgval, val, size); + } + return true; } -UPB_INLINE void* _upb_array_ptr(upb_Array* arr) { - return (void*)_upb_array_constptr(arr); +UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val); + memcpy(out, strp, sizeof(upb_StringView)); + } else { + memcpy(out, &val, size); + } } -UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) { - UPB_ASSERT(elem_size_lg2 <= 4); - UPB_ASSERT(((uintptr_t)ptr & 7) == 0); - return (uintptr_t)ptr | (unsigned)elem_size_lg2; +UPB_INLINE void* _upb_map_next(const upb_Map* map, size_t* iter) { + upb_strtable_iter it; + it.t = &map->table; + it.index = *iter; + upb_strtable_next(&it); + *iter = it.index; + if (upb_strtable_done(&it)) return NULL; + return (void*)str_tabent(&it); } -extern const char _upb_Array_CTypeSizeLg2Table[]; - -UPB_INLINE size_t _upb_Array_CTypeSizeLg2(upb_CType ctype) { - return _upb_Array_CTypeSizeLg2Table[ctype]; +UPB_INLINE void _upb_Map_Clear(upb_Map* map) { + upb_strtable_clear(&map->table); } -UPB_INLINE upb_Array* _upb_Array_New(upb_Arena* a, size_t init_capacity, - int elem_size_lg2) { - UPB_ASSERT(elem_size_lg2 <= 4); - const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_Array), UPB_MALLOC_ALIGN); - const size_t bytes = arr_size + (init_capacity << elem_size_lg2); - upb_Array* arr = (upb_Array*)upb_Arena_Malloc(a, bytes); - if (!arr) return NULL; - arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2); - arr->size = 0; - arr->capacity = init_capacity; - return arr; +UPB_INLINE bool _upb_Map_Delete(upb_Map* map, const void* key, size_t key_size, + upb_value* val) { + upb_StringView k = _upb_map_tokey(key, key_size); + return upb_strtable_remove2(&map->table, k.data, k.size, val); } -// Resizes the capacity of the array to be at least min_size. -bool _upb_array_realloc(upb_Array* arr, size_t min_size, upb_Arena* arena); - -UPB_INLINE bool _upb_array_reserve(upb_Array* arr, size_t size, - upb_Arena* arena) { - if (arr->capacity < size) return _upb_array_realloc(arr, size, arena); - return true; +UPB_INLINE bool _upb_Map_Get(const upb_Map* map, const void* key, + size_t key_size, void* val, size_t val_size) { + upb_value tabval; + upb_StringView k = _upb_map_tokey(key, key_size); + bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); + if (ret && val) { + _upb_map_fromvalue(tabval, val, val_size); + } + return ret; } -// Resize without initializing new elements. -UPB_INLINE bool _upb_Array_ResizeUninitialized(upb_Array* arr, size_t size, - upb_Arena* arena) { - UPB_ASSERT(size <= arr->size || arena); // Allow NULL arena when shrinking. - if (!_upb_array_reserve(arr, size, arena)) return false; - arr->size = size; - return true; -} +UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(upb_Map* map, const void* key, + size_t key_size, void* val, + size_t val_size, upb_Arena* a) { + upb_StringView strkey = _upb_map_tokey(key, key_size); + upb_value tabval = {0}; + if (!_upb_map_tovalue(val, val_size, &tabval, a)) { + return kUpb_MapInsertStatus_OutOfMemory; + } -// This function is intended for situations where elem_size is compile-time -// constant or a known expression of the form (1 << lg2), so that the expression -// i*elem_size does not result in an actual multiplication. -UPB_INLINE void _upb_Array_Set(upb_Array* arr, size_t i, const void* data, - size_t elem_size) { - UPB_ASSERT(i < arr->size); - UPB_ASSERT(elem_size == 1U << _upb_Array_ElementSizeLg2(arr)); - char* arr_data = (char*)_upb_array_ptr(arr); - memcpy(arr_data + (i * elem_size), data, elem_size); + // TODO(haberman): add overwrite operation to minimize number of lookups. + bool removed = + upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL); + if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) { + return kUpb_MapInsertStatus_OutOfMemory; + } + return removed ? kUpb_MapInsertStatus_Replaced + : kUpb_MapInsertStatus_Inserted; } -UPB_INLINE void _upb_array_detach(const void* msg, size_t ofs) { - *UPB_PTR_AT(msg, ofs, upb_Array*) = NULL; +UPB_INLINE size_t _upb_Map_Size(const upb_Map* map) { + return map->table.t.count; } -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_COLLECTIONS_INTERNAL_ARRAY_H_ */ - -#ifndef UPB_COLLECTIONS_MAP_H_ -#define UPB_COLLECTIONS_MAP_H_ +// Strings/bytes are special-cased in maps. +extern char _upb_Map_CTypeSizeTable[12]; +UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) { + return _upb_Map_CTypeSizeTable[ctype]; +} -// Must be last. +// Creates a new map on the given arena with this key/value type. +upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size); #ifdef __cplusplus -extern "C" { +} /* extern "C" */ #endif -// Creates a new map on the given arena with the given key/value size. -UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, - upb_CType value_type); - -// Returns the number of entries in the map. -UPB_API size_t upb_Map_Size(const upb_Map* map); - -// Stores a value for the given key into |*val| (or the zero value if the key is -// not present). Returns whether the key was present. The |val| pointer may be -// NULL, in which case the function tests whether the given key is present. -UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, - upb_MessageValue* val); -// Removes all entries in the map. -UPB_API void upb_Map_Clear(upb_Map* map); +#endif /* UPB_COLLECTIONS_INTERNAL_MAP_H_ */ -typedef enum { - kUpb_MapInsertStatus_Inserted = 0, - kUpb_MapInsertStatus_Replaced = 1, - kUpb_MapInsertStatus_OutOfMemory = 2, -} upb_MapInsertStatus; +// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// -// Sets the given key to the given value, returning whether the key was inserted -// or replaced. If the key was inserted, then any existing iterators will be -// invalidated. -UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, - upb_Arena* arena); +#ifndef UPB_COLLECTIONS_INTERNAL_MAP_SORTER_H_ +#define UPB_COLLECTIONS_INTERNAL_MAP_SORTER_H_ -// Sets the given key to the given value. Returns false if memory allocation -// failed. If the key is newly inserted, then any existing iterators will be -// invalidated. -UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, upb_Arena* arena) { - return upb_Map_Insert(map, key, val, arena) != - kUpb_MapInsertStatus_OutOfMemory; -} +#include -// Deletes this key from the table. Returns true if the key was present. -// If present and |val| is non-NULL, stores the deleted value. -UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, - upb_MessageValue* val); -// (DEPRECATED and going away soon. Do not use.) -UPB_INLINE bool upb_Map_Delete2(upb_Map* map, upb_MessageValue key, - upb_MessageValue* val) { - return upb_Map_Delete(map, key, val); -} +#ifndef UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ +#define UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ -// Map iteration: -// -// size_t iter = kUpb_Map_Begin; -// upb_MessageValue key, val; -// while (upb_Map_Next(map, &key, &val, &iter)) { -// ... -// } -#define kUpb_Map_Begin ((size_t)-1) +#ifndef UPB_MINI_TABLE_INTERNAL_TYPES_H_ +#define UPB_MINI_TABLE_INTERNAL_TYPES_H_ -// Advances to the next entry. Returns false if no more entries are present. -// Otherwise returns true and populates both *key and *value. -UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, - upb_MessageValue* val, size_t* iter); +typedef struct upb_Message_InternalData upb_Message_InternalData; -// Sets the value for the entry pointed to by iter. -// WARNING: this does not currently work for string values! -UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, - upb_MessageValue val); +typedef struct { + union { + upb_Message_InternalData* internal; -// DEPRECATED iterator, slated for removal. + // Force 8-byte alignment, since the data members may contain members that + // require 8-byte alignment. + double d; + }; +} upb_Message_Internal; -/* Map iteration: - * - * size_t iter = kUpb_Map_Begin; - * while (upb_MapIterator_Next(map, &iter)) { - * upb_MessageValue key = upb_MapIterator_Key(map, iter); - * upb_MessageValue val = upb_MapIterator_Value(map, iter); - * } - */ +#endif // UPB_MINI_TABLE_INTERNAL_TYPES_H_ -// Advances to the next entry. Returns false if no more entries are present. -UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter); +// Map entries aren't actually stored for map fields, they are only used during +// parsing. For parsing, it helps a lot if all map entry messages have the same +// layout. The layout code in mini_table/decode.c will ensure that all map +// entries have this layout. +// +// Note that users can and do create map entries directly, which will also use +// this layout. +// +// NOTE: sync with wire/decode.c. +typedef struct { + // We only need 2 hasbits max, but due to alignment we'll use 8 bytes here, + // and the uint64_t helps make this clear. + uint64_t hasbits; + union { + upb_StringView str; // For str/bytes. + upb_value val; // For all other types. + } k; + union { + upb_StringView str; // For str/bytes. + upb_value val; // For all other types. + } v; +} upb_MapEntryData; -// Returns true if the iterator still points to a valid entry, or false if the -// iterator is past the last element. It is an error to call this function with -// kUpb_Map_Begin (you must call next() at least once first). -UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter); +typedef struct { + upb_Message_Internal internal; + upb_MapEntryData data; +} upb_MapEntry; -// Returns the key and value for this entry of the map. -UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter); -UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter); +#endif // UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ -#ifdef __cplusplus -} /* extern "C" */ -#endif +#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_ +#define UPB_MESSAGE_INTERNAL_EXTENSION_H_ -#endif /* UPB_COLLECTIONS_MAP_H_ */ +// Public APIs for message operations that do not depend on the schema. +// +// MiniTable-based accessors live in accessors.h. -// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// +#ifndef UPB_MESSAGE_MESSAGE_H_ +#define UPB_MESSAGE_MESSAGE_H_ -#ifndef UPB_COLLECTIONS_INTERNAL_MAP_H_ -#define UPB_COLLECTIONS_INTERNAL_MAP_H_ +#include -#ifndef UPB_HASH_STR_TABLE_H_ -#define UPB_HASH_STR_TABLE_H_ +#ifndef UPB_MINI_TABLE_MESSAGE_H_ +#define UPB_MINI_TABLE_MESSAGE_H_ -/* - * upb_table - * - * This header is INTERNAL-ONLY! Its interfaces are not public or stable! - * This file defines very fast int->upb_value (inttable) and string->upb_value - * (strtable) hash tables. - * - * The table uses chained scatter with Brent's variation (inspired by the Lua - * implementation of hash tables). The hash function for strings is Austin - * Appleby's "MurmurHash." - * - * The inttable uses uintptr_t as its key, which guarantees it can be used to - * store pointers or integers of at least 32 bits (upb isn't really useful on - * systems where sizeof(void*) < 4). - * - * The table must be homogeneous (all values of the same type). In debug - * mode, we check this on insert and lookup. - */ +#ifndef UPB_MINI_TABLE_ENUM_H_ +#define UPB_MINI_TABLE_ENUM_H_ -#ifndef UPB_HASH_COMMON_H_ -#define UPB_HASH_COMMON_H_ -#include +#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_ +#define UPB_MINI_TABLE_INTERNAL_ENUM_H_ +#include // Must be last. +struct upb_MiniTableEnum { + uint32_t mask_limit; // Limit enum value that can be tested with mask. + uint32_t value_count; // Number of values after the bitfield. + uint32_t data[]; // Bitmask + enumerated values follow. +}; + +typedef enum { + _kUpb_FastEnumCheck_ValueIsInEnum = 0, + _kUpb_FastEnumCheck_ValueIsNotInEnum = 1, + _kUpb_FastEnumCheck_CannotCheckFast = 2, +} _kUpb_FastEnumCheck_Status; + #ifdef __cplusplus extern "C" { #endif -/* upb_value ******************************************************************/ - -typedef struct { - uint64_t val; -} upb_value; - -UPB_INLINE void _upb_value_setval(upb_value* v, uint64_t val) { v->val = val; } +UPB_INLINE _kUpb_FastEnumCheck_Status _upb_MiniTable_CheckEnumValueFast( + const struct upb_MiniTableEnum* e, uint32_t val) { + if (UPB_UNLIKELY(val >= 64)) return _kUpb_FastEnumCheck_CannotCheckFast; + uint64_t mask = e->data[0] | ((uint64_t)e->data[1] << 32); + return (mask & (1ULL << val)) ? _kUpb_FastEnumCheck_ValueIsInEnum + : _kUpb_FastEnumCheck_ValueIsNotInEnum; +} -/* For each value ctype, define the following set of functions: - * - * // Get/set an int32 from a upb_value. - * int32_t upb_value_getint32(upb_value val); - * void upb_value_setint32(upb_value *val, int32_t cval); - * - * // Construct a new upb_value from an int32. - * upb_value upb_value_int32(int32_t val); */ -#define FUNCS(name, membername, type_t, converter) \ - UPB_INLINE void upb_value_set##name(upb_value* val, type_t cval) { \ - val->val = (converter)cval; \ - } \ - UPB_INLINE upb_value upb_value_##name(type_t val) { \ - upb_value ret; \ - upb_value_set##name(&ret, val); \ - return ret; \ - } \ - UPB_INLINE type_t upb_value_get##name(upb_value val) { \ - return (type_t)(converter)val.val; \ +UPB_INLINE bool _upb_MiniTable_CheckEnumValueSlow( + const struct upb_MiniTableEnum* e, uint32_t val) { + if (val < e->mask_limit) return e->data[val / 32] & (1ULL << (val % 32)); + // OPT: binary search long lists? + const uint32_t* start = &e->data[e->mask_limit / 32]; + const uint32_t* limit = &e->data[(e->mask_limit / 32) + e->value_count]; + for (const uint32_t* p = start; p < limit; p++) { + if (*p == val) return true; } + return false; +} -FUNCS(int32, int32, int32_t, int32_t) -FUNCS(int64, int64, int64_t, int64_t) -FUNCS(uint32, uint32, uint32_t, uint32_t) -FUNCS(uint64, uint64, uint64_t, uint64_t) -FUNCS(bool, _bool, bool, bool) -FUNCS(cstr, cstr, char*, uintptr_t) -FUNCS(uintptr, uptr, uintptr_t, uintptr_t) -FUNCS(ptr, ptr, void*, uintptr_t) -FUNCS(constptr, constptr, const void*, uintptr_t) +#ifdef __cplusplus +} /* extern "C" */ +#endif -#undef FUNCS -UPB_INLINE void upb_value_setfloat(upb_value* val, float cval) { - memcpy(&val->val, &cval, sizeof(cval)); -} +#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */ -UPB_INLINE void upb_value_setdouble(upb_value* val, double cval) { - memcpy(&val->val, &cval, sizeof(cval)); -} +// Must be last -UPB_INLINE upb_value upb_value_float(float cval) { - upb_value ret; - upb_value_setfloat(&ret, cval); - return ret; -} +typedef struct upb_MiniTableEnum upb_MiniTableEnum; -UPB_INLINE upb_value upb_value_double(double cval) { - upb_value ret; - upb_value_setdouble(&ret, cval); - return ret; +// Validates enum value against range defined by enum mini table. +UPB_INLINE bool upb_MiniTableEnum_CheckValue(const struct upb_MiniTableEnum* e, + uint32_t val) { + _kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, val); + if (UPB_UNLIKELY(status == _kUpb_FastEnumCheck_CannotCheckFast)) { + return _upb_MiniTable_CheckEnumValueSlow(e, val); + } + return status == _kUpb_FastEnumCheck_ValueIsInEnum ? true : false; } -/* upb_tabkey *****************************************************************/ -/* Either: - * 1. an actual integer key, or - * 2. a pointer to a string prefixed by its uint32_t length, owned by us. - * - * ...depending on whether this is a string table or an int table. We would - * make this a union of those two types, but C89 doesn't support statically - * initializing a non-first union member. */ -typedef uintptr_t upb_tabkey; +#endif /* UPB_MINI_TABLE_ENUM_H_ */ -UPB_INLINE char* upb_tabstr(upb_tabkey key, uint32_t* len) { - char* mem = (char*)key; - if (len) memcpy(len, mem, sizeof(*len)); - return mem + sizeof(*len); -} +#ifndef UPB_MINI_TABLE_FIELD_H_ +#define UPB_MINI_TABLE_FIELD_H_ -UPB_INLINE upb_StringView upb_tabstrview(upb_tabkey key) { - upb_StringView ret; - uint32_t len; - ret.data = upb_tabstr(key, &len); - ret.size = len; - return ret; -} -/* upb_tabval *****************************************************************/ +#ifndef UPB_MINI_TABLE_INTERNAL_FIELD_H_ +#define UPB_MINI_TABLE_INTERNAL_FIELD_H_ -typedef struct upb_tabval { - uint64_t val; -} upb_tabval; +#include -#define UPB_TABVALUE_EMPTY_INIT \ - { -1 } -/* upb_table ******************************************************************/ +// Must be last. -typedef struct _upb_tabent { - upb_tabkey key; - upb_tabval val; +struct upb_MiniTableField { + uint32_t number; + uint16_t offset; + int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index - /* Internal chaining. This is const so we can create static initializers for - * tables. We cast away const sometimes, but *only* when the containing - * upb_table is known to be non-const. This requires a bit of care, but - * the subtlety is confined to table.c. */ - const struct _upb_tabent* next; -} upb_tabent; + // Indexes into `upb_MiniTable.subs` + // Will be set to `kUpb_NoSub` if `descriptortype` != MESSAGE/GROUP/ENUM + uint16_t UPB_PRIVATE(submsg_index); -typedef struct { - size_t count; /* Number of entries in the hash part. */ - uint32_t mask; /* Mask to turn hash value -> bucket. */ - uint32_t max_count; /* Max count before we hit our load limit. */ - uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ - upb_tabent* entries; -} upb_table; + uint8_t UPB_PRIVATE(descriptortype); -UPB_INLINE size_t upb_table_size(const upb_table* t) { - return t->size_lg2 ? 1 << t->size_lg2 : 0; -} + // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift) + uint8_t mode; +}; -// Internal-only functions, in .h file only out of necessity. +#define kUpb_NoSub ((uint16_t)-1) -UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; } +typedef enum { + kUpb_FieldMode_Map = 0, + kUpb_FieldMode_Array = 1, + kUpb_FieldMode_Scalar = 2, +} upb_FieldMode; -uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed); +// Mask to isolate the upb_FieldMode from field.mode. +#define kUpb_FieldMode_Mask 3 -#ifdef __cplusplus -} /* extern "C" */ -#endif +// Extra flags on the mode field. +typedef enum { + kUpb_LabelFlags_IsPacked = 4, + kUpb_LabelFlags_IsExtension = 8, + // Indicates that this descriptor type is an "alternate type": + // - for Int32, this indicates that the actual type is Enum (but was + // rewritten to Int32 because it is an open enum that requires no check). + // - for Bytes, this indicates that the actual type is String (but does + // not require any UTF-8 check). + kUpb_LabelFlags_IsAlternate = 16, +} upb_LabelFlags; +// Note: we sort by this number when calculating layout order. +typedef enum { + kUpb_FieldRep_1Byte = 0, + kUpb_FieldRep_4Byte = 1, + kUpb_FieldRep_StringView = 2, + kUpb_FieldRep_8Byte = 3, -#endif /* UPB_HASH_COMMON_H_ */ + kUpb_FieldRep_NativePointer = + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte), + kUpb_FieldRep_Max = kUpb_FieldRep_8Byte, +} upb_FieldRep; -// Must be last. +#define kUpb_FieldRep_Shift 6 -typedef struct { - upb_table t; -} upb_strtable; +UPB_INLINE upb_FieldRep +_upb_MiniTableField_GetRep(const struct upb_MiniTableField* field) { + return (upb_FieldRep)(field->mode >> kUpb_FieldRep_Shift); +} #ifdef __cplusplus extern "C" { #endif -// Initialize a table. If memory allocation failed, false is returned and -// the table is uninitialized. -bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a); - -// Returns the number of values in the table. -UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) { - return t->t.count; +UPB_INLINE upb_FieldMode +upb_FieldMode_Get(const struct upb_MiniTableField* field) { + return (upb_FieldMode)(field->mode & 3); } -void upb_strtable_clear(upb_strtable* t); - -// Inserts the given key into the hashtable with the given value. -// The key must not already exist in the hash table. The key is not required -// to be NULL-terminated, and the table will make an internal copy of the key. -// -// If a table resize was required but memory allocation failed, false is -// returned and the table is unchanged. */ -bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len, - upb_value val, upb_Arena* a); - -// Looks up key in this table, returning "true" if the key was found. -// If v is non-NULL, copies the value for this key into *v. -bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len, - upb_value* v); +UPB_INLINE void _upb_MiniTableField_CheckIsArray( + const struct upb_MiniTableField* field) { + UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_FieldMode_Get(field) == kUpb_FieldMode_Array); + UPB_ASSUME(field->presence == 0); +} -// For NULL-terminated strings. -UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key, - upb_value* v) { - return upb_strtable_lookup2(t, key, strlen(key), v); +UPB_INLINE void _upb_MiniTableField_CheckIsMap( + const struct upb_MiniTableField* field) { + UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_FieldMode_Get(field) == kUpb_FieldMode_Map); + UPB_ASSUME(field->presence == 0); } -// Removes an item from the table. Returns true if the remove was successful, -// and stores the removed item in *val if non-NULL. -bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len, - upb_value* val); +UPB_INLINE bool upb_IsRepeatedOrMap(const struct upb_MiniTableField* field) { + // This works because upb_FieldMode has no value 3. + return !(field->mode & kUpb_FieldMode_Scalar); +} -UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key, - upb_value* v) { - return upb_strtable_remove2(t, key, strlen(key), v); +UPB_INLINE bool upb_IsSubMessage(const struct upb_MiniTableField* field) { + return field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message || + field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group; } -// Exposed for testing only. -bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a); +#ifdef __cplusplus +} /* extern "C" */ +#endif -/* Iteration over strtable: - * - * intptr_t iter = UPB_STRTABLE_BEGIN; - * upb_StringView key; - * upb_value val; - * while (upb_strtable_next2(t, &key, &val, &iter)) { - * // ... - * } - */ -#define UPB_STRTABLE_BEGIN -1 +#endif /* UPB_MINI_TABLE_INTERNAL_FIELD_H_ */ -bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, - upb_value* val, intptr_t* iter); -void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter); -void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v); +#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ +#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ -/* DEPRECATED iterators, slated for removal. - * - * Iterators for string tables. We are subject to some kind of unusual - * design constraints: - * - * For high-level languages: - * - we must be able to guarantee that we don't crash or corrupt memory even if - * the program accesses an invalidated iterator. - * - * For C++11 range-based for: - * - iterators must be copyable - * - iterators must be comparable - * - it must be possible to construct an "end" value. - * - * Iteration order is undefined. - * - * Modifying the table invalidates iterators. upb_{str,int}table_done() is - * guaranteed to work even on an invalidated iterator, as long as the table it - * is iterating over has not been freed. Calling next() or accessing data from - * an invalidated iterator yields unspecified elements from the table, but it is - * guaranteed not to crash and to return real table elements (except when done() - * is true). */ -/* upb_strtable_iter **********************************************************/ -/* upb_strtable_iter i; - * upb_strtable_begin(&i, t); - * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - * const char *key = upb_strtable_iter_key(&i); - * const upb_value val = upb_strtable_iter_value(&i); - * // ... - * } - */ +// Must be last. +struct upb_Decoder; +typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr, + upb_Message* msg, intptr_t table, + uint64_t hasbits, uint64_t data); typedef struct { - const upb_strtable* t; - size_t index; -} upb_strtable_iter; - -UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) { - return &i->t->t.entries[i->index]; -} + uint64_t field_data; + _upb_FieldParser* field_parser; +} _upb_FastTable_Entry; -void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t); -void upb_strtable_next(upb_strtable_iter* i); -bool upb_strtable_done(const upb_strtable_iter* i); -upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i); -upb_value upb_strtable_iter_value(const upb_strtable_iter* i); -void upb_strtable_iter_setdone(upb_strtable_iter* i); -bool upb_strtable_iter_isequal(const upb_strtable_iter* i1, - const upb_strtable_iter* i2); +typedef enum { + kUpb_ExtMode_NonExtendable = 0, // Non-extendable message. + kUpb_ExtMode_Extendable = 1, // Normal extendable message. + kUpb_ExtMode_IsMessageSet = 2, // MessageSet message. + kUpb_ExtMode_IsMessageSet_ITEM = + 3, // MessageSet item (temporary only, see decode.c) -#ifdef __cplusplus -} /* extern "C" */ -#endif + // During table building we steal a bit to indicate that the message is a map + // entry. *Only* used during table building! + kUpb_ExtMode_IsMapEntry = 4, +} upb_ExtMode; +union upb_MiniTableSub; -#endif /* UPB_HASH_STR_TABLE_H_ */ +// upb_MiniTable represents the memory layout of a given upb_MessageDef. +// The members are public so generated code can initialize them, +// but users MUST NOT directly read or write any of its members. +struct upb_MiniTable { + const union upb_MiniTableSub* subs; + const struct upb_MiniTableField* fields; -// Must be last. + // Must be aligned to sizeof(void*). Doesn't include internal members like + // unknown fields, extension dict, pointer to msglayout, etc. + uint16_t size; -struct upb_Map { - // Size of key and val, based on the map type. - // Strings are represented as '0' because they must be handled specially. - char key_size; - char val_size; + uint16_t field_count; + uint8_t ext; // upb_ExtMode, declared as uint8_t so sizeof(ext) == 1 + uint8_t dense_below; + uint8_t table_mask; + uint8_t required_count; // Required fields have the lowest hasbits. - upb_strtable table; + // To statically initialize the tables of variable length, we need a flexible + // array member, and we need to compile in gnu99 mode (constant initialization + // of flexible array members is a GNU extension, not in C99 unfortunately. + _upb_FastTable_Entry fasttable[]; }; #ifdef __cplusplus extern "C" { #endif -// Converting between internal table representation and user values. -// -// _upb_map_tokey() and _upb_map_fromkey() are inverses. -// _upb_map_tovalue() and _upb_map_fromvalue() are inverses. -// -// These functions account for the fact that strings are treated differently -// from other types when stored in a map. - -UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - return *(upb_StringView*)key; - } else { - return upb_StringView_FromDataAndSize((const char*)key, size); - } -} - -UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - memcpy(out, &key, sizeof(key)); - } else { - memcpy(out, key.data, size); - } -} +// A MiniTable for an empty message, used for unlinked sub-messages. +extern const struct upb_MiniTable _kUpb_MiniTable_Empty; -UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size, - upb_value* msgval, upb_Arena* a) { - if (size == UPB_MAPTYPE_STRING) { - upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp)); - if (!strp) return false; - *strp = *(upb_StringView*)val; - *msgval = upb_value_ptr(strp); - } else { - memcpy(msgval, val, size); - } - return true; +// Computes a bitmask in which the |l->required_count| lowest bits are set, +// except that we skip the lowest bit (because upb never uses hasbit 0). +// +// Sample output: +// requiredmask(1) => 0b10 (0x2) +// requiredmask(5) => 0b111110 (0x3e) +UPB_INLINE uint64_t upb_MiniTable_requiredmask(const struct upb_MiniTable* l) { + int n = l->required_count; + assert(0 < n && n <= 63); + return ((1ULL << n) - 1) << 1; } -UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val); - memcpy(out, strp, sizeof(upb_StringView)); - } else { - memcpy(out, &val, size); - } -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_INLINE void* _upb_map_next(const upb_Map* map, size_t* iter) { - upb_strtable_iter it; - it.t = &map->table; - it.index = *iter; - upb_strtable_next(&it); - *iter = it.index; - if (upb_strtable_done(&it)) return NULL; - return (void*)str_tabent(&it); -} -UPB_INLINE void _upb_Map_Clear(upb_Map* map) { - upb_strtable_clear(&map->table); -} +#endif /* UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ */ -UPB_INLINE bool _upb_Map_Delete(upb_Map* map, const void* key, size_t key_size, - upb_value* val) { - upb_StringView k = _upb_map_tokey(key, key_size); - return upb_strtable_remove2(&map->table, k.data, k.size, val); -} +#ifndef UPB_MINI_TABLE_INTERNAL_SUB_H_ +#define UPB_MINI_TABLE_INTERNAL_SUB_H_ -UPB_INLINE bool _upb_Map_Get(const upb_Map* map, const void* key, - size_t key_size, void* val, size_t val_size) { - upb_value tabval; - upb_StringView k = _upb_map_tokey(key, key_size); - bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); - if (ret && val) { - _upb_map_fromvalue(tabval, val, val_size); - } - return ret; -} -UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(upb_Map* map, const void* key, - size_t key_size, void* val, - size_t val_size, upb_Arena* a) { - upb_StringView strkey = _upb_map_tokey(key, key_size); - upb_value tabval = {0}; - if (!_upb_map_tovalue(val, val_size, &tabval, a)) { - return kUpb_MapInsertStatus_OutOfMemory; - } +union upb_MiniTableSub { + const struct upb_MiniTable* submsg; + const struct upb_MiniTableEnum* subenum; +}; - // TODO(haberman): add overwrite operation to minimize number of lookups. - bool removed = - upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL); - if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) { - return kUpb_MapInsertStatus_OutOfMemory; +#endif /* UPB_MINI_TABLE_INTERNAL_SUB_H_ */ + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct upb_MiniTableField upb_MiniTableField; + +UPB_API_INLINE upb_FieldType +upb_MiniTableField_Type(const upb_MiniTableField* field) { + if (field->mode & kUpb_LabelFlags_IsAlternate) { + if (field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Int32) { + return kUpb_FieldType_Enum; + } else if (field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bytes) { + return kUpb_FieldType_String; + } else { + UPB_ASSERT(false); + } } - return removed ? kUpb_MapInsertStatus_Replaced - : kUpb_MapInsertStatus_Inserted; + return (upb_FieldType)field->UPB_PRIVATE(descriptortype); } -UPB_INLINE size_t _upb_Map_Size(const upb_Map* map) { - return map->table.t.count; +UPB_API_INLINE upb_CType upb_MiniTableField_CType(const upb_MiniTableField* f) { + switch (upb_MiniTableField_Type(f)) { + case kUpb_FieldType_Double: + return kUpb_CType_Double; + case kUpb_FieldType_Float: + return kUpb_CType_Float; + case kUpb_FieldType_Int64: + case kUpb_FieldType_SInt64: + case kUpb_FieldType_SFixed64: + return kUpb_CType_Int64; + case kUpb_FieldType_Int32: + case kUpb_FieldType_SFixed32: + case kUpb_FieldType_SInt32: + return kUpb_CType_Int32; + case kUpb_FieldType_UInt64: + case kUpb_FieldType_Fixed64: + return kUpb_CType_UInt64; + case kUpb_FieldType_UInt32: + case kUpb_FieldType_Fixed32: + return kUpb_CType_UInt32; + case kUpb_FieldType_Enum: + return kUpb_CType_Enum; + case kUpb_FieldType_Bool: + return kUpb_CType_Bool; + case kUpb_FieldType_String: + return kUpb_CType_String; + case kUpb_FieldType_Bytes: + return kUpb_CType_Bytes; + case kUpb_FieldType_Group: + case kUpb_FieldType_Message: + return kUpb_CType_Message; + } + UPB_UNREACHABLE(); } -// Strings/bytes are special-cased in maps. -extern char _upb_Map_CTypeSizeTable[12]; +UPB_API_INLINE bool upb_MiniTableField_IsExtension( + const upb_MiniTableField* field) { + return field->mode & kUpb_LabelFlags_IsExtension; +} -UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) { - return _upb_Map_CTypeSizeTable[ctype]; +UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( + const upb_MiniTableField* field) { + return field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum; } -// Creates a new map on the given arena with this key/value type. -upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size); +UPB_API_INLINE bool upb_MiniTableField_HasPresence( + const upb_MiniTableField* field) { + if (upb_MiniTableField_IsExtension(field)) { + return !upb_IsRepeatedOrMap(field); + } else { + return field->presence != 0; + } +} #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_COLLECTIONS_INTERNAL_MAP_H_ */ - -// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// - -#ifndef UPB_COLLECTIONS_INTERNAL_MAP_SORTER_H_ -#define UPB_COLLECTIONS_INTERNAL_MAP_SORTER_H_ - -#include +#endif /* UPB_MINI_TABLE_FIELD_H_ */ +// Must be last. -#ifndef UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ -#define UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ +#ifdef __cplusplus +extern "C" { +#endif +typedef struct upb_MiniTable upb_MiniTable; -#ifndef UPB_MINI_TABLE_INTERNAL_TYPES_H_ -#define UPB_MINI_TABLE_INTERNAL_TYPES_H_ +UPB_API const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( + const upb_MiniTable* table, uint32_t number); -typedef struct upb_Message_InternalData upb_Message_InternalData; +UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_GetFieldByIndex( + const upb_MiniTable* t, uint32_t index) { + return &t->fields[index]; +} -typedef struct { - union { - upb_Message_InternalData* internal; +// Returns the MiniTable for this message field. If the field is unlinked, +// returns NULL. +UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( + const upb_MiniTable* mini_table, const upb_MiniTableField* field) { + UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Message); + const upb_MiniTable* ret = + mini_table->subs[field->UPB_PRIVATE(submsg_index)].submsg; + UPB_ASSUME(ret); + return ret == &_kUpb_MiniTable_Empty ? NULL : ret; +} - // Force 8-byte alignment, since the data members may contain members that - // require 8-byte alignment. - double d; - }; -} upb_Message_Internal; +// Returns the MiniTableEnum for this enum field. If the field is unlinked, +// returns NULL. +UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( + const upb_MiniTable* mini_table, const upb_MiniTableField* field) { + UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Enum); + return mini_table->subs[field->UPB_PRIVATE(submsg_index)].subenum; +} -#endif // UPB_MINI_TABLE_INTERNAL_TYPES_H_ +// Returns true if this MiniTable field is linked to a MiniTable for the +// sub-message. +UPB_API_INLINE bool upb_MiniTable_MessageFieldIsLinked( + const upb_MiniTable* mini_table, const upb_MiniTableField* field) { + return upb_MiniTable_GetSubMessageTable(mini_table, field) != NULL; +} -// Map entries aren't actually stored for map fields, they are only used during -// parsing. For parsing, it helps a lot if all map entry messages have the same -// layout. The layout code in mini_table/decode.c will ensure that all map -// entries have this layout. +// If this field is in a oneof, returns the first field in the oneof. // -// Note that users can and do create map entries directly, which will also use -// this layout. +// Otherwise returns NULL. // -// NOTE: sync with wire/decode.c. -typedef struct { - // We only need 2 hasbits max, but due to alignment we'll use 8 bytes here, - // and the uint64_t helps make this clear. - uint64_t hasbits; - union { - upb_StringView str; // For str/bytes. - upb_value val; // For all other types. - } k; - union { - upb_StringView str; // For str/bytes. - upb_value val; // For all other types. - } v; -} upb_MapEntryData; - -typedef struct { - upb_Message_Internal internal; - upb_MapEntryData data; -} upb_MapEntry; - -#endif // UPB_COLLECTIONS_INTERNAL_MAP_ENTRY_H_ - -#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_ -#define UPB_MESSAGE_INTERNAL_EXTENSION_H_ - - -// Public APIs for message operations that do not depend on the schema. +// Usage: +// const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f); +// do { +// .. +// } while (upb_MiniTable_NextOneofField(m, &field); // -// MiniTable-based accessors live in accessors.h. +const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, + const upb_MiniTableField* f); -#ifndef UPB_MESSAGE_MESSAGE_H_ -#define UPB_MESSAGE_MESSAGE_H_ +// Iterates to the next field in the oneof. If this is the last field in the +// oneof, returns false. The ordering of fields in the oneof is not +// guaranteed. +// REQUIRES: |f| is the field initialized by upb_MiniTable_GetOneof and updated +// by prior upb_MiniTable_NextOneofField calls. +bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, + const upb_MiniTableField** f); -#include +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* UPB_MINI_TABLE_MESSAGE_H_ */ + // Must be last. #ifdef __cplusplus @@ -11454,6 +11458,8 @@ int upb_Unicode_ToUTF8(uint32_t cp, char* out); #ifndef UPB_REFLECTION_MESSAGE_H_ #define UPB_REFLECTION_MESSAGE_H_ +#include + // Must be last. diff --git a/upb/cmake/google/protobuf/descriptor.upb_minitable.c b/upb/cmake/google/protobuf/descriptor.upb_minitable.c new file mode 100644 index 0000000000..eb885fcfa3 --- /dev/null +++ b/upb/cmake/google/protobuf/descriptor.upb_minitable.c @@ -0,0 +1,1351 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/upb/generated_code_support.h" +#include "google/protobuf/descriptor.upb_minitable.h" + +// Must be last. +#include "upb/upb/port/def.inc" + +static const upb_MiniTableSub google_protobuf_FileDescriptorSet_submsgs[1] = { + {.submsg = &google_protobuf_FileDescriptorProto_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_FileDescriptorSet__fields[1] = { + {1, 0, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_FileDescriptorSet_msg_init = { + &google_protobuf_FileDescriptorSet_submsgs[0], + &google_protobuf_FileDescriptorSet__fields[0], + 8, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000000003f00000a, &upb_prm_1bt_max192b}, + }) +}; + +static const upb_MiniTableSub google_protobuf_FileDescriptorProto_submsgs[7] = { + {.submsg = &google_protobuf_DescriptorProto_msg_init}, + {.submsg = &google_protobuf_EnumDescriptorProto_msg_init}, + {.submsg = &google_protobuf_ServiceDescriptorProto_msg_init}, + {.submsg = &google_protobuf_FieldDescriptorProto_msg_init}, + {.submsg = &google_protobuf_FileOptions_msg_init}, + {.submsg = &google_protobuf_SourceCodeInfo_msg_init}, + {.subenum = &google_protobuf_Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FileDescriptorProto__fields[14] = { + {1, UPB_SIZE(44, 8), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(52, 24), 2, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(4, 40), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(8, 48), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(12, 56), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(16, 64), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(20, 72), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(24, 80), 3, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {9, UPB_SIZE(28, 88), 4, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {10, UPB_SIZE(32, 96), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {11, UPB_SIZE(36, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {12, UPB_SIZE(60, 112), 5, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {13, UPB_SIZE(68, 128), 6, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {14, UPB_SIZE(40, 4), 7, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_FileDescriptorProto_msg_init = { + &google_protobuf_FileDescriptorProto_submsgs[0], + &google_protobuf_FileDescriptorProto__fields[0], + UPB_SIZE(80, 144), 14, kUpb_ExtMode_NonExtendable, 14, UPB_FASTTABLE_MASK(120), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x0018000002000012, &upb_pss_1bt}, + {0x002800003f00001a, &upb_prs_1bt}, + {0x003000003f000022, &upb_prm_1bt_max128b}, + {0x003800003f01002a, &upb_prm_1bt_max64b}, + {0x004000003f020032, &upb_prm_1bt_max64b}, + {0x004800003f03003a, &upb_prm_1bt_max128b}, + {0x0050000003040042, &upb_psm_1bt_max256b}, + {0x005800000405004a, &upb_psm_1bt_max64b}, + {0x006000003f000050, &upb_prv4_1bt}, + {0x006800003f000058, &upb_prv4_1bt}, + {0x0070000005000062, &upb_pss_1bt}, + {0x008000000600006a, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_DescriptorProto_submsgs[8] = { + {.submsg = &google_protobuf_FieldDescriptorProto_msg_init}, + {.submsg = &google_protobuf_DescriptorProto_msg_init}, + {.submsg = &google_protobuf_EnumDescriptorProto_msg_init}, + {.submsg = &google_protobuf_DescriptorProto_ExtensionRange_msg_init}, + {.submsg = &google_protobuf_FieldDescriptorProto_msg_init}, + {.submsg = &google_protobuf_MessageOptions_msg_init}, + {.submsg = &google_protobuf_OneofDescriptorProto_msg_init}, + {.submsg = &google_protobuf_DescriptorProto_ReservedRange_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_DescriptorProto__fields[10] = { + {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(4, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 32), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(12, 40), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(16, 48), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(20, 56), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(24, 64), 2, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(28, 72), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {9, UPB_SIZE(32, 80), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {10, UPB_SIZE(36, 88), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_DescriptorProto_msg_init = { + &google_protobuf_DescriptorProto_submsgs[0], + &google_protobuf_DescriptorProto__fields[0], + UPB_SIZE(48, 96), 10, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(120), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x001800003f000012, &upb_prm_1bt_max128b}, + {0x002000003f01001a, &upb_prm_1bt_max128b}, + {0x002800003f020022, &upb_prm_1bt_max64b}, + {0x003000003f03002a, &upb_prm_1bt_max64b}, + {0x003800003f040032, &upb_prm_1bt_max128b}, + {0x004000000205003a, &upb_psm_1bt_max64b}, + {0x004800003f060042, &upb_prm_1bt_max64b}, + {0x005000003f07004a, &upb_prm_1bt_max64b}, + {0x005800003f000052, &upb_prs_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = { + {.submsg = &google_protobuf_ExtensionRangeOptions_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_DescriptorProto_ExtensionRange__fields[3] = { + {1, 4, 1, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 8, 2, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(12, 16), 3, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msg_init = { + &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0], + &google_protobuf_DescriptorProto_ExtensionRange__fields[0], + UPB_SIZE(16, 24), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0004000001000008, &upb_psv4_1bt}, + {0x0008000002000010, &upb_psv4_1bt}, + {0x001000000300001a, &upb_psm_1bt_max64b}, + }) +}; + +static const upb_MiniTableField google_protobuf_DescriptorProto_ReservedRange__fields[2] = { + {1, 4, 1, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 8, 2, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msg_init = { + NULL, + &google_protobuf_DescriptorProto_ReservedRange__fields[0], + 16, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(24), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0004000001000008, &upb_psv4_1bt}, + {0x0008000002000010, &upb_psv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_ExtensionRangeOptions_submsgs[4] = { + {.submsg = &google_protobuf_ExtensionRangeOptions_Declaration_msg_init}, + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.submsg = &google_protobuf_UninterpretedOption_msg_init}, + {.subenum = &google_protobuf_ExtensionRangeOptions_VerificationState_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_ExtensionRangeOptions__fields[4] = { + {2, UPB_SIZE(4, 8), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 4), 1, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {50, UPB_SIZE(12, 16), 2, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(16, 24), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_ExtensionRangeOptions_msg_init = { + &google_protobuf_ExtensionRangeOptions_submsgs[0], + &google_protobuf_ExtensionRangeOptions__fields[0], + UPB_SIZE(24, 32), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f000012, &upb_prm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0010000002010392, &upb_psm_2bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f023eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableField google_protobuf_ExtensionRangeOptions_Declaration__fields[5] = { + {1, 4, 1, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 16), 2, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(20, 32), 3, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {5, 8, 4, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, 9, 5, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_ExtensionRangeOptions_Declaration_msg_init = { + NULL, + &google_protobuf_ExtensionRangeOptions_Declaration__fields[0], + UPB_SIZE(32, 48), 5, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(56), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0004000001000008, &upb_psv4_1bt}, + {0x0010000002000012, &upb_pss_1bt}, + {0x002000000300001a, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0008000004000028, &upb_psb1_1bt}, + {0x0009000005000030, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_FieldDescriptorProto_submsgs[3] = { + {.submsg = &google_protobuf_FieldOptions_msg_init}, + {.subenum = &google_protobuf_FieldDescriptorProto_Label_enum_init}, + {.subenum = &google_protobuf_FieldDescriptorProto_Type_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldDescriptorProto__fields[11] = { + {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, 4, 3, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, 8, 4, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, 12, 5, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(16, 88), 8, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_FieldDescriptorProto_msg_init = { + &google_protobuf_FieldDescriptorProto_submsgs[0], + &google_protobuf_FieldDescriptorProto__fields[0], + UPB_SIZE(72, 112), 11, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800000100000a, &upb_pss_1bt}, + {0x0028000002000012, &upb_pss_1bt}, + {0x0004000003000018, &upb_psv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0038000006000032, &upb_pss_1bt}, + {0x004800000700003a, &upb_pss_1bt}, + {0x0058000008000042, &upb_psm_1bt_max64b}, + {0x0010000009000048, &upb_psv4_1bt}, + {0x006000000a000052, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001400000b000188, &upb_psb1_2bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_OneofDescriptorProto_submsgs[1] = { + {.submsg = &google_protobuf_OneofOptions_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_OneofDescriptorProto__fields[2] = { + {1, 8, 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(4, 24), 2, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_OneofDescriptorProto_msg_init = { + &google_protobuf_OneofDescriptorProto_submsgs[0], + &google_protobuf_OneofDescriptorProto__fields[0], + UPB_SIZE(16, 32), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(24), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x0018000002000012, &upb_psm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_EnumDescriptorProto_submsgs[3] = { + {.submsg = &google_protobuf_EnumValueDescriptorProto_msg_init}, + {.submsg = &google_protobuf_EnumOptions_msg_init}, + {.submsg = &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_EnumDescriptorProto__fields[5] = { + {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(4, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 32), 2, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(12, 40), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(16, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_EnumDescriptorProto_msg_init = { + &google_protobuf_EnumDescriptorProto_submsgs[0], + &google_protobuf_EnumDescriptorProto__fields[0], + UPB_SIZE(32, 56), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(56), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x001800003f000012, &upb_prm_1bt_max64b}, + {0x002000000201001a, &upb_psm_1bt_max64b}, + {0x002800003f020022, &upb_prm_1bt_max64b}, + {0x003000003f00002a, &upb_prs_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableField google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { + {1, 4, 1, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 8, 2, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init = { + NULL, + &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], + 16, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(24), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0004000001000008, &upb_psv4_1bt}, + {0x0008000002000010, &upb_psv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_EnumValueDescriptorProto_submsgs[1] = { + {.submsg = &google_protobuf_EnumValueOptions_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_EnumValueDescriptorProto__fields[3] = { + {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, 4, 2, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 24), 3, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msg_init = { + &google_protobuf_EnumValueDescriptorProto_submsgs[0], + &google_protobuf_EnumValueDescriptorProto__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x0004000002000010, &upb_psv4_1bt}, + {0x001800000300001a, &upb_psm_1bt_max64b}, + }) +}; + +static const upb_MiniTableSub google_protobuf_ServiceDescriptorProto_submsgs[2] = { + {.submsg = &google_protobuf_MethodDescriptorProto_msg_init}, + {.submsg = &google_protobuf_ServiceOptions_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_ServiceDescriptorProto__fields[3] = { + {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(4, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 32), 2, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_ServiceDescriptorProto_msg_init = { + &google_protobuf_ServiceDescriptorProto_submsgs[0], + &google_protobuf_ServiceDescriptorProto__fields[0], + UPB_SIZE(24, 40), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x001800003f000012, &upb_prm_1bt_max128b}, + {0x002000000201001a, &upb_psm_1bt_max64b}, + }) +}; + +static const upb_MiniTableSub google_protobuf_MethodDescriptorProto_submsgs[1] = { + {.submsg = &google_protobuf_MethodOptions_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_MethodDescriptorProto__fields[6] = { + {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(4, 56), 4, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_MethodDescriptorProto_msg_init = { + &google_protobuf_MethodDescriptorProto_submsgs[0], + &google_protobuf_MethodDescriptorProto__fields[0], + UPB_SIZE(40, 64), 6, kUpb_ExtMode_NonExtendable, 6, UPB_FASTTABLE_MASK(56), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x0018000002000012, &upb_pss_1bt}, + {0x002800000300001a, &upb_pss_1bt}, + {0x0038000004000022, &upb_psm_1bt_max64b}, + {0x0001000005000028, &upb_psb1_1bt}, + {0x0002000006000030, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_FileOptions_submsgs[3] = { + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.submsg = &google_protobuf_UninterpretedOption_msg_init}, + {.subenum = &google_protobuf_FileOptions_OptimizeMode_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FileOptions__fields[22] = { + {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {9, 4, 3, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {10, 8, 4, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {11, UPB_SIZE(44, 56), 5, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {16, 9, 6, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {17, 10, 7, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {18, 11, 8, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {20, 12, 9, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {23, 13, 10, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {27, 14, 11, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {31, 15, 12, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {36, UPB_SIZE(52, 72), 13, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {37, UPB_SIZE(60, 88), 14, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {39, UPB_SIZE(68, 104), 15, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {40, UPB_SIZE(76, 120), 16, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {41, UPB_SIZE(84, 136), 17, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {42, 16, 18, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {44, UPB_SIZE(92, 152), 19, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {45, UPB_SIZE(100, 168), 20, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {50, UPB_SIZE(20, 184), 21, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(24, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_FileOptions_msg_init = { + &google_protobuf_FileOptions_submsgs[0], + &google_protobuf_FileOptions__fields[0], + UPB_SIZE(112, 200), 22, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800000100000a, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0028000002000042, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0008000004000050, &upb_psb1_1bt}, + {0x003800000500005a, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0009000006000180, &upb_psb1_2bt}, + {0x000a000007000188, &upb_psb1_2bt}, + {0x000b000008000190, &upb_psb1_2bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000c0000090001a0, &upb_psb1_2bt}, + {0x005800000e0002aa, &upb_pss_2bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000d00000a0001b8, &upb_psb1_2bt}, + {0x00780000100002c2, &upb_pss_2bt}, + {0x00880000110002ca, &upb_pss_2bt}, + {0x00100000120002d0, &upb_psb1_2bt}, + {0x000e00000b0001d8, &upb_psb1_2bt}, + {0x00980000130002e2, &upb_pss_2bt}, + {0x00a80000140002ea, &upb_pss_2bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000f00000c0001f8, &upb_psb1_2bt}, + }) +}; + +static const upb_MiniTableSub google_protobuf_MessageOptions_submsgs[2] = { + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.submsg = &google_protobuf_UninterpretedOption_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_MessageOptions__fields[7] = { + {1, 1, 1, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {2, 2, 2, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {3, 3, 3, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {7, 4, 4, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {11, 5, 5, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {12, 8, 6, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(12, 16), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_MessageOptions_msg_init = { + &google_protobuf_MessageOptions_submsgs[0], + &google_protobuf_MessageOptions__fields[0], + UPB_SIZE(16, 24), 7, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0001000001000008, &upb_psb1_1bt}, + {0x0002000002000010, &upb_psb1_1bt}, + {0x0003000003000018, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0004000004000038, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0005000005000058, &upb_psb1_1bt}, + {0x0008000006000062, &upb_psm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_FieldOptions_submsgs[7] = { + {.submsg = &google_protobuf_FieldOptions_EditionDefault_msg_init}, + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.submsg = &google_protobuf_UninterpretedOption_msg_init}, + {.subenum = &google_protobuf_FieldOptions_CType_enum_init}, + {.subenum = &google_protobuf_FieldOptions_JSType_enum_init}, + {.subenum = &google_protobuf_FieldOptions_OptionRetention_enum_init}, + {.subenum = &google_protobuf_FieldOptions_OptionTargetType_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldOptions__fields[13] = { + {1, 4, 1, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 8, 2, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {3, 9, 3, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {5, 10, 4, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, 12, 5, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {10, 16, 6, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {15, 17, 7, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {16, 18, 8, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {17, 20, 9, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {19, 24, 0, 6, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {20, UPB_SIZE(28, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {21, UPB_SIZE(32, 40), 10, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(36, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_FieldOptions_msg_init = { + &google_protobuf_FieldOptions_submsgs[0], + &google_protobuf_FieldOptions__fields[0], + UPB_SIZE(40, 56), 13, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0008000002000010, &upb_psb1_1bt}, + {0x0009000003000018, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000a000004000028, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0010000006000050, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0011000007000078, &upb_psb1_1bt}, + {0x0012000008000180, &upb_psb1_2bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f0001a2, &upb_prm_2bt_max64b}, + {0x002800000a0101aa, &upb_psm_2bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x003000003f023eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_FieldOptions_EditionDefault_submsgs[1] = { + {.subenum = &google_protobuf_Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldOptions_EditionDefault__fields[3] = { + {1, 8, 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(16, 24), 2, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, 4, 3, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_FieldOptions_EditionDefault_msg_init = { + &google_protobuf_FieldOptions_EditionDefault_submsgs[0], + &google_protobuf_FieldOptions_EditionDefault__fields[0], + UPB_SIZE(24, 40), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x0018000002000012, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_OneofOptions_submsgs[2] = { + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.submsg = &google_protobuf_UninterpretedOption_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_OneofOptions__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(8, 16), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_OneofOptions_msg_init = { + &google_protobuf_OneofOptions_submsgs[0], + &google_protobuf_OneofOptions__fields[0], + UPB_SIZE(16, 24), 2, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_psm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_EnumOptions_submsgs[2] = { + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.submsg = &google_protobuf_UninterpretedOption_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_EnumOptions__fields[5] = { + {2, 1, 1, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {3, 2, 2, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, 3, 3, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(4, 8), 4, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(8, 16), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_EnumOptions_msg_init = { + &google_protobuf_EnumOptions_submsgs[0], + &google_protobuf_EnumOptions__fields[0], + UPB_SIZE(16, 24), 5, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0001000001000010, &upb_psb1_1bt}, + {0x0002000002000018, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0003000003000030, &upb_psb1_1bt}, + {0x000800000400003a, &upb_psm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_EnumValueOptions_submsgs[2] = { + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.submsg = &google_protobuf_UninterpretedOption_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_EnumValueOptions__fields[4] = { + {1, 1, 1, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(4, 8), 2, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 2), 3, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(12, 16), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_EnumValueOptions_msg_init = { + &google_protobuf_EnumValueOptions_submsgs[0], + &google_protobuf_EnumValueOptions__fields[0], + UPB_SIZE(16, 24), 4, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0001000001000008, &upb_psb1_1bt}, + {0x0008000002000012, &upb_psm_1bt_max64b}, + {0x0002000003000018, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_ServiceOptions_submsgs[2] = { + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.submsg = &google_protobuf_UninterpretedOption_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_ServiceOptions__fields[3] = { + {33, 1, 1, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {34, UPB_SIZE(4, 8), 2, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(8, 16), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_ServiceOptions_msg_init = { + &google_protobuf_ServiceOptions_submsgs[0], + &google_protobuf_ServiceOptions__fields[0], + UPB_SIZE(16, 24), 3, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0001000001000288, &upb_psb1_2bt}, + {0x0008000002000292, &upb_psm_2bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_MethodOptions_submsgs[3] = { + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.submsg = &google_protobuf_UninterpretedOption_msg_init}, + {.subenum = &google_protobuf_MethodOptions_IdempotencyLevel_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_MethodOptions__fields[4] = { + {33, 1, 1, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {34, 4, 2, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {35, 8, 3, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(12, 16), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_MethodOptions_msg_init = { + &google_protobuf_MethodOptions_submsgs[0], + &google_protobuf_MethodOptions__fields[0], + UPB_SIZE(16, 24), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0001000001000288, &upb_psb1_2bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000300029a, &upb_psm_2bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_UninterpretedOption_submsgs[1] = { + {.submsg = &google_protobuf_UninterpretedOption_NamePart_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_UninterpretedOption__fields[7] = { + {2, UPB_SIZE(4, 8), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_UninterpretedOption_msg_init = { + &google_protobuf_UninterpretedOption_submsgs[0], + &google_protobuf_UninterpretedOption__fields[0], + UPB_SIZE(56, 88), 7, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(120), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f000012, &upb_prm_1bt_max64b}, + {0x001000000100001a, &upb_pss_1bt}, + {0x0020000002000020, &upb_psv8_1bt}, + {0x0028000003000028, &upb_psv8_1bt}, + {0x0030000004000031, &upb_psf8_1bt}, + {0x003800000500003a, &upb_psb_1bt}, + {0x0048000006000042, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableField google_protobuf_UninterpretedOption_NamePart__fields[2] = { + {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, 1, 2, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msg_init = { + NULL, + &google_protobuf_UninterpretedOption_NamePart__fields[0], + UPB_SIZE(16, 24), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(24), 2, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x0001000002000010, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_FeatureSet_submsgs[5] = { + {.subenum = &google_protobuf_FeatureSet_FieldPresence_enum_init}, + {.subenum = &google_protobuf_FeatureSet_EnumType_enum_init}, + {.subenum = &google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init}, + {.subenum = &google_protobuf_FeatureSet_MessageEncoding_enum_init}, + {.subenum = &google_protobuf_FeatureSet_JsonFormat_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FeatureSet__fields[5] = { + {1, 4, 1, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 8, 2, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, 12, 3, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, 16, 4, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {6, 20, 5, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_FeatureSet_msg_init = { + &google_protobuf_FeatureSet_submsgs[0], + &google_protobuf_FeatureSet__fields[0], + 24, 5, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(255), 0, +}; + +static const upb_MiniTableSub google_protobuf_FeatureSetDefaults_submsgs[3] = { + {.submsg = &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_msg_init}, + {.subenum = &google_protobuf_Edition_enum_init}, + {.subenum = &google_protobuf_Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FeatureSetDefaults__fields[5] = { + {1, UPB_SIZE(4, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(8, 4), 3, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(12, 8), 4, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_FeatureSetDefaults_msg_init = { + &google_protobuf_FeatureSetDefaults_submsgs[0], + &google_protobuf_FeatureSetDefaults__fields[0], + UPB_SIZE(32, 56), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(24), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f00000a, &upb_prm_1bt_max64b}, + {0x0018000001000012, &upb_pss_1bt}, + {0x002800000200001a, &upb_pss_1bt}, + }) +}; + +static const upb_MiniTableSub google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_submsgs[2] = { + {.submsg = &google_protobuf_FeatureSet_msg_init}, + {.subenum = &google_protobuf_Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[3] = { + {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(4, 24), 2, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 4), 3, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_msg_init = { + &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_submsgs[0], + &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800000100000a, &upb_pss_1bt}, + {0x0018000002000012, &upb_psm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_SourceCodeInfo_submsgs[1] = { + {.submsg = &google_protobuf_SourceCodeInfo_Location_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_SourceCodeInfo__fields[1] = { + {1, 0, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_SourceCodeInfo_msg_init = { + &google_protobuf_SourceCodeInfo_submsgs[0], + &google_protobuf_SourceCodeInfo__fields[0], + 8, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000000003f00000a, &upb_prm_1bt_max128b}, + }) +}; + +static const upb_MiniTableField google_protobuf_SourceCodeInfo_Location__fields[5] = { + {1, UPB_SIZE(4, 8), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(8, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(12, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msg_init = { + NULL, + &google_protobuf_SourceCodeInfo_Location__fields[0], + UPB_SIZE(32, 64), 5, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(56), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f00000a, &upb_ppv4_1bt}, + {0x001000003f000012, &upb_ppv4_1bt}, + {0x001800000100001a, &upb_pss_1bt}, + {0x0028000002000022, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x003800003f000032, &upb_prs_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_submsgs[1] = { + {.submsg = &google_protobuf_GeneratedCodeInfo_Annotation_msg_init}, +}; + +static const upb_MiniTableField google_protobuf_GeneratedCodeInfo__fields[1] = { + {1, 0, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_GeneratedCodeInfo_msg_init = { + &google_protobuf_GeneratedCodeInfo_submsgs[0], + &google_protobuf_GeneratedCodeInfo__fields[0], + 8, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000000003f00000a, &upb_prm_1bt_max64b}, + }) +}; + +static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_Annotation_submsgs[1] = { + {.subenum = &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_GeneratedCodeInfo_Annotation__fields[5] = { + {1, UPB_SIZE(4, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(16, 12), 4, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msg_init = { + &google_protobuf_GeneratedCodeInfo_Annotation_submsgs[0], + &google_protobuf_GeneratedCodeInfo_Annotation__fields[0], + UPB_SIZE(32, 40), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(56), 0, + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f00000a, &upb_ppv4_1bt}, + {0x0018000001000012, &upb_pss_1bt}, + {0x0004000002000018, &upb_psv4_1bt}, + {0x0008000003000020, &upb_psv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTable *messages_layout[32] = { + &google_protobuf_FileDescriptorSet_msg_init, + &google_protobuf_FileDescriptorProto_msg_init, + &google_protobuf_DescriptorProto_msg_init, + &google_protobuf_DescriptorProto_ExtensionRange_msg_init, + &google_protobuf_DescriptorProto_ReservedRange_msg_init, + &google_protobuf_ExtensionRangeOptions_msg_init, + &google_protobuf_ExtensionRangeOptions_Declaration_msg_init, + &google_protobuf_FieldDescriptorProto_msg_init, + &google_protobuf_OneofDescriptorProto_msg_init, + &google_protobuf_EnumDescriptorProto_msg_init, + &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, + &google_protobuf_EnumValueDescriptorProto_msg_init, + &google_protobuf_ServiceDescriptorProto_msg_init, + &google_protobuf_MethodDescriptorProto_msg_init, + &google_protobuf_FileOptions_msg_init, + &google_protobuf_MessageOptions_msg_init, + &google_protobuf_FieldOptions_msg_init, + &google_protobuf_FieldOptions_EditionDefault_msg_init, + &google_protobuf_OneofOptions_msg_init, + &google_protobuf_EnumOptions_msg_init, + &google_protobuf_EnumValueOptions_msg_init, + &google_protobuf_ServiceOptions_msg_init, + &google_protobuf_MethodOptions_msg_init, + &google_protobuf_UninterpretedOption_msg_init, + &google_protobuf_UninterpretedOption_NamePart_msg_init, + &google_protobuf_FeatureSet_msg_init, + &google_protobuf_FeatureSetDefaults_msg_init, + &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_msg_init, + &google_protobuf_SourceCodeInfo_msg_init, + &google_protobuf_SourceCodeInfo_Location_msg_init, + &google_protobuf_GeneratedCodeInfo_msg_init, + &google_protobuf_GeneratedCodeInfo_Annotation_msg_init, +}; + +const upb_MiniTableEnum google_protobuf_Edition_enum_init = { + 64, + 4, + { + 0x7, + 0x0, + 0x3e8, + 0x1869d, + 0x1869e, + 0x1869f, + }, +}; + +const upb_MiniTableEnum google_protobuf_ExtensionRangeOptions_VerificationState_enum_init = { + 64, + 0, + { + 0x3, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FeatureSet_EnumType_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FeatureSet_FieldPresence_enum_init = { + 64, + 0, + { + 0xf, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FeatureSet_JsonFormat_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FeatureSet_MessageEncoding_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init = { + 64, + 0, + { + 0xe, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init = { + 64, + 0, + { + 0x7fffe, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FieldOptions_OptionRetention_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FieldOptions_OptionTargetType_enum_init = { + 64, + 0, + { + 0x3ff, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init = { + 64, + 0, + { + 0xe, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +static const upb_MiniTableEnum *enums_layout[16] = { + &google_protobuf_Edition_enum_init, + &google_protobuf_ExtensionRangeOptions_VerificationState_enum_init, + &google_protobuf_FeatureSet_EnumType_enum_init, + &google_protobuf_FeatureSet_FieldPresence_enum_init, + &google_protobuf_FeatureSet_JsonFormat_enum_init, + &google_protobuf_FeatureSet_MessageEncoding_enum_init, + &google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init, + &google_protobuf_FieldDescriptorProto_Label_enum_init, + &google_protobuf_FieldDescriptorProto_Type_enum_init, + &google_protobuf_FieldOptions_CType_enum_init, + &google_protobuf_FieldOptions_JSType_enum_init, + &google_protobuf_FieldOptions_OptionRetention_enum_init, + &google_protobuf_FieldOptions_OptionTargetType_enum_init, + &google_protobuf_FileOptions_OptimizeMode_enum_init, + &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init, + &google_protobuf_MethodOptions_IdempotencyLevel_enum_init, +}; + +const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { + messages_layout, + enums_layout, + NULL, + 32, + 16, + 0, +}; + +#include "upb/upb/port/undef.inc" + diff --git a/upb/cmake/google/protobuf/descriptor.upb_minitable.h b/upb/cmake/google/protobuf/descriptor.upb_minitable.h new file mode 100644 index 0000000000..9ed12d21ae --- /dev/null +++ b/upb/cmake/google/protobuf/descriptor.upb_minitable.h @@ -0,0 +1,78 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_MINITABLE_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_MINITABLE_H_ + +#include "upb/upb/generated_code_support.h" + +// Must be last. +#include "upb/upb/port/def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const upb_MiniTable google_protobuf_FileDescriptorSet_msg_init; +extern const upb_MiniTable google_protobuf_FileDescriptorProto_msg_init; +extern const upb_MiniTable google_protobuf_DescriptorProto_msg_init; +extern const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msg_init; +extern const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msg_init; +extern const upb_MiniTable google_protobuf_ExtensionRangeOptions_msg_init; +extern const upb_MiniTable google_protobuf_ExtensionRangeOptions_Declaration_msg_init; +extern const upb_MiniTable google_protobuf_FieldDescriptorProto_msg_init; +extern const upb_MiniTable google_protobuf_OneofDescriptorProto_msg_init; +extern const upb_MiniTable google_protobuf_EnumDescriptorProto_msg_init; +extern const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init; +extern const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msg_init; +extern const upb_MiniTable google_protobuf_ServiceDescriptorProto_msg_init; +extern const upb_MiniTable google_protobuf_MethodDescriptorProto_msg_init; +extern const upb_MiniTable google_protobuf_FileOptions_msg_init; +extern const upb_MiniTable google_protobuf_MessageOptions_msg_init; +extern const upb_MiniTable google_protobuf_FieldOptions_msg_init; +extern const upb_MiniTable google_protobuf_FieldOptions_EditionDefault_msg_init; +extern const upb_MiniTable google_protobuf_OneofOptions_msg_init; +extern const upb_MiniTable google_protobuf_EnumOptions_msg_init; +extern const upb_MiniTable google_protobuf_EnumValueOptions_msg_init; +extern const upb_MiniTable google_protobuf_ServiceOptions_msg_init; +extern const upb_MiniTable google_protobuf_MethodOptions_msg_init; +extern const upb_MiniTable google_protobuf_UninterpretedOption_msg_init; +extern const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msg_init; +extern const upb_MiniTable google_protobuf_FeatureSet_msg_init; +extern const upb_MiniTable google_protobuf_FeatureSetDefaults_msg_init; +extern const upb_MiniTable google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_msg_init; +extern const upb_MiniTable google_protobuf_SourceCodeInfo_msg_init; +extern const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msg_init; +extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_msg_init; +extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msg_init; + +extern const upb_MiniTableEnum google_protobuf_Edition_enum_init; +extern const upb_MiniTableEnum google_protobuf_ExtensionRangeOptions_VerificationState_enum_init; +extern const upb_MiniTableEnum google_protobuf_FeatureSet_EnumType_enum_init; +extern const upb_MiniTableEnum google_protobuf_FeatureSet_FieldPresence_enum_init; +extern const upb_MiniTableEnum google_protobuf_FeatureSet_JsonFormat_enum_init; +extern const upb_MiniTableEnum google_protobuf_FeatureSet_MessageEncoding_enum_init; +extern const upb_MiniTableEnum google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init; +extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init; +extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init; +extern const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init; +extern const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init; +extern const upb_MiniTableEnum google_protobuf_FieldOptions_OptionRetention_enum_init; +extern const upb_MiniTableEnum google_protobuf_FieldOptions_OptionTargetType_enum_init; +extern const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init; +extern const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init; +extern const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init; +extern const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/upb/port/undef.inc" + +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_MINITABLE_H_ */