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.
238 lines
8.6 KiB
238 lines
8.6 KiB
#include "google/protobuf/map.h" |
|
|
|
#include <cstddef> |
|
#include <cstdint> |
|
#include <string> |
|
#include <type_traits> |
|
#include <utility> |
|
|
|
#include "absl/functional/overload.h" |
|
#include "absl/log/absl_log.h" |
|
#include "absl/strings/string_view.h" |
|
#include "google/protobuf/message.h" |
|
#include "google/protobuf/message_lite.h" |
|
#include "rust/cpp_kernel/strings.h" |
|
|
|
namespace google { |
|
namespace protobuf { |
|
namespace rust { |
|
namespace { |
|
|
|
using MapValueTag = internal::UntypedMapBase::TypeKind; |
|
|
|
// LINT.IfChange(map_ffi) |
|
struct MapValue { |
|
MapValueTag tag; |
|
union { |
|
bool b; |
|
uint32_t u32; |
|
uint64_t u64; |
|
float f32; |
|
double f64; |
|
std::string* s; |
|
google::protobuf::MessageLite* message; |
|
}; |
|
}; |
|
// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/cpp.rs:map_ffi) |
|
|
|
template <typename T> |
|
struct FromViewType { |
|
using type = T; |
|
}; |
|
|
|
template <> |
|
struct FromViewType<PtrAndLen> { |
|
using type = std::string; |
|
}; |
|
|
|
template <typename Key> |
|
using KeyMap = internal::KeyMapBase< |
|
internal::KeyForBase<typename FromViewType<Key>::type>>; |
|
|
|
template <typename T> |
|
T AsViewType(T t) { |
|
return t; |
|
} |
|
|
|
absl::string_view AsViewType(PtrAndLen key) { return key.AsStringView(); } |
|
|
|
void InitializeMessageValue(void* raw_ptr, MessageLite* msg) { |
|
MessageLite* new_msg = internal::RustMapHelper::PlacementNew(msg, raw_ptr); |
|
auto* full_msg = DynamicCastMessage<Message>(new_msg); |
|
|
|
// If we are working with a full (non-lite) proto, we reflectively swap the |
|
// value into place. Otherwise, we have to perform a copy. |
|
if (full_msg != nullptr) { |
|
full_msg->GetReflection()->Swap(full_msg, DynamicCastMessage<Message>(msg)); |
|
} else { |
|
new_msg->CheckTypeAndMergeFrom(*msg); |
|
} |
|
delete msg; |
|
} |
|
|
|
template <typename Key> |
|
bool Insert(internal::UntypedMapBase* m, Key key, MapValue value) { |
|
internal::NodeBase* node = internal::RustMapHelper::AllocNode(m); |
|
if constexpr (std::is_same<Key, PtrAndLen>::value) { |
|
key.PlacementNewString(node->GetVoidKey()); |
|
} else { |
|
*static_cast<Key*>(node->GetVoidKey()) = key; |
|
} |
|
|
|
m->VisitValue(node, absl::Overload{ |
|
[&](bool* v) { *v = value.b; }, |
|
[&](uint32_t* v) { *v = value.u32; }, |
|
[&](uint64_t* v) { *v = value.u64; }, |
|
[&](float* v) { *v = value.f32; }, |
|
[&](double* v) { *v = value.f64; }, |
|
[&](std::string* str) { |
|
new (str) std::string(std::move(*value.s)); |
|
delete value.s; |
|
}, |
|
[&](MessageLite* msg) { |
|
InitializeMessageValue(msg, value.message); |
|
}, |
|
}); |
|
|
|
return internal::RustMapHelper::InsertOrReplaceNode( |
|
static_cast<KeyMap<Key>*>(m), node); |
|
} |
|
|
|
void PopulateMapValue(const internal::UntypedMapBase& map, |
|
internal::NodeBase* node, MapValue& output) { |
|
map.VisitValue(node, absl::Overload{ |
|
[&](const bool* v) { |
|
output.tag = MapValueTag::kBool; |
|
output.b = *v; |
|
}, |
|
[&](const uint32_t* v) { |
|
output.tag = MapValueTag::kU32; |
|
output.u32 = *v; |
|
}, |
|
[&](const uint64_t* v) { |
|
output.tag = MapValueTag::kU64; |
|
output.u64 = *v; |
|
}, |
|
[&](const float* v) { |
|
output.tag = MapValueTag::kFloat; |
|
output.f32 = *v; |
|
}, |
|
[&](const double* v) { |
|
output.tag = MapValueTag::kDouble; |
|
output.f64 = *v; |
|
}, |
|
[&](std::string* str) { |
|
output.tag = MapValueTag::kString; |
|
output.s = str; |
|
}, |
|
[&](MessageLite* msg) { |
|
output.tag = MapValueTag::kMessage; |
|
output.message = msg; |
|
}, |
|
}); |
|
} |
|
|
|
template <typename Key> |
|
bool Get(internal::UntypedMapBase* m, Key key, MapValue* value) { |
|
auto* map_base = static_cast<KeyMap<Key>*>(m); |
|
auto result = internal::RustMapHelper::FindHelper(map_base, AsViewType(key)); |
|
if (result.node == nullptr) { |
|
return false; |
|
} |
|
PopulateMapValue(*m, result.node, *value); |
|
return true; |
|
} |
|
|
|
template <typename Key> |
|
bool Remove(internal::UntypedMapBase* m, Key key) { |
|
auto* map_base = static_cast<KeyMap<Key>*>(m); |
|
return internal::RustMapHelper::EraseImpl(map_base, AsViewType(key)); |
|
} |
|
|
|
template <typename Key> |
|
void IterGet(const internal::UntypedMapIterator* iter, Key* key, |
|
MapValue* value) { |
|
internal::NodeBase* node = iter->node_; |
|
if constexpr (std::is_same<Key, PtrAndLen>::value) { |
|
const std::string* s = iter->m_->GetKey<std::string>(node); |
|
*key = PtrAndLen{s->data(), s->size()}; |
|
} else { |
|
*key = *iter->m_->GetKey<Key>(node); |
|
} |
|
PopulateMapValue(*iter->m_, node, *value); |
|
} |
|
|
|
} // namespace |
|
} // namespace rust |
|
} // namespace protobuf |
|
} // namespace google |
|
|
|
extern "C" { |
|
|
|
void proto2_rust_thunk_UntypedMapIterator_increment( |
|
google::protobuf::internal::UntypedMapIterator* iter) { |
|
iter->PlusPlus(); |
|
} |
|
|
|
google::protobuf::internal::UntypedMapBase* proto2_rust_map_new( |
|
google::protobuf::rust::MapValue key_prototype, |
|
google::protobuf::rust::MapValue value_prototype) { |
|
return new google::protobuf::internal::UntypedMapBase( |
|
/* arena = */ nullptr, |
|
google::protobuf::internal::UntypedMapBase::GetTypeInfoDynamic( |
|
key_prototype.tag, value_prototype.tag, |
|
value_prototype.tag == google::protobuf::rust::MapValueTag::kMessage |
|
? value_prototype.message |
|
: nullptr)); |
|
} |
|
|
|
size_t proto2_rust_map_size(google::protobuf::internal::UntypedMapBase* m) { |
|
return m->size(); |
|
} |
|
|
|
google::protobuf::internal::UntypedMapIterator proto2_rust_map_iter( |
|
google::protobuf::internal::UntypedMapBase* m) { |
|
return m->begin(); |
|
} |
|
|
|
void proto2_rust_map_free(google::protobuf::internal::UntypedMapBase* m) { |
|
m->ClearTable(false, nullptr); |
|
delete m; |
|
} |
|
|
|
void proto2_rust_map_clear(google::protobuf::internal::UntypedMapBase* m) { |
|
m->ClearTable(true, nullptr); |
|
} |
|
|
|
#define DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(cpp_type, suffix) \ |
|
bool proto2_rust_map_insert_##suffix(google::protobuf::internal::UntypedMapBase* m, \ |
|
cpp_type key, \ |
|
google::protobuf::rust::MapValue value) { \ |
|
return google::protobuf::rust::Insert(m, key, value); \ |
|
} \ |
|
\ |
|
bool proto2_rust_map_get_##suffix(google::protobuf::internal::UntypedMapBase* m, \ |
|
cpp_type key, \ |
|
google::protobuf::rust::MapValue* value) { \ |
|
return google::protobuf::rust::Get(m, key, value); \ |
|
} \ |
|
\ |
|
bool proto2_rust_map_remove_##suffix(google::protobuf::internal::UntypedMapBase* m, \ |
|
cpp_type key) { \ |
|
return google::protobuf::rust::Remove(m, key); \ |
|
} \ |
|
\ |
|
void proto2_rust_map_iter_get_##suffix( \ |
|
const google::protobuf::internal::UntypedMapIterator* iter, cpp_type* key, \ |
|
google::protobuf::rust::MapValue* value) { \ |
|
return google::protobuf::rust::IterGet(iter, key, value); \ |
|
} |
|
|
|
DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(int32_t, i32) |
|
DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(uint32_t, u32) |
|
DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(int64_t, i64) |
|
DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(uint64_t, u64) |
|
DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(bool, bool) |
|
DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(google::protobuf::rust::PtrAndLen, ProtoString) |
|
|
|
} // extern "C"
|
|
|