// Protocol Buffers - Google's data interchange format // Copyright 2023 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_INTERNAL_ENCODE_H_ #define UPB_WIRE_INTERNAL_ENCODE_H_ #include #include #include #include "upb/mem/arena.h" #include "upb/message/array.h" #include "upb/message/internal/map_sorter.h" #include "upb/message/internal/message.h" #include "upb/message/message.h" #include "upb/mini_table/extension.h" #include "upb/mini_table/field.h" #include "upb/mini_table/message.h" #include "upb/wire/encode.h" #include "upb/wire/internal/back_alloc.h" #include "upb/wire/types.h" // Must be last. #include "upb/port/def.inc" #ifdef __cplusplus extern "C" { #endif typedef struct { upb_BackAlloc alloc; int options; int depth; upb_EncodeStatus status; _upb_mapsorter sorter; jmp_buf* err; } upb_encstate; UPB_INLINE char* UPB_PRIVATE(_upb_encstate_init)(upb_encstate* e, jmp_buf* err, upb_Arena* arena) { e->status = kUpb_EncodeStatus_Ok; char* ptr = upb_BackAlloc_Init(&e->alloc, arena); e->options = 0; e->depth = 0; e->err = err; _upb_mapsorter_init(&e->sorter); return ptr; } UPB_INLINE void UPB_PRIVATE(_upb_encstate_destroy)(upb_encstate* e) { _upb_mapsorter_destroy(&e->sorter); } // Internal version of upb_Encode that encodes a single field. // // The caller must clean up the `upb_encstate` by calling // `_upb_encstate_destroy(e)` when done. upb_EncodeStatus UPB_PRIVATE(_upb_Encode_Field)(upb_encstate* e, const upb_Message* msg, const upb_MiniTableField* field, char** buf, size_t* size, int options); // Internal version of upb_Encode that encodes a single extension. // // The caller must clean up the `upb_encstate` by calling // `_upb_encstate_destroy(e)` when done. upb_EncodeStatus UPB_PRIVATE(_upb_Encode_Extension)( upb_encstate* e, const upb_MiniTableExtension* ext, upb_MessageValue ext_val, bool is_message_set, char** buf, size_t* size, int options); char* encode_message(char* ptr, upb_encstate* e, const upb_Message* msg, const upb_MiniTable* m, size_t* size); #define kUpb_Encoder_EncodeVarint32MaxSize 5 #define kUpb_Encoder_EncodeVarint64MaxSize 10 static char* upb_Encoder_EncodeVarint32(uint32_t val, char* ptr) { do { uint8_t byte = val & 0x7fU; val >>= 7; if (val) byte |= 0x80U; *(ptr++) = byte; } while (val); return ptr; } static char* upb_Encoder_EncodeVarint64(uint64_t val, char* ptr) { do { uint8_t byte = val & 0x7fU; val >>= 7; if (val) byte |= 0x80U; *(ptr++) = byte; } while (val); return ptr; } UPB_INLINE bool _upb_Encoder_AddEnumValueToUnknown(upb_Message* msg, const upb_MiniTableField* field, uint64_t val, upb_Arena* arena) { // Unrecognized enum goes into unknown fields. // For packed fields the tag could be arbitrarily far in the past, // so we just re-encode the tag and value here. const uint32_t tag = ((uint32_t)field->UPB_PRIVATE(number) << 3) | kUpb_WireType_Varint; char buf[kUpb_Encoder_EncodeVarint32MaxSize + kUpb_Encoder_EncodeVarint64MaxSize]; char* end = buf; end = upb_Encoder_EncodeVarint32(tag, end); end = upb_Encoder_EncodeVarint64(val, end); return UPB_PRIVATE(_upb_Message_AddUnknown)(msg, buf, end - buf, arena, kUpb_AddUnknown_Copy); } bool _upb_Encoder_AddMapEntryUnknown(upb_Message* msg, const upb_MiniTableField* field, upb_Message* ent_msg, const upb_MiniTable* entry, upb_Arena* arena); upb_EncodeStatus _upb_Encode(const upb_Message* msg, const upb_MiniTable* l, int options, upb_Arena* arena, char** buf, size_t* size, bool prepend_len); #ifdef __cplusplus } /* extern "C" */ #endif #include "upb/port/undef.inc" #endif /* UPB_WIRE_INTERNAL_ENCODE_H_ */