| #include "google/protobuf/message.h" |
| |
| #include <cstddef> |
| #include <limits> |
| |
| #include "google/protobuf/message_lite.h" |
| #include "rust/cpp_kernel/serialized_data.h" |
| #include "rust/cpp_kernel/strings.h" |
| |
| constexpr bool kHasFullRuntime = true; |
| |
| extern "C" { |
| |
| void proto2_rust_Message_delete(google::protobuf::MessageLite* m) { delete m; } |
| |
| void proto2_rust_Message_clear(google::protobuf::MessageLite* m) { m->Clear(); } |
| |
| bool proto2_rust_Message_parse(google::protobuf::MessageLite* m, |
| google::protobuf::rust::PtrAndLen input) { |
| return m->ParseFromString(input.AsStringView()); |
| } |
| |
| bool proto2_rust_Message_parse_dont_enforce_required( |
| google::protobuf::MessageLite* m, google::protobuf::rust::PtrAndLen input) { |
| return m->ParsePartialFromString(input.AsStringView()); |
| } |
| |
| bool proto2_rust_Message_serialize(const google::protobuf::MessageLite* m, |
| google::protobuf::rust::SerializedData* output) { |
| return google::protobuf::rust::SerializeMsg(m, output); |
| } |
| |
| size_t proto2_rust_Message_serialized_len(const google::protobuf::MessageLite* m) { |
| return m->ByteSizeLong(); |
| } |
| |
| void proto2_rust_Message_copy_from(google::protobuf::MessageLite* dst, |
| const google::protobuf::MessageLite& src) { |
| dst->Clear(); |
| dst->CheckTypeAndMergeFrom(src); |
| } |
| |
| void proto2_rust_Message_merge_from(google::protobuf::MessageLite* dst, |
| const google::protobuf::MessageLite& src) { |
| dst->CheckTypeAndMergeFrom(src); |
| } |
| |
| void proto2_rust_Message_take_from(google::protobuf::MessageLite* dst, |
| google::protobuf::MessageLite* src) { |
| // Rust guarantees that dst and src do not alias. |
| |
| dst->Clear(); |
| if constexpr (kHasFullRuntime) { |
| if (auto* dst_msg = google::protobuf::DynamicCastMessage<google::protobuf::Message>(dst)) { |
| // Rust's TakeFrom trait bounds (MutProxied = Self::Proxied) guarantee at |
| // compile time that dst and src point to instances of the exact same |
| // C++ message class. Therefore, if dst is a google::protobuf::Message, src is |
| // guaranteed to also be a google::protobuf::Message, allowing us to safely |
| // static_cast and skip a second runtime dynamic_cast check. |
| auto* src_msg = static_cast<google::protobuf::Message*>(src); |
| if (const auto* reflection = dst_msg->GetReflection()) { |
| // TODO: Use a generic Move operation here instead of Swap, |
| // which will be more efficient if the protos are in different arenas. |
| reflection->Swap(dst_msg, src_msg); |
| return; |
| } |
| } |
| } |
| dst->CheckTypeAndMergeFrom(*src); |
| src->Clear(); |
| } |
| |
| // Returns a pointer to the descriptor of the message, or nullptr if |
| // the message is not google::protobuf::Message. |
| const void* proto2_rust_Message_get_descriptor(const google::protobuf::MessageLite* m) { |
| if constexpr (kHasFullRuntime) { |
| auto msg = google::protobuf::DynamicCastMessage<google::protobuf::Message>(m); |
| if (msg == nullptr) { |
| return nullptr; |
| } |
| return msg->GetDescriptor(); |
| } |
| return nullptr; |
| } |
| |
| } // extern "C" |