1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #ifndef UPB_MINI_TABLE_INTERNAL_FIELD_H_
9 #define UPB_MINI_TABLE_INTERNAL_FIELD_H_
10
11 #include <stddef.h>
12 #include <stdint.h>
13
14 #include "upb/base/descriptor_constants.h"
15 #include "upb/mini_table/internal/size_log2.h"
16
17 // Must be last.
18 #include "upb/port/def.inc"
19
20 // LINT.IfChange(struct_definition)
21 struct upb_MiniTableField {
22 uint32_t UPB_ONLYBITS(number);
23 uint16_t UPB_ONLYBITS(offset);
24 int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index
25
26 // Indexes into `upb_MiniTable.subs`
27 // Will be set to `kUpb_NoSub` if `descriptortype` != MESSAGE/GROUP/ENUM
28 uint16_t UPB_PRIVATE(submsg_index);
29
30 uint8_t UPB_PRIVATE(descriptortype);
31
32 // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift)
33 uint8_t UPB_ONLYBITS(mode);
34 };
35
36 #define kUpb_NoSub ((uint16_t)-1)
37
38 typedef enum {
39 kUpb_FieldMode_Map = 0,
40 kUpb_FieldMode_Array = 1,
41 kUpb_FieldMode_Scalar = 2,
42 } upb_FieldMode;
43
44 // Mask to isolate the upb_FieldMode from field.mode.
45 #define kUpb_FieldMode_Mask 3
46
47 // Extra flags on the mode field.
48 typedef enum {
49 kUpb_LabelFlags_IsPacked = 4,
50 kUpb_LabelFlags_IsExtension = 8,
51 // Indicates that this descriptor type is an "alternate type":
52 // - for Int32, this indicates that the actual type is Enum (but was
53 // rewritten to Int32 because it is an open enum that requires no check).
54 // - for Bytes, this indicates that the actual type is String (but does
55 // not require any UTF-8 check).
56 kUpb_LabelFlags_IsAlternate = 16,
57 } upb_LabelFlags;
58
59 // Note: we sort by this number when calculating layout order.
60 typedef enum {
61 kUpb_FieldRep_1Byte = 0,
62 kUpb_FieldRep_4Byte = 1,
63 kUpb_FieldRep_StringView = 2,
64 kUpb_FieldRep_8Byte = 3,
65
66 kUpb_FieldRep_NativePointer =
67 UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte),
68 kUpb_FieldRep_Max = kUpb_FieldRep_8Byte,
69 } upb_FieldRep;
70
71 #define kUpb_FieldRep_Shift 6
72
73 #ifdef __cplusplus
74 extern "C" {
75 #endif
76
77 UPB_INLINE upb_FieldMode
UPB_PRIVATE(_upb_MiniTableField_Mode)78 UPB_PRIVATE(_upb_MiniTableField_Mode)(const struct upb_MiniTableField* f) {
79 return (upb_FieldMode)(f->UPB_ONLYBITS(mode) & kUpb_FieldMode_Mask);
80 }
81
82 UPB_INLINE upb_FieldRep
UPB_PRIVATE(_upb_MiniTableField_GetRep)83 UPB_PRIVATE(_upb_MiniTableField_GetRep)(const struct upb_MiniTableField* f) {
84 return (upb_FieldRep)(f->UPB_ONLYBITS(mode) >> kUpb_FieldRep_Shift);
85 }
86
UPB_PRIVATE(_upb_MiniTableField_IsArray)87 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsArray)(
88 const struct upb_MiniTableField* f) {
89 return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Array;
90 }
91
UPB_PRIVATE(_upb_MiniTableField_IsMap)92 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsMap)(
93 const struct upb_MiniTableField* f) {
94 return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Map;
95 }
96
UPB_PRIVATE(_upb_MiniTableField_IsScalar)97 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsScalar)(
98 const struct upb_MiniTableField* f) {
99 return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Scalar;
100 }
101
UPB_PRIVATE(_upb_MiniTableField_IsAlternate)102 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsAlternate)(
103 const struct upb_MiniTableField* f) {
104 return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsAlternate) != 0;
105 }
106
UPB_PRIVATE(_upb_MiniTableField_IsExtension)107 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsExtension)(
108 const struct upb_MiniTableField* f) {
109 return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsExtension) != 0;
110 }
111
UPB_PRIVATE(_upb_MiniTableField_IsPacked)112 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsPacked)(
113 const struct upb_MiniTableField* f) {
114 return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsPacked) != 0;
115 }
116
117 UPB_INLINE upb_FieldType
UPB_PRIVATE(_upb_MiniTableField_Type)118 UPB_PRIVATE(_upb_MiniTableField_Type)(const struct upb_MiniTableField* f) {
119 const upb_FieldType type = (upb_FieldType)f->UPB_PRIVATE(descriptortype);
120 if (UPB_PRIVATE(_upb_MiniTableField_IsAlternate)(f)) {
121 if (type == kUpb_FieldType_Int32) return kUpb_FieldType_Enum;
122 if (type == kUpb_FieldType_Bytes) return kUpb_FieldType_String;
123 UPB_ASSERT(false);
124 }
125 return type;
126 }
127
128 UPB_INLINE upb_CType
UPB_PRIVATE(_upb_MiniTableField_CType)129 UPB_PRIVATE(_upb_MiniTableField_CType)(const struct upb_MiniTableField* f) {
130 return upb_FieldType_CType(UPB_PRIVATE(_upb_MiniTableField_Type)(f));
131 }
132
UPB_PRIVATE(_upb_MiniTableField_HasHasbit)133 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(
134 const struct upb_MiniTableField* f) {
135 return f->presence > 0;
136 }
137
UPB_PRIVATE(_upb_MiniTableField_HasbitMask)138 UPB_INLINE char UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(
139 const struct upb_MiniTableField* f) {
140 UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f));
141 const size_t index = f->presence;
142 return 1 << (index % 8);
143 }
144
UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)145 UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(
146 const struct upb_MiniTableField* f) {
147 UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f));
148 const size_t index = f->presence;
149 return index / 8;
150 }
151
UPB_PRIVATE(_upb_MiniTableField_IsClosedEnum)152 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsClosedEnum)(
153 const struct upb_MiniTableField* f) {
154 return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum;
155 }
156
UPB_PRIVATE(_upb_MiniTableField_IsInOneof)157 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsInOneof)(
158 const struct upb_MiniTableField* f) {
159 return f->presence < 0;
160 }
161
UPB_PRIVATE(_upb_MiniTableField_IsSubMessage)162 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsSubMessage)(
163 const struct upb_MiniTableField* f) {
164 return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message ||
165 f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group;
166 }
167
UPB_PRIVATE(_upb_MiniTableField_HasPresence)168 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_HasPresence)(
169 const struct upb_MiniTableField* f) {
170 if (UPB_PRIVATE(_upb_MiniTableField_IsExtension)(f)) {
171 return UPB_PRIVATE(_upb_MiniTableField_IsScalar)(f);
172 } else {
173 return f->presence != 0;
174 }
175 }
176
177 UPB_INLINE uint32_t
UPB_PRIVATE(_upb_MiniTableField_Number)178 UPB_PRIVATE(_upb_MiniTableField_Number)(const struct upb_MiniTableField* f) {
179 return f->UPB_ONLYBITS(number);
180 }
181
182 UPB_INLINE uint16_t
UPB_PRIVATE(_upb_MiniTableField_Offset)183 UPB_PRIVATE(_upb_MiniTableField_Offset)(const struct upb_MiniTableField* f) {
184 return f->UPB_ONLYBITS(offset);
185 }
186
UPB_PRIVATE(_upb_MiniTableField_OneofOffset)187 UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_OneofOffset)(
188 const struct upb_MiniTableField* f) {
189 UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_IsInOneof)(f));
190 return ~(ptrdiff_t)f->presence;
191 }
192
UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)193 UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(
194 const struct upb_MiniTableField* f) {
195 UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) ==
196 kUpb_FieldRep_NativePointer);
197 UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_IsArray)(f));
198 UPB_ASSUME(f->presence == 0);
199 }
200
UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)201 UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(
202 const struct upb_MiniTableField* f) {
203 UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) ==
204 kUpb_FieldRep_NativePointer);
205 UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_IsMap)(f));
206 UPB_ASSUME(f->presence == 0);
207 }
208
UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)209 UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)(
210 const struct upb_MiniTableField* f) {
211 const upb_FieldType field_type = UPB_PRIVATE(_upb_MiniTableField_Type)(f);
212 return UPB_PRIVATE(_upb_FieldType_SizeLg2)(field_type);
213 }
214
215 // LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/mini_table_field.ts)
216
217 #ifdef __cplusplus
218 } /* extern "C" */
219 #endif
220
221 #include "upb/port/undef.inc"
222
223 #endif /* UPB_MINI_TABLE_INTERNAL_FIELD_H_ */
224