Files
tensorflow--tensorflow/tensorflow/tools/proto_splitter/cc/util.cc
T
wehub-resource-sync 8a852e4b4e
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s
chore: import upstream snapshot with attribution
2026-07-13 12:14:16 +08:00

806 lines
30 KiB
C++

/* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/tools/proto_splitter/cc/util.h"
#include <cstdint>
#include <functional>
#include <ios>
#include <optional>
#include <sstream>
#include <string>
#include <utility>
#include <variant>
#include <vector>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "riegeli/base/maker.h" // from @riegeli
#include "riegeli/base/types.h" // from @riegeli
#include "riegeli/bytes/fd_reader.h" // from @riegeli
#include "riegeli/bytes/string_reader.h" // from @riegeli
#include "riegeli/records/record_reader.h" // from @riegeli
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/file_system_helper.h"
#include "tensorflow/tools/proto_splitter/chunk.pb.h"
#include "tsl/platform/errors.h"
#include "tsl/platform/protobuf.h"
#include "tsl/platform/statusor.h"
namespace tensorflow {
namespace tools::proto_splitter {
using ::tensorflow::proto_splitter::ChunkedField;
namespace {
absl::StatusOr<int> FieldInt(const FieldType& field) {
switch (field.index()) {
case 0: { // std::string
int value;
if (absl::SimpleAtoi(std::get<std::string>(field), &value)) return value;
return absl::InvalidArgumentError(absl::StrCat(
"Unable to convert '", std::get<std::string>(field), "' to int."));
break;
}
case 1: // int
return std::get<int>(field);
case 2: // bool
return std::get<bool>(field) ? 1 : 0;
default:
// This should not happen.
return absl::InvalidArgumentError("Invalid field type.");
}
}
absl::StatusOr<bool> FieldBool(const FieldType& field) {
switch (field.index()) {
case 0: { // std::string
std::string s = std::get<std::string>(field);
if (s == "true") return true;
if (s == "false") return false;
return absl::InvalidArgumentError("Unable to convert '" + s +
"' to bool.");
}
case 1: // int
return std::get<int>(field) != 0;
case 2: // bool
return std::get<bool>(field);
default:
// This should not happen.
return absl::InvalidArgumentError("Invalid field type.");
}
}
std::string FieldString(const FieldType& field) {
switch (field.index()) {
case 0: // std::string
return std::get<std::string>(field);
case 1: // int
return std::to_string(std::get<int>(field));
case 2: // bool
return std::get<bool>(field) ? "true" : "false";
default:
// This should not happen.
CHECK(false) << "Invalid field type: " << field.index(); // Crash OK.
return "";
}
}
template <typename FieldCallback, typename MapKeyCallback,
typename ListIndexCallback>
absl::Status WalkFields(const tsl::protobuf::Descriptor& desc,
const std::vector<FieldType>& fields,
FieldCallback field_callback,
MapKeyCallback map_key_callback,
ListIndexCallback list_index_callback) {
const tsl::protobuf::Descriptor* message_desc = &desc;
std::vector<FieldType>::const_iterator it = fields.begin();
while (it != fields.end()) {
const tsl::protobuf::FieldDescriptor* field_desc;
if (std::holds_alternative<std::string>(*it)) {
field_desc = message_desc->FindFieldByName(std::get<std::string>(*it));
} else if (std::holds_alternative<int>(*it)) {
field_desc = message_desc->FindFieldByNumber(std::get<int>(*it));
} else {
return absl::InvalidArgumentError(absl::StrCat(
"Invalid field, expected int or str: ", FieldString(*it)));
}
if (field_desc == nullptr) {
return absl::NotFoundError(
absl::StrCat("Field not found: ", FieldString(*it)));
}
TF_RETURN_IF_ERROR(field_callback(field_desc));
message_desc = field_desc->message_type();
it++;
// Handle special field types (map key and list index).
if (it != fields.end()) {
if (field_desc->is_map()) {
auto key_field = message_desc->FindFieldByNumber(1);
auto status = map_key_callback(*key_field, *it);
if (!status.ok()) {
return status;
}
// The next element in `fields` must be a field in the value message.
message_desc = message_desc->FindFieldByName("value")->message_type();
it++;
} else if (field_desc->is_repeated()) {
auto status = list_index_callback(*it);
if (!status.ok()) {
return status;
}
it++;
}
}
}
return absl::OkStatus();
}
absl::Status AddMapKey(const tsl::protobuf::FieldDescriptor& key_field,
const FieldType& map_key, ChunkedField& chunked_field) {
auto msg = chunked_field.add_field_tag()->mutable_map_key();
switch (key_field.type()) {
case tsl::protobuf::FieldDescriptor::TYPE_BOOL: {
TF_ASSIGN_OR_RETURN(auto key, FieldBool(map_key));
msg->set_boolean(key);
break;
}
case tsl::protobuf::FieldDescriptor::TYPE_STRING: {
msg->set_s(FieldString(map_key));
break;
}
case tsl::protobuf::FieldDescriptor::TYPE_INT32: {
TF_ASSIGN_OR_RETURN(auto key, FieldInt(map_key));
msg->set_i32(key);
break;
}
case tsl::protobuf::FieldDescriptor::TYPE_INT64: {
TF_ASSIGN_OR_RETURN(auto key, FieldInt(map_key));
msg->set_i64(key);
break;
}
case tsl::protobuf::FieldDescriptor::TYPE_UINT32: {
TF_ASSIGN_OR_RETURN(auto key, FieldInt(map_key));
msg->set_ui32(key);
break;
}
case tsl::protobuf::FieldDescriptor::TYPE_UINT64: {
TF_ASSIGN_OR_RETURN(auto key, FieldInt(map_key));
msg->set_ui64(key);
break;
}
case tsl::protobuf::FieldDescriptor::TYPE_FIXED64:
case tsl::protobuf::FieldDescriptor::TYPE_FIXED32:
case tsl::protobuf::FieldDescriptor::TYPE_SINT32:
case tsl::protobuf::FieldDescriptor::TYPE_SINT64:
case tsl::protobuf::FieldDescriptor::TYPE_SFIXED32:
case tsl::protobuf::FieldDescriptor::TYPE_SFIXED64:
return absl::UnimplementedError(
"Fixed map key types not implemented yet.");
case tsl::protobuf::FieldDescriptor::TYPE_DOUBLE:
case tsl::protobuf::FieldDescriptor::TYPE_FLOAT:
case tsl::protobuf::FieldDescriptor::TYPE_ENUM:
case tsl::protobuf::FieldDescriptor::TYPE_BYTES:
case tsl::protobuf::FieldDescriptor::TYPE_MESSAGE:
case tsl::protobuf::FieldDescriptor::TYPE_GROUP:
return absl::FailedPreconditionError(absl::StrCat(
"Encountered type that is not supported for MapKey.type: ",
key_field.type()));
default:
return absl::FailedPreconditionError("Proto field type not recognized.");
}
return absl::OkStatus();
}
absl::StatusOr<FieldType> GetMapKeyFromFieldIndex(
::tensorflow::proto_splitter::FieldIndex field_index) {
if (!field_index.has_map_key())
return absl::FailedPreconditionError(
"Field index doesn't contain a map key.");
switch (field_index.map_key().type_case()) {
case ::tensorflow::proto_splitter::FieldIndex::MapKey::TypeCase::kBoolean:
return field_index.map_key().boolean();
break;
case ::tensorflow::proto_splitter::FieldIndex::MapKey::TypeCase::kS:
return field_index.map_key().s();
break;
case ::tensorflow::proto_splitter::FieldIndex::MapKey::TypeCase::kI32:
return field_index.map_key().i32();
break;
case ::tensorflow::proto_splitter::FieldIndex::MapKey::TypeCase::kI64:
// Cast to int type, which may be lossy. We'll deal with it when it
// becomes an issue.
return static_cast<int>(field_index.map_key().i64());
break;
case ::tensorflow::proto_splitter::FieldIndex::MapKey::TypeCase::kUi32:
return static_cast<int>(field_index.map_key().ui32());
break;
case ::tensorflow::proto_splitter::FieldIndex::MapKey::TypeCase::kUi64:
return static_cast<int>(field_index.map_key().ui64());
break;
case ::tensorflow::proto_splitter::FieldIndex::MapKey::TypeCase::
TYPE_NOT_SET:
default:
return absl::FailedPreconditionError(
absl::StrCat("Unknown map key type: ", field_index.DebugString()));
}
}
} // namespace
absl::StatusOr<const std::vector<Field>> GetFieldTypes(
const tsl::protobuf::RepeatedPtrField<
::tensorflow::proto_splitter::FieldIndex>& field_tags) {
std::vector<Field> fields;
for (int fti = 0; fti < field_tags.size();) {
switch (field_tags[fti].kind_case()) {
case ::tensorflow::proto_splitter::FieldIndex::KindCase::kField:
fields.push_back(
Field(static_cast<int>(field_tags[fti].field()), std::nullopt));
fti++;
if (fti == field_tags.size()) break;
// Multiple field tags may correspond to a single field when the field
// is repeated or a map.
if (field_tags[fti].has_index()) {
fields.back().second = static_cast<int>(field_tags[fti++].index());
} else if (field_tags[fti].has_map_key()) {
TF_ASSIGN_OR_RETURN(const FieldType& map_key,
GetMapKeyFromFieldIndex(field_tags[fti++]));
fields.back().second = map_key;
}
break;
case ::tensorflow::proto_splitter::FieldIndex::KindCase::kIndex:
return absl::FailedPreconditionError(
"Index doesn't belong to any field.");
break;
case ::tensorflow::proto_splitter::FieldIndex::KindCase::kMapKey:
return absl::FailedPreconditionError(
"Map key doesn't belong to any field.");
break;
case ::tensorflow::proto_splitter::FieldIndex::KindCase::KIND_NOT_SET:
default:
return absl::FailedPreconditionError(absl::StrCat(
"Unknown field kind: ", field_tags[fti].DebugString()));
}
}
return fields;
}
absl::Status SetRepeatedFieldElement(
tsl::protobuf::Message* message,
const tsl::protobuf::FieldDescriptor* field_desc, uint64_t field_index,
const std::string& chunk,
std::function<absl::Status(void)> message_callback) {
if (field_desc->is_map())
return absl::FailedPreconditionError("Field is a map.");
const tsl::protobuf::Reflection* reflection = message->GetReflection();
if (field_index >= reflection->FieldSize(*message, field_desc))
return absl::OutOfRangeError(
absl::StrCat("Field index out of range: ", field_index));
switch (field_desc->cpp_type()) {
case tsl::protobuf::FieldDescriptor::CPPTYPE_INT32:
reflection->SetRepeatedInt32(message, field_desc, std::stoi(chunk),
field_index);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_INT64:
reflection->SetRepeatedInt64(message, field_desc, std::stoll(chunk),
field_index);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_UINT32:
reflection->SetRepeatedUInt32(message, field_desc, std::stoul(chunk),
field_index);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_UINT64:
reflection->SetRepeatedUInt64(message, field_desc, std::stoull(chunk),
field_index);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
reflection->SetRepeatedDouble(message, field_desc, std::stod(chunk),
field_index);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
reflection->SetRepeatedFloat(message, field_desc, std::stof(chunk),
field_index);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_BOOL:
bool b;
std::istringstream(chunk) >> std::boolalpha >> b;
reflection->SetRepeatedBool(message, field_desc, b, field_index);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_ENUM:
reflection->SetRepeatedEnum(
message, field_desc, field_index,
field_desc->enum_type()->FindValueByName(chunk));
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_STRING:
reflection->SetRepeatedString(message, field_desc, field_index, chunk);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
return message_callback();
break;
default:
return absl::FailedPreconditionError(absl::StrCat(
"Proto field type not recognized: ", field_desc->cpp_type_name()));
break;
}
return absl::OkStatus();
}
absl::Status SetFieldElement(
tsl::protobuf::Message* message,
const tsl::protobuf::FieldDescriptor* field_desc, const std::string& chunk,
std::function<absl::Status(void)> message_callback) {
const tsl::protobuf::Reflection* reflection = message->GetReflection();
switch (field_desc->cpp_type()) {
case tsl::protobuf::FieldDescriptor::CPPTYPE_INT32:
reflection->SetInt32(message, field_desc, std::stoi(chunk));
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_INT64:
reflection->SetInt64(message, field_desc, std::stoll(chunk));
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_UINT32:
reflection->SetUInt32(message, field_desc, std::stoul(chunk));
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_UINT64:
reflection->SetUInt64(message, field_desc, std::stoull(chunk));
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
reflection->SetDouble(message, field_desc, std::stod(chunk));
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
reflection->SetFloat(message, field_desc, std::stof(chunk));
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_BOOL:
bool b;
std::istringstream(chunk) >> std::boolalpha >> b;
reflection->SetBool(message, field_desc, b);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_ENUM:
reflection->SetEnum(message, field_desc,
field_desc->enum_type()->FindValueByName(chunk));
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_STRING:
reflection->SetString(message, field_desc, chunk);
break;
case tsl::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
return message_callback();
break;
default:
return absl::FailedPreconditionError("Proto field type not recognized.");
break;
}
return absl::OkStatus();
}
absl::Status AddMapEntry(tsl::protobuf::Message* message,
const tsl::protobuf::FieldDescriptor* field_desc,
FieldType map_key) {
tsl::protobuf::Message* map_entry =
message->GetReflection()->AddMessage(message, field_desc);
const tsl::protobuf::Reflection* reflection = map_entry->GetReflection();
const tsl::protobuf::FieldDescriptor* key =
field_desc->message_type()->FindFieldByNumber(1);
switch (key->cpp_type()) {
case tsl::protobuf::FieldDescriptor::CPPTYPE_INT32: {
TF_ASSIGN_OR_RETURN(auto map_key_int32, FieldInt(map_key));
reflection->SetInt32(map_entry, key, map_key_int32);
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_INT64: {
TF_ASSIGN_OR_RETURN(auto map_key_int64, FieldInt(map_key));
reflection->SetInt64(map_entry, key, map_key_int64);
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
TF_ASSIGN_OR_RETURN(auto map_key_uint32, FieldInt(map_key));
reflection->SetUInt32(map_entry, key, map_key_uint32);
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
TF_ASSIGN_OR_RETURN(auto map_key_uint64, FieldInt(map_key));
reflection->SetUInt64(map_entry, key, map_key_uint64);
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
TF_ASSIGN_OR_RETURN(auto map_key_bool, FieldBool(map_key));
reflection->SetBool(map_entry, key, map_key_bool);
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_STRING: {
reflection->SetString(map_entry, key, FieldString(map_key));
break;
}
default:
return absl::FailedPreconditionError(absl::StrCat(
"Proto field type not recognized.", key->cpp_type_name()));
}
return absl::OkStatus();
}
absl::StatusOr<MutableFieldResult> GetMutableField(
tsl::protobuf::Message* message, const std::vector<FieldType>& fields) {
tsl::protobuf::Message* parent = message;
const tsl::protobuf::FieldDescriptor* field = nullptr;
int index = -1;
auto field_callback =
[&parent, &field, &index](
const tsl::protobuf::FieldDescriptor* field_desc) -> absl::Status {
const tsl::protobuf::Reflection* reflection = parent->GetReflection();
if (field != nullptr) {
// Update the parent proto using the previous FieldDescriptor.
if (field->is_map()) {
parent = reflection->MutableRepeatedMessage(parent, field, index);
parent = parent->GetReflection()->MutableMessage(
parent, parent->GetDescriptor()->FindFieldByNumber(2));
index = -1;
} else if (field->is_repeated()) {
parent = reflection->MutableRepeatedMessage(parent, field, index);
index = -1;
} else {
parent = reflection->MutableMessage(parent, field);
}
}
field = field_desc;
return absl::OkStatus();
};
auto map_key_callback = [&parent, &field, &index](
const tsl::protobuf::FieldDescriptor& key_field,
const FieldType& map_key) -> absl::Status {
// Finds the index of the map field w/ the corresponding map_key.
const tsl::protobuf::Reflection* reflection = parent->GetReflection();
TF_ASSIGN_OR_RETURN(int found_index,
FindMapKey(*parent, *field, &key_field, map_key));
if (found_index == -1) {
return absl::NotFoundError(
absl::StrCat("Error when getting map field, couldn't find key: ",
FieldString(map_key)));
}
if (reflection->FieldSize(*parent, field) <= found_index) {
return absl::NotFoundError(absl::StrCat(
"Can't access index ", index, " in field '", field->name(),
"' (size = ", reflection->FieldSize(*parent, field), ")."));
}
index = found_index;
return absl::OkStatus();
};
auto list_index_callback = [&parent, &field,
&index](FieldType list_index) -> absl::Status {
TF_ASSIGN_OR_RETURN(index, FieldInt(list_index));
const tsl::protobuf::Reflection* reflection = parent->GetReflection();
if (reflection->FieldSize(*parent, field) <= index) {
return absl::NotFoundError(absl::StrCat(
"Can't access index ", index, " in field '", field->name(),
"' (size = ", reflection->FieldSize(*parent, field), ")."));
}
return absl::OkStatus();
};
TF_RETURN_IF_ERROR(WalkFields(*message->GetDescriptor(), fields,
field_callback, map_key_callback,
list_index_callback));
MutableFieldResult result{.parent = parent, .field = field, .index = index};
return result;
}
absl::StatusOr<MutableFieldResult> GetMutableField(
tsl::protobuf::Message* message, const Field& field) {
std::vector<FieldType> fields = {field.first};
if (field.second != std::nullopt) fields.push_back(field.second.value());
return GetMutableField(message, fields);
}
absl::StatusOr<MutableFieldResult> GetMutableField(
tsl::protobuf::Message* message, const FieldType& field_type) {
std::vector<FieldType> fields = {field_type};
return GetMutableField(message, fields);
}
absl::StatusOr<FieldResult> GetField(const tsl::protobuf::Message& message,
const std::vector<FieldType>& fields) {
const tsl::protobuf::Message* parent = &message;
const tsl::protobuf::FieldDescriptor* field = nullptr;
int index = -1;
auto field_callback =
[&parent, &field, &index](
const tsl::protobuf::FieldDescriptor* field_desc) -> absl::Status {
const tsl::protobuf::Reflection* reflection = parent->GetReflection();
if (field != nullptr) {
// Update the parent proto using the previous FieldDescriptor.
if (field->is_map()) {
parent = &reflection->GetRepeatedMessage(*parent, field, index);
parent = &parent->GetReflection()->GetMessage(
*parent, parent->GetDescriptor()->FindFieldByNumber(2));
index = -1;
} else if (field->is_repeated()) {
parent = &reflection->GetRepeatedMessage(*parent, field, index);
index = -1;
} else {
parent = &reflection->GetMessage(*parent, field);
}
}
field = field_desc;
return absl::OkStatus();
};
auto map_key_callback = [&parent, &field, &index](
const tsl::protobuf::FieldDescriptor& key_field,
const FieldType& map_key) -> absl::Status {
// Finds the index of the map field w/ the corresponding map_key.
const tsl::protobuf::Reflection* reflection = parent->GetReflection();
TF_ASSIGN_OR_RETURN(int found_index,
FindMapKey(*parent, *field, &key_field, map_key));
if (found_index == -1) {
return absl::NotFoundError(
absl::StrCat("Error when getting map field, couldn't find key: ",
FieldString(map_key)));
}
if (reflection->FieldSize(*parent, field) <= found_index) {
return absl::NotFoundError(absl::StrCat(
"Can't access index ", index, " in field '", field->name(),
"' (size = ", reflection->FieldSize(*parent, field), ")."));
}
index = found_index;
return absl::OkStatus();
};
auto list_index_callback = [&parent, &field,
&index](FieldType list_index) -> absl::Status {
TF_ASSIGN_OR_RETURN(index, FieldInt(list_index));
const tsl::protobuf::Reflection* reflection = parent->GetReflection();
if (reflection->FieldSize(*parent, field) <= index) {
return absl::NotFoundError(absl::StrCat(
"Can't access index ", index, " in field '", field->name(),
"' (size = ", reflection->FieldSize(*parent, field), ")."));
}
return absl::OkStatus();
};
TF_RETURN_IF_ERROR(WalkFields(*message.GetDescriptor(), fields,
field_callback, map_key_callback,
list_index_callback));
FieldResult result{
.parent = parent,
.field = field,
.index = index,
};
return result;
}
absl::Status AddFieldTag(const tsl::protobuf::Descriptor& desc,
const std::vector<FieldType>& fields,
ChunkedField& chunked_field) {
auto field_callback =
[&chunked_field](
const tsl::protobuf::FieldDescriptor* field_desc) -> absl::Status {
chunked_field.add_field_tag()->set_field(field_desc->number());
return absl::OkStatus();
};
auto map_key_callback = [&chunked_field](
const tsl::protobuf::FieldDescriptor& key_field,
FieldType map_key) -> absl::Status {
return AddMapKey(key_field, map_key, chunked_field);
};
auto list_index_callback =
[&chunked_field](FieldType list_index) -> absl::Status {
TF_ASSIGN_OR_RETURN(auto index, FieldInt(list_index));
chunked_field.add_field_tag()->set_index(index);
return absl::OkStatus();
};
return WalkFields(desc, fields, field_callback, map_key_callback,
list_index_callback);
}
absl::Status AddFieldTag(const tsl::protobuf::Descriptor& desc,
const Field& field, ChunkedField& chunked_field) {
std::vector<FieldType> fields = {field.first};
if (field.second != std::nullopt) fields.push_back(field.second.value());
return AddFieldTag(desc, fields, chunked_field);
}
absl::StatusOr<int> FindMapKey(const tsl::protobuf::Message& parent,
const tsl::protobuf::FieldDescriptor& map_field,
const tsl::protobuf::FieldDescriptor* key_field,
FieldType map_key) {
const tsl::protobuf::Reflection* reflection = parent.GetReflection();
if (!map_field.is_map()) {
return absl::InvalidArgumentError(absl::StrCat(
"FindMapKey() was given a non map field: ", map_field.full_name()));
}
if (key_field == nullptr) {
key_field = map_field.message_type()->FindFieldByNumber(1);
}
bool found = false;
for (int i = 0; i < reflection->FieldSize(parent, &map_field) && !found;
i++) {
auto kv_pair = &reflection->GetRepeatedMessage(parent, &map_field, i);
auto kv_reflection = kv_pair->GetReflection();
switch (key_field->cpp_type()) {
case tsl::protobuf::FieldDescriptor::CPPTYPE_INT32: {
TF_ASSIGN_OR_RETURN(auto key, FieldInt(map_key));
if (kv_reflection->GetInt32(*kv_pair, key_field) == key) {
found = true;
}
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_INT64: {
TF_ASSIGN_OR_RETURN(auto key, FieldInt(map_key));
if (kv_reflection->GetInt64(*kv_pair, key_field) == key) {
found = true;
}
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
TF_ASSIGN_OR_RETURN(auto key, FieldInt(map_key));
if (kv_reflection->GetUInt32(*kv_pair, key_field) == key) {
found = true;
}
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
TF_ASSIGN_OR_RETURN(auto key, FieldInt(map_key));
if (kv_reflection->GetUInt64(*kv_pair, key_field) == key) {
found = true;
}
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
TF_ASSIGN_OR_RETURN(auto key, FieldBool(map_key));
if (kv_reflection->GetBool(*kv_pair, key_field) == key) {
found = true;
}
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_STRING: {
if (kv_reflection->GetString(*kv_pair, key_field) ==
FieldString(map_key)) {
found = true;
}
break;
}
case tsl::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
case tsl::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
case tsl::protobuf::FieldDescriptor::CPPTYPE_ENUM:
case tsl::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
return absl::FailedPreconditionError(absl::StrCat(
"Type is not supported for MapKey.type: ", key_field->cpp_type()));
default:
return absl::FailedPreconditionError(
"Proto field type not recognized.");
}
if (found) return i;
}
return -1;
}
namespace {
const std::vector<std::pair<double, std::string>>& ByteUnits() {
static const auto& byte_units =
*(new std::vector<std::pair<double, std::string>>(
{{1, "B"}, {1 << 10, "KiB"}, {1 << 20, "MiB"}, {1 << 30, "GiB"}}));
return byte_units;
}
} // namespace
std::string HumanReadableBytes(int64_t byte_count) {
for (int i = 1; i < ByteUnits().size(); i++) {
if (byte_count < ByteUnits()[i].first) {
return absl::StrFormat("%.1f%s", byte_count / ByteUnits()[i - 1].first,
ByteUnits()[i - 1].second);
}
}
int i = ByteUnits().size() - 1;
return absl::StrFormat("%.1f%s", byte_count / ByteUnits()[i].first,
ByteUnits()[i].second);
}
std::string HumanReadableDuration(int64_t microseconds) {
if (microseconds < 1000) {
return absl::StrFormat("%d microseconds", microseconds);
} else if (microseconds < 1e6) {
return absl::StrFormat("%.2f ms", microseconds / 1e3);
} else {
return absl::StrFormat("%.2f s", microseconds / 1e6);
}
}
absl::StatusOr<riegeli::RecordReader<riegeli::FdReader<>>> GetRiegeliReader(
absl::string_view cpb_file) {
riegeli::RecordReader reader(riegeli::Maker<riegeli::FdReader>(cpb_file));
if (!reader.ok()) {
return reader.status();
}
return reader;
}
absl::StatusOr<riegeli::RecordReader<riegeli::StringReader<>>>
GetRiegeliStringReader(absl::string_view cpb_data) {
riegeli::RecordReader reader(
riegeli::Maker<riegeli::StringReader<>>(cpb_data));
if (!reader.ok()) {
return reader.status();
}
return reader;
}
absl::StatusOr<::tensorflow::proto_splitter::ChunkMetadata> GetChunkMetadata(
riegeli::RecordReaderBase& reader) {
::tensorflow::proto_splitter::ChunkMetadata chunk_metadata;
bool read_metadata_success = reader.Seek(reader.Size().value()) &&
reader.SeekBack() &&
reader.ReadRecord(chunk_metadata);
if (read_metadata_success) return chunk_metadata;
return reader.status();
}
absl::StatusOr<std::string> ReadChunk(
riegeli::RecordReaderBase& reader,
const ::tensorflow::proto_splitter::ChunkInfo& chunk_info) {
riegeli::Position pos = chunk_info.offset();
std::string chunk(chunk_info.size(), '\0');
if (reader.Seek(pos) && reader.ReadRecord(chunk)) return chunk;
return absl::NotFoundError(
absl::StrCat("Chunk could not be found at position: ", pos, ".\n",
reader.status().ToString()));
}
absl::StatusOr<bool> OnlyContainsPb(absl::string_view prefix) {
const std::string pb_file = absl::StrCat(prefix, ".pb");
const std::string cpb_file = absl::StrCat(prefix, ".cpb");
TF_ASSIGN_OR_RETURN(bool is_pb,
internal::FileExists(Env::Default(), pb_file));
TF_ASSIGN_OR_RETURN(bool is_cpb,
internal::FileExists(Env::Default(), cpb_file));
if (is_pb && !is_cpb) {
return true;
} else if (!is_pb && !is_cpb) {
return absl::NotFoundError(
absl::StrCat("Could not find SavedModel .pb or .cpb at supplied "
"export directory path with prefix: ",
prefix,
". Check that "
"the directory exists and that you have the right "
"permissions for accessing it."));
}
LOG(INFO) << "Reading chunked proto from " << cpb_file;
return false;
}
} // namespace tools::proto_splitter
} // namespace tensorflow