Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
5.8 KiB
180 lines
5.8 KiB
5 months ago
|
// Protocol Buffers - Google's data interchange format
|
||
|
// Copyright 2024 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
|
||
|
|
||
|
#include "upb/text/internal/encode.h"
|
||
|
|
||
|
#include <inttypes.h>
|
||
|
#include <stddef.h>
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#include "upb/base/descriptor_constants.h"
|
||
|
#include "upb/base/string_view.h"
|
||
|
#include "upb/lex/round_trip.h"
|
||
|
#include "upb/message/array.h"
|
||
|
#include "upb/wire/eps_copy_input_stream.h"
|
||
|
#include "upb/wire/reader.h"
|
||
|
#include "upb/wire/types.h"
|
||
|
|
||
|
// Must be last.
|
||
|
#include "upb/port/def.inc"
|
||
|
|
||
|
#define CHK(x) \
|
||
|
do { \
|
||
|
if (!(x)) { \
|
||
|
return false; \
|
||
|
} \
|
||
|
} while (0)
|
||
|
|
||
|
/*
|
||
|
* Unknown fields are printed by number.
|
||
|
*
|
||
|
* 1001: 123
|
||
|
* 1002: "hello"
|
||
|
* 1006: 0xdeadbeef
|
||
|
* 1003: {
|
||
|
* 1: 111
|
||
|
* }
|
||
|
*/
|
||
|
const char* UPB_PRIVATE(_upb_TextEncode_Unknown)(txtenc* e, const char* ptr,
|
||
|
upb_EpsCopyInputStream* stream,
|
||
|
int groupnum) {
|
||
|
// We are guaranteed that the unknown data is valid wire format, and will not
|
||
|
// contain tag zero.
|
||
|
uint32_t end_group = groupnum > 0
|
||
|
? ((groupnum << kUpb_WireReader_WireTypeBits) |
|
||
|
kUpb_WireType_EndGroup)
|
||
|
: 0;
|
||
|
|
||
|
while (!upb_EpsCopyInputStream_IsDone(stream, &ptr)) {
|
||
|
uint32_t tag;
|
||
|
CHK(ptr = upb_WireReader_ReadTag(ptr, &tag));
|
||
|
if (tag == end_group) return ptr;
|
||
|
|
||
|
UPB_PRIVATE(_upb_TextEncode_Indent)(e);
|
||
|
UPB_PRIVATE(_upb_TextEncode_Printf)
|
||
|
(e, "%d: ", (int)upb_WireReader_GetFieldNumber(tag));
|
||
|
|
||
|
switch (upb_WireReader_GetWireType(tag)) {
|
||
|
case kUpb_WireType_Varint: {
|
||
|
uint64_t val;
|
||
|
CHK(ptr = upb_WireReader_ReadVarint(ptr, &val));
|
||
|
UPB_PRIVATE(_upb_TextEncode_Printf)(e, "%" PRIu64, val);
|
||
|
break;
|
||
|
}
|
||
|
case kUpb_WireType_32Bit: {
|
||
|
uint32_t val;
|
||
|
ptr = upb_WireReader_ReadFixed32(ptr, &val);
|
||
|
UPB_PRIVATE(_upb_TextEncode_Printf)(e, "0x%08" PRIu32, val);
|
||
|
break;
|
||
|
}
|
||
|
case kUpb_WireType_64Bit: {
|
||
|
uint64_t val;
|
||
|
ptr = upb_WireReader_ReadFixed64(ptr, &val);
|
||
|
UPB_PRIVATE(_upb_TextEncode_Printf)(e, "0x%016" PRIu64, val);
|
||
|
break;
|
||
|
}
|
||
|
case kUpb_WireType_Delimited: {
|
||
|
int size;
|
||
|
char* start = e->ptr;
|
||
|
size_t start_overflow = e->overflow;
|
||
|
CHK(ptr = upb_WireReader_ReadSize(ptr, &size));
|
||
|
CHK(upb_EpsCopyInputStream_CheckDataSizeAvailable(stream, ptr, size));
|
||
|
|
||
|
// Speculatively try to parse as message.
|
||
|
UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "{");
|
||
|
UPB_PRIVATE(_upb_TextEncode_EndField)(e);
|
||
|
|
||
|
// EpsCopyInputStream can't back up, so create a sub-stream for the
|
||
|
// speculative parse.
|
||
|
upb_EpsCopyInputStream sub_stream;
|
||
|
const char* sub_ptr = upb_EpsCopyInputStream_GetAliasedPtr(stream, ptr);
|
||
|
upb_EpsCopyInputStream_Init(&sub_stream, &sub_ptr, size, true);
|
||
|
|
||
|
e->indent_depth++;
|
||
|
if (UPB_PRIVATE(_upb_TextEncode_Unknown)(e, sub_ptr, &sub_stream, -1)) {
|
||
|
ptr = upb_EpsCopyInputStream_Skip(stream, ptr, size);
|
||
|
e->indent_depth--;
|
||
|
UPB_PRIVATE(_upb_TextEncode_Indent)(e);
|
||
|
UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "}");
|
||
|
} else {
|
||
|
// Didn't work out, print as raw bytes.
|
||
|
e->indent_depth--;
|
||
|
e->ptr = start;
|
||
|
e->overflow = start_overflow;
|
||
|
const char* str = ptr;
|
||
|
ptr = upb_EpsCopyInputStream_ReadString(stream, &str, size, NULL);
|
||
|
UPB_ASSERT(ptr);
|
||
|
UPB_PRIVATE(_upb_TextEncode_Bytes)
|
||
|
(e, (upb_StringView){.data = str, .size = size});
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case kUpb_WireType_StartGroup:
|
||
|
UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "{");
|
||
|
UPB_PRIVATE(_upb_TextEncode_EndField)(e);
|
||
|
e->indent_depth++;
|
||
|
CHK(ptr = UPB_PRIVATE(_upb_TextEncode_Unknown)(
|
||
|
e, ptr, stream, upb_WireReader_GetFieldNumber(tag)));
|
||
|
e->indent_depth--;
|
||
|
UPB_PRIVATE(_upb_TextEncode_Indent)(e);
|
||
|
UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "}");
|
||
|
break;
|
||
|
default:
|
||
|
return NULL;
|
||
|
}
|
||
|
UPB_PRIVATE(_upb_TextEncode_EndField)(e);
|
||
|
}
|
||
|
|
||
|
return end_group == 0 && !upb_EpsCopyInputStream_IsError(stream) ? ptr : NULL;
|
||
|
}
|
||
|
|
||
|
#undef CHK
|
||
|
|
||
|
void UPB_PRIVATE(_upb_TextEncode_Scalar)(txtenc* e, upb_MessageValue val,
|
||
|
upb_CType ctype) {
|
||
|
switch (ctype) {
|
||
|
case kUpb_CType_Bool:
|
||
|
UPB_PRIVATE(_upb_TextEncode_PutStr)(e, val.bool_val ? "true" : "false");
|
||
|
break;
|
||
|
case kUpb_CType_Float: {
|
||
|
char buf[32];
|
||
|
_upb_EncodeRoundTripFloat(val.float_val, buf, sizeof(buf));
|
||
|
UPB_PRIVATE(_upb_TextEncode_PutStr)(e, buf);
|
||
|
break;
|
||
|
}
|
||
|
case kUpb_CType_Double: {
|
||
|
char buf[32];
|
||
|
_upb_EncodeRoundTripDouble(val.double_val, buf, sizeof(buf));
|
||
|
UPB_PRIVATE(_upb_TextEncode_PutStr)(e, buf);
|
||
|
break;
|
||
|
}
|
||
|
case kUpb_CType_Int32:
|
||
|
UPB_PRIVATE(_upb_TextEncode_Printf)(e, "%" PRId32, val.int32_val);
|
||
|
break;
|
||
|
case kUpb_CType_UInt32:
|
||
|
UPB_PRIVATE(_upb_TextEncode_Printf)(e, "%" PRIu32, val.uint32_val);
|
||
|
break;
|
||
|
case kUpb_CType_Int64:
|
||
|
UPB_PRIVATE(_upb_TextEncode_Printf)(e, "%" PRId64, val.int64_val);
|
||
|
break;
|
||
|
case kUpb_CType_UInt64:
|
||
|
UPB_PRIVATE(_upb_TextEncode_Printf)(e, "%" PRIu64, val.uint64_val);
|
||
|
break;
|
||
|
case kUpb_CType_String:
|
||
|
UPB_PRIVATE(_upb_HardenedPrintString)
|
||
|
(e, val.str_val.data, val.str_val.size);
|
||
|
break;
|
||
|
case kUpb_CType_Bytes:
|
||
|
UPB_PRIVATE(_upb_TextEncode_Bytes)(e, val.str_val);
|
||
|
break;
|
||
|
case kUpb_CType_Enum:
|
||
|
UPB_ASSERT(false); // handled separately in each encoder
|
||
|
break;
|
||
|
default:
|
||
|
UPB_UNREACHABLE();
|
||
|
}
|
||
|
}
|