xref: /aosp_15_r20/external/grpc-grpc/third_party/upb/upb/message/internal/accessors.h (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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_MESSAGE_INTERNAL_ACCESSORS_H_
9 #define UPB_MESSAGE_INTERNAL_ACCESSORS_H_
10 
11 #include <stddef.h>
12 #include <stdint.h>
13 #include <string.h>
14 
15 #include "upb/base/internal/endian.h"
16 #include "upb/base/string_view.h"
17 #include "upb/mem/arena.h"
18 #include "upb/message/internal/extension.h"
19 #include "upb/message/internal/map.h"
20 #include "upb/message/internal/message.h"
21 #include "upb/message/internal/tagged_ptr.h"
22 #include "upb/message/internal/types.h"
23 #include "upb/mini_table/extension.h"
24 #include "upb/mini_table/field.h"
25 #include "upb/mini_table/internal/field.h"
26 #include "upb/mini_table/message.h"
27 
28 // Must be last.
29 #include "upb/port/def.inc"
30 
31 #if defined(__GNUC__) && !defined(__clang__)
32 // GCC raises incorrect warnings in these functions.  It thinks that we are
33 // overrunning buffers, but we carefully write the functions in this file to
34 // guarantee that this is impossible.  GCC gets this wrong due it its failure
35 // to perform constant propagation as we expect:
36 //   - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108217
37 //   - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108226
38 //
39 // Unfortunately this also indicates that GCC is not optimizing away the
40 // switch() in cases where it should be, compromising the performance.
41 #pragma GCC diagnostic push
42 #pragma GCC diagnostic ignored "-Warray-bounds"
43 #pragma GCC diagnostic ignored "-Wstringop-overflow"
44 #if __GNUC__ >= 11
45 #pragma GCC diagnostic ignored "-Wstringop-overread"
46 #endif
47 #endif
48 
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52 
53 // LINT.IfChange(presence_logic)
54 
55 // Hasbit access ///////////////////////////////////////////////////////////////
56 
UPB_PRIVATE(_upb_Message_GetHasbit)57 UPB_INLINE bool UPB_PRIVATE(_upb_Message_GetHasbit)(
58     const struct upb_Message* msg, const upb_MiniTableField* f) {
59   const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f);
60   const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f);
61 
62   return (*UPB_PTR_AT(msg, offset, const char) & mask) != 0;
63 }
64 
UPB_PRIVATE(_upb_Message_SetHasbit)65 UPB_INLINE void UPB_PRIVATE(_upb_Message_SetHasbit)(
66     const struct upb_Message* msg, const upb_MiniTableField* f) {
67   const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f);
68   const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f);
69 
70   (*UPB_PTR_AT(msg, offset, char)) |= mask;
71 }
72 
UPB_PRIVATE(_upb_Message_ClearHasbit)73 UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearHasbit)(
74     const struct upb_Message* msg, const upb_MiniTableField* f) {
75   const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f);
76   const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f);
77 
78   (*UPB_PTR_AT(msg, offset, char)) &= ~mask;
79 }
80 
81 // Oneof case access ///////////////////////////////////////////////////////////
82 
UPB_PRIVATE(_upb_Message_OneofCasePtr)83 UPB_INLINE uint32_t* UPB_PRIVATE(_upb_Message_OneofCasePtr)(
84     struct upb_Message* msg, const upb_MiniTableField* f) {
85   return UPB_PTR_AT(msg, UPB_PRIVATE(_upb_MiniTableField_OneofOffset)(f),
86                     uint32_t);
87 }
88 
UPB_PRIVATE(_upb_Message_GetOneofCase)89 UPB_INLINE uint32_t UPB_PRIVATE(_upb_Message_GetOneofCase)(
90     const struct upb_Message* msg, const upb_MiniTableField* f) {
91   const uint32_t* ptr =
92       UPB_PRIVATE(_upb_Message_OneofCasePtr)((struct upb_Message*)msg, f);
93 
94   return *ptr;
95 }
96 
UPB_PRIVATE(_upb_Message_SetOneofCase)97 UPB_INLINE void UPB_PRIVATE(_upb_Message_SetOneofCase)(
98     struct upb_Message* msg, const upb_MiniTableField* f) {
99   uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f);
100 
101   *ptr = upb_MiniTableField_Number(f);
102 }
103 
104 // Returns true if the given field is the current oneof case.
105 // Does nothing if it is not the current oneof case.
UPB_PRIVATE(_upb_Message_ClearOneofCase)106 UPB_INLINE bool UPB_PRIVATE(_upb_Message_ClearOneofCase)(
107     struct upb_Message* msg, const upb_MiniTableField* f) {
108   uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f);
109 
110   if (*ptr != upb_MiniTableField_Number(f)) return false;
111   *ptr = 0;
112   return true;
113 }
114 
115 // LINT.ThenChange(GoogleInternalName2)
116 
117 // Returns false if the message is missing any of its required fields.
UPB_PRIVATE(_upb_Message_IsInitializedShallow)118 UPB_INLINE bool UPB_PRIVATE(_upb_Message_IsInitializedShallow)(
119     const struct upb_Message* msg, const upb_MiniTable* m) {
120   uint64_t bits;
121   memcpy(&bits, msg + 1, sizeof(bits));
122   bits = upb_BigEndian64(bits);
123   return (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~bits) == 0;
124 }
125 
UPB_PRIVATE(_upb_Message_MutableDataPtr)126 UPB_INLINE void* UPB_PRIVATE(_upb_Message_MutableDataPtr)(
127     struct upb_Message* msg, const upb_MiniTableField* f) {
128   return (char*)msg + f->UPB_ONLYBITS(offset);
129 }
130 
UPB_PRIVATE(_upb_Message_DataPtr)131 UPB_INLINE const void* UPB_PRIVATE(_upb_Message_DataPtr)(
132     const struct upb_Message* msg, const upb_MiniTableField* f) {
133   return (const char*)msg + f->UPB_ONLYBITS(offset);
134 }
135 
UPB_PRIVATE(_upb_Message_SetPresence)136 UPB_INLINE void UPB_PRIVATE(_upb_Message_SetPresence)(
137     struct upb_Message* msg, const upb_MiniTableField* f) {
138   if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
139     UPB_PRIVATE(_upb_Message_SetHasbit)(msg, f);
140   } else if (upb_MiniTableField_IsInOneof(f)) {
141     UPB_PRIVATE(_upb_Message_SetOneofCase)(msg, f);
142   }
143 }
144 
UPB_PRIVATE(_upb_MiniTableField_DataCopy)145 UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataCopy)(
146     const upb_MiniTableField* f, void* to, const void* from) {
147   switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) {
148     case kUpb_FieldRep_1Byte:
149       memcpy(to, from, 1);
150       return;
151     case kUpb_FieldRep_4Byte:
152       memcpy(to, from, 4);
153       return;
154     case kUpb_FieldRep_8Byte:
155       memcpy(to, from, 8);
156       return;
157     case kUpb_FieldRep_StringView: {
158       memcpy(to, from, sizeof(upb_StringView));
159       return;
160     }
161   }
162   UPB_UNREACHABLE();
163 }
164 
UPB_PRIVATE(_upb_MiniTableField_DataEquals)165 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataEquals)(
166     const upb_MiniTableField* f, const void* a, const void* b) {
167   switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) {
168     case kUpb_FieldRep_1Byte:
169       return memcmp(a, b, 1) == 0;
170     case kUpb_FieldRep_4Byte:
171       return memcmp(a, b, 4) == 0;
172     case kUpb_FieldRep_8Byte:
173       return memcmp(a, b, 8) == 0;
174     case kUpb_FieldRep_StringView: {
175       const upb_StringView sa = *(const upb_StringView*)a;
176       const upb_StringView sb = *(const upb_StringView*)b;
177       return upb_StringView_IsEqual(sa, sb);
178     }
179   }
180   UPB_UNREACHABLE();
181 }
182 
UPB_PRIVATE(_upb_MiniTableField_DataClear)183 UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataClear)(
184     const upb_MiniTableField* f, void* val) {
185   const char zero[16] = {0};
186   return UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, zero);
187 }
188 
UPB_PRIVATE(_upb_MiniTableField_DataIsZero)189 UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(
190     const upb_MiniTableField* f, const void* val) {
191   const char zero[16] = {0};
192   return UPB_PRIVATE(_upb_MiniTableField_DataEquals)(f, val, zero);
193 }
194 
195 // Here we define universal getter/setter functions for message fields.
196 // These look very branchy and inefficient, but as long as the MiniTableField
197 // values are known at compile time, all the branches are optimized away and
198 // we are left with ideal code.  This can happen either through through
199 // literals or UPB_ASSUME():
200 //
201 //   // Via struct literals.
202 //   bool FooMessage_set_bool_field(const upb_Message* msg, bool val) {
203 //     const upb_MiniTableField field = {1, 0, 0, /* etc... */};
204 //     // All value in "field" are compile-time known.
205 //     _upb_Message_SetNonExtensionField(msg, &field, &value);
206 //   }
207 //
208 //   // Via UPB_ASSUME().
209 //   UPB_INLINE bool upb_Message_SetBool(upb_Message* msg,
210 //                                       const upb_MiniTableField* field,
211 //                                       bool value, upb_Arena* a) {
212 //     UPB_ASSUME(field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bool);
213 //     UPB_ASSUME(upb_MiniTableField_IsScalar(field));
214 //     UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) ==
215 //                kUpb_FieldRep_1Byte);
216 //     upb_Message_SetField(msg, field, &value, a);
217 //   }
218 //
219 // As a result, we can use these universal getters/setters for *all* message
220 // accessors: generated code, MiniTable accessors, and reflection.  The only
221 // exception is the binary encoder/decoder, which need to be a bit more clever
222 // about how they read/write the message data, for efficiency.
223 //
224 // These functions work on both extensions and non-extensions. If the field
225 // of a setter is known to be a non-extension, the arena may be NULL and the
226 // returned bool value may be ignored since it will always succeed.
227 
UPB_PRIVATE(_upb_Message_HasBaseField)228 UPB_INLINE bool UPB_PRIVATE(_upb_Message_HasBaseField)(
229     const struct upb_Message* msg, const upb_MiniTableField* field) {
230   UPB_ASSERT(upb_MiniTableField_HasPresence(field));
231   UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
232   if (upb_MiniTableField_IsInOneof(field)) {
233     return UPB_PRIVATE(_upb_Message_GetOneofCase)(msg, field) ==
234            upb_MiniTableField_Number(field);
235   } else {
236     return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, field);
237   }
238 }
239 
UPB_PRIVATE(_upb_Message_HasExtension)240 UPB_INLINE bool UPB_PRIVATE(_upb_Message_HasExtension)(
241     const struct upb_Message* msg, const upb_MiniTableExtension* ext) {
242   UPB_ASSERT(upb_MiniTableField_HasPresence(&ext->UPB_PRIVATE(field)));
243   return UPB_PRIVATE(_upb_Message_Getext)(msg, ext) != NULL;
244 }
245 
_upb_Message_GetNonExtensionField(const struct upb_Message * msg,const upb_MiniTableField * field,const void * default_val,void * val)246 static UPB_FORCEINLINE void _upb_Message_GetNonExtensionField(
247     const struct upb_Message* msg, const upb_MiniTableField* field,
248     const void* default_val, void* val) {
249   UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
250   if ((upb_MiniTableField_IsInOneof(field) ||
251        !UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(field, default_val)) &&
252       !UPB_PRIVATE(_upb_Message_HasBaseField)(msg, field)) {
253     UPB_PRIVATE(_upb_MiniTableField_DataCopy)(field, val, default_val);
254     return;
255   }
256   UPB_PRIVATE(_upb_MiniTableField_DataCopy)
257   (field, val, UPB_PRIVATE(_upb_Message_DataPtr)(msg, field));
258 }
259 
_upb_Message_GetExtensionField(const struct upb_Message * msg,const upb_MiniTableExtension * mt_ext,const void * default_val,void * val)260 UPB_INLINE void _upb_Message_GetExtensionField(
261     const struct upb_Message* msg, const upb_MiniTableExtension* mt_ext,
262     const void* default_val, void* val) {
263   const struct upb_Extension* ext =
264       UPB_PRIVATE(_upb_Message_Getext)(msg, mt_ext);
265   const upb_MiniTableField* f = &mt_ext->UPB_PRIVATE(field);
266   UPB_ASSUME(upb_MiniTableField_IsExtension(f));
267 
268   if (ext) {
269     UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, &ext->data);
270   } else {
271     UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, default_val);
272   }
273 }
274 
_upb_Message_SetNonExtensionField(struct upb_Message * msg,const upb_MiniTableField * field,const void * val)275 UPB_INLINE void _upb_Message_SetNonExtensionField(
276     struct upb_Message* msg, const upb_MiniTableField* field, const void* val) {
277   UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
278   UPB_PRIVATE(_upb_Message_SetPresence)(msg, field);
279   UPB_PRIVATE(_upb_MiniTableField_DataCopy)
280   (field, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, field), val);
281 }
282 
_upb_Message_SetExtensionField(struct upb_Message * msg,const upb_MiniTableExtension * mt_ext,const void * val,upb_Arena * a)283 UPB_INLINE bool _upb_Message_SetExtensionField(
284     struct upb_Message* msg, const upb_MiniTableExtension* mt_ext,
285     const void* val, upb_Arena* a) {
286   UPB_ASSERT(a);
287   struct upb_Extension* ext =
288       UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(msg, mt_ext, a);
289   if (!ext) return false;
290   UPB_PRIVATE(_upb_MiniTableField_DataCopy)
291   (&mt_ext->UPB_PRIVATE(field), &ext->data, val);
292   return true;
293 }
294 
UPB_PRIVATE(_upb_Message_Clear)295 UPB_INLINE void UPB_PRIVATE(_upb_Message_Clear)(struct upb_Message* msg,
296                                                 const upb_MiniTable* m) {
297   memset(msg, 0, m->UPB_PRIVATE(size));
298 }
299 
UPB_PRIVATE(_upb_Message_ClearBaseField)300 UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearBaseField)(
301     struct upb_Message* msg, const upb_MiniTableField* f) {
302   if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
303     UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, f);
304   } else if (upb_MiniTableField_IsInOneof(f)) {
305     uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f);
306     if (*ptr != upb_MiniTableField_Number(f)) return;
307     *ptr = 0;
308   }
309   const char zeros[16] = {0};
310   UPB_PRIVATE(_upb_MiniTableField_DataCopy)
311   (f, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, f), zeros);
312 }
313 
UPB_PRIVATE(_upb_Message_ClearExtension)314 UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearExtension)(
315     struct upb_Message* msg, const upb_MiniTableExtension* e) {
316   upb_Message_Internal* in = msg->internal;
317   if (!in) return;
318   const struct upb_Extension* base =
319       UPB_PTR_AT(in, in->ext_begin, struct upb_Extension);
320   struct upb_Extension* ext =
321       (struct upb_Extension*)UPB_PRIVATE(_upb_Message_Getext)(msg, e);
322   if (ext) {
323     *ext = *base;
324     in->ext_begin += sizeof(struct upb_Extension);
325   }
326 }
327 
_upb_Message_AssertMapIsUntagged(const struct upb_Message * msg,const upb_MiniTableField * field)328 UPB_INLINE void _upb_Message_AssertMapIsUntagged(
329     const struct upb_Message* msg, const upb_MiniTableField* field) {
330   UPB_UNUSED(msg);
331   UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field);
332 #ifndef NDEBUG
333   uintptr_t default_val = 0;
334   uintptr_t tagged;
335   _upb_Message_GetNonExtensionField(msg, field, &default_val, &tagged);
336   UPB_ASSERT(!UPB_PRIVATE(_upb_TaggedMessagePtr_IsEmpty)(tagged));
337 #endif
338 }
339 
_upb_Message_GetOrCreateMutableMap(struct upb_Message * msg,const upb_MiniTableField * field,size_t key_size,size_t val_size,upb_Arena * arena)340 UPB_INLINE struct upb_Map* _upb_Message_GetOrCreateMutableMap(
341     struct upb_Message* msg, const upb_MiniTableField* field, size_t key_size,
342     size_t val_size, upb_Arena* arena) {
343   UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field);
344   _upb_Message_AssertMapIsUntagged(msg, field);
345   struct upb_Map* map = NULL;
346   struct upb_Map* default_map_value = NULL;
347   _upb_Message_GetNonExtensionField(msg, field, &default_map_value, &map);
348   if (!map) {
349     map = _upb_Map_New(arena, key_size, val_size);
350     // Check again due to: https://godbolt.org/z/7WfaoKG1r
351     UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field);
352     _upb_Message_SetNonExtensionField(msg, field, &map);
353   }
354   return map;
355 }
356 
357 #ifdef __cplusplus
358 } /* extern "C" */
359 #endif
360 
361 #if defined(__GNUC__) && !defined(__clang__)
362 #pragma GCC diagnostic pop
363 #endif
364 
365 #include "upb/port/undef.inc"
366 
367 #endif  // UPB_MESSAGE_INTERNAL_ACCESSORS_H_
368