| // Protocol Buffers - Google's data interchange format |
| // Copyright 2025 Google LLC. All rights reserved. |
| // |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file or at |
| // https://developers.google.com/open-source/licenses/bsd |
| |
| #ifndef UPB_WIRE_DECODE_FAST_FIELD_DISPATCH_H_ |
| #define UPB_WIRE_DECODE_FAST_FIELD_DISPATCH_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include "upb/message/message.h" |
| #include "upb/mini_table/internal/message.h" |
| #include "upb/mini_table/message.h" |
| #include "upb/wire/decode_fast/data.h" |
| #include "upb/wire/internal/decoder.h" |
| #include "upb/wire/internal/eps_copy_input_stream.h" |
| |
| // Must be last. |
| #include "upb/port/def.inc" |
| |
| typedef struct upb_FastDecoder_Return { |
| const char* ptr; |
| } upb_FastDecoder_Return; |
| |
| // The standard set of arguments passed to each parsing function. |
| // Thanks to x86-64 calling conventions, these will stay in registers. |
| #define UPB_PARSE_PARAMS \ |
| upb_Decoder *d, const char *ptr, upb_Message *msg, \ |
| const upb_MiniTable *table, uint64_t hasbits, uint64_t data, \ |
| uint64_t data2 |
| |
| #define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data, data2 |
| |
| UPB_INLINE uint32_t _upb_FastDecoder_LoadTag(const char* ptr) { |
| uint16_t tag; |
| memcpy(&tag, ptr, 2); |
| return tag; |
| } |
| |
| UPB_INLINE UPB_PRESERVE_NONE upb_FastDecoder_Return |
| _upb_FastDecoder_TagDispatch(struct upb_Decoder* d, const char* ptr, |
| upb_Message* msg, const upb_MiniTable* table, |
| uint64_t hasbits, uint64_t data, uint64_t data2) { |
| uint8_t mask = upb_DecodeFastData2_GetMask(data2); |
| size_t ofs = data2 & mask; |
| UPB_ASSUME((ofs & 0xf8) == ofs); |
| |
| #if UPB_FASTTABLE |
| const _upb_FastTable_Entry* ent = &table->UPB_PRIVATE(fasttable)[ofs >> 3]; |
| #else |
| // Unreachable, since this header is only used from C, but when the header |
| // module is compiled for C++ we need to avoid a compilation error. |
| UPB_UNREACHABLE(); |
| _upb_FastTable_Entry* ent = NULL; |
| #endif |
| |
| UPB_MUSTTAIL return ent->field_parser(d, ptr, msg, table, hasbits, |
| ent->field_data, data2); |
| } |
| |
| UPB_NOINLINE UPB_PRESERVE_NONE upb_FastDecoder_Return |
| upb_DecodeFast_MessageIsDoneFallback(UPB_PARSE_PARAMS); |
| |
| UPB_FORCEINLINE UPB_PRESERVE_NONE upb_FastDecoder_Return |
| upb_DecodeFast_Dispatch(UPB_PARSE_PARAMS) { |
| int overrun; |
| upb_IsDoneStatus status = UPB_PRIVATE(upb_EpsCopyInputStream_IsDoneStatus)( |
| &d->input, ptr, &overrun); |
| |
| if (UPB_UNLIKELY(status != kUpb_IsDoneStatus_NotDone)) { |
| // End-of-message or end-of-buffer. |
| UPB_MUSTTAIL return upb_DecodeFast_MessageIsDoneFallback(UPB_PARSE_ARGS); |
| } |
| |
| // Read two bytes of tag data (for a one-byte tag, the high byte is junk). |
| uint16_t tag = _upb_FastDecoder_LoadTag(ptr); |
| data2 = upb_DecodeFastData2_PackOriginalTag(data2, tag); |
| _upb_Decoder_Trace(d, 'D'); |
| UPB_MUSTTAIL return _upb_FastDecoder_TagDispatch(d, ptr, msg, table, hasbits, |
| data, data2); |
| } |
| |
| UPB_FORCEINLINE |
| void upb_DecodeFast_SetHasbits(upb_Message* msg, uint64_t hasbits) { |
| // TODO: Can we use `=` instead of` |=`? |
| *(uint32_t*)&msg[1] |= hasbits; |
| } |
| |
| #include "upb/port/undef.inc" |
| |
| #endif // UPB_WIRE_DECODE_FAST_FIELD_DISPATCH_H_ |