blob: 1008be67bffce2274dd282f8402e040d28160056 [file] [log] [blame]
// 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
#include "upb/wire/test_util/make_mini_table.h"
#include <string>
#include <utility>
#include "absl/log/absl_check.h"
#include "absl/log/log.h"
#include "upb/base/status.hpp"
#include "upb/mem/arena.h"
#include "upb/mini_descriptor/decode.h"
#include "upb/mini_descriptor/internal/encode.hpp"
#include "upb/mini_descriptor/internal/modifiers.h"
#include "upb/mini_table/field.h"
#include "upb/mini_table/message.h"
#include "upb/wire/decode_fast/combinations.h"
#include "upb/wire/decode_fast/data.h"
#include "upb/wire/reader.h"
// Must be last.
#include "upb/port/def.inc"
namespace upb {
namespace test {
int FieldModifiers(upb_DecodeFast_Type type,
upb_DecodeFast_Cardinality cardinality) {
int modifiers = 0;
switch (type) {
case kUpb_DecodeFast_String:
modifiers |= kUpb_FieldModifier_ValidateUtf8;
break;
default:
break;
}
switch (cardinality) {
case kUpb_DecodeFast_Repeated:
modifiers |= kUpb_FieldModifier_IsRepeated;
break;
case kUpb_DecodeFast_Packed:
modifiers |= kUpb_FieldModifier_IsRepeated | kUpb_FieldModifier_IsPacked;
break;
default:
return 0;
}
return modifiers;
}
std::pair<const upb_MiniTable*, const upb_MiniTableField*>
MiniTable::MakeSingleFieldTable(int field_number, upb_FieldType type,
upb_DecodeFast_Type fast_type,
upb_DecodeFast_Cardinality cardinality,
upb_Arena* arena) {
MtDataEncoder encoder;
encoder.StartMessage(0);
encoder.PutField(type, 1, FieldModifiers(fast_type, cardinality));
if (cardinality == kUpb_DecodeFast_Oneof) {
encoder.StartOneof();
encoder.PutOneofField(field_number);
}
const std::string& data = encoder.data();
upb::Status status;
const upb_MiniTable* table =
upb_MiniTable_Build(data.data(), data.size(), arena, status.ptr());
ABSL_CHECK(status.ok()) << status.error_message();
const upb_MiniTableField* field = upb_MiniTable_GetFieldByIndex(table, 0);
ABSL_CHECK(field != nullptr);
#if UPB_FASTTABLE
if (field_number < (1 << 11)) {
ABSL_CHECK_EQ(HasFastTableEntry(table, field),
UPB_DECODEFAST_ISENABLED(fast_type, cardinality,
kUpb_DecodeFast_Tag1Byte))
<< "fast type: " << fast_type << ", cardinality: " << cardinality;
}
#endif
return std::make_pair(table, upb_MiniTable_GetFieldByIndex(table, 0));
}
bool MiniTable::HasFastTableEntry(const upb_MiniTable* mt,
const upb_MiniTableField* field) {
#if UPB_FASTTABLE
int n = (int8_t)mt->UPB_PRIVATE(table_mask) + 1;
for (int i = 0; i < n; ++i) {
const _upb_FastTable_Entry* entry = &mt->UPB_PRIVATE(fasttable)[i];
uint16_t encoded_tag = upb_DecodeFastData_GetExpectedTag(entry->field_data);
uint32_t tag;
char buf[16];
memset(buf, 0, sizeof(buf));
memcpy(buf, &encoded_tag, sizeof(encoded_tag));
const char* end = upb_WireReader_ReadTag(buf, &tag, nullptr);
ABSL_CHECK(end == buf + 1 || end == buf + 2);
if (tag >> 3 == field->UPB_PRIVATE(number)) {
return true;
}
}
return false;
#else
return false;
#endif
}
} // namespace test
} // namespace upb