Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions rust/codegen_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,13 @@ pub(crate) mod interop {
#[cfg(cpp_kernel)]
unsafe fn __unstable_wrap_raw_message_mut_unchecked_lifetime(raw: *mut c_void) -> Self;
}

/// A trait that provides a descriptor for a message.
/// This is only implemented by the messages that implement the
/// `proto2::Message` interface.
#[cfg(all(cpp_kernel, not(lite_runtime)))]
pub trait MessageDescriptorInterop {
/// Returns a pointer to a `proto2::Descriptor`.
fn __unstable_get_descriptor() -> *const std::ffi::c_void;
}
}
1 change: 1 addition & 0 deletions rust/cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ unsafe extern "C" {
pub fn proto2_rust_Message_serialize(m: RawMessage, output: &mut SerializedData) -> bool;
pub fn proto2_rust_Message_copy_from(dst: RawMessage, src: RawMessage) -> bool;
pub fn proto2_rust_Message_merge_from(dst: RawMessage, src: RawMessage) -> bool;
pub fn proto2_rust_Message_get_descriptor(m: RawMessage) -> *const std::ffi::c_void;
}

impl Drop for InnerProtoString {
Expand Down
17 changes: 17 additions & 0 deletions rust/cpp_kernel/message.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#include "google/protobuf/message.h"

#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; }
Expand Down Expand Up @@ -42,4 +46,17 @@ void proto2_rust_Message_merge_from(google::protobuf::MessageLite* dst,
dst->CheckTypeAndMergeFrom(src);
}

// 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"
2 changes: 2 additions & 0 deletions rust/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use std::fmt;
// This problem is referred to as "perfect derive".
// https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/

#[cfg(all(cpp_kernel, not(lite_runtime)))]
pub use crate::codegen_traits::interop::MessageDescriptorInterop;
pub use crate::codegen_traits::{
create::Parse,
interop::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop},
Expand Down
1 change: 1 addition & 0 deletions rust/test/cpp/interop/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ cc_library(
deps = [
":interop_test_cc_proto",
"//rust/cpp_kernel:cpp_api",
"//src/google/protobuf",
"@abseil-cpp//absl/log:absl_check",
"@abseil-cpp//absl/strings",
],
Expand Down
13 changes: 12 additions & 1 deletion rust/test/cpp/interop/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use googletest::prelude::*;
use protobuf_cpp::prelude::*;

use protobuf_cpp::__internal::runtime::PtrAndLen;
use protobuf_cpp::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop};
use protobuf_cpp::{
MessageDescriptorInterop, MessageMutInterop, MessageViewInterop, OwnedMessageInterop,
};
use std::ffi::c_void;

use interop_test_rust_proto::{InteropTestMessage, InteropTestMessageMut, InteropTestMessageView};
Expand Down Expand Up @@ -40,6 +42,8 @@ unsafe extern "C" {
fn GetBytesExtension(msg: *const c_void) -> PtrAndLen;

fn GetConstStaticInteropTestMessage() -> *const c_void;

fn IsExpectedDescriptor(provided: *const c_void) -> bool;
}

#[gtest]
Expand Down Expand Up @@ -155,3 +159,10 @@ fn view_of_const_static() {
assert_eq!(view.i64(), 0);
assert_eq!(view.default_int32(), 41);
}

#[gtest]
fn descriptor_interop() {
let descriptor = InteropTestMessage::__unstable_get_descriptor();
let result = unsafe { IsExpectedDescriptor(descriptor) };
assert!(result);
}
5 changes: 5 additions & 0 deletions rust/test/cpp/interop/test_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "absl/log/absl_check.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/descriptor.h"
#include "rust/cpp_kernel/serialized_data.h"
#include "rust/cpp_kernel/strings.h"
#include "rust/test/cpp/interop/interop_test.pb.h"
Expand Down Expand Up @@ -64,3 +65,7 @@ extern "C" const void* GetConstStaticInteropTestMessage() {
static const auto* msg = new InteropTestMessage;
return msg;
}

extern "C" bool IsExpectedDescriptor(const google::protobuf::Descriptor* descriptor) {
return descriptor == InteropTestMessage::GetDescriptor();
}
14 changes: 14 additions & 0 deletions src/google/protobuf/compiler/rust/message.cc
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,20 @@ void GenerateRs(Context& ctx, const Descriptor& msg, const upb::DefPool& pool) {
}
}
)rs");

// TODO: Check if we are in a forced lite runtime in addition
// to the existing check.
if (msg.file()->options().optimize_for() != FileOptions::LITE_RUNTIME) {
ctx.Emit({{"Msg", RsSafeName(msg.name())}},
R"rs(
#[cfg(all(cpp_kernel, not(lite_runtime)))]
impl $pb$::MessageDescriptorInterop for $Msg$ {
fn __unstable_get_descriptor() -> *const $std$::ffi::c_void {
unsafe { $pbr$::proto2_rust_Message_get_descriptor(<$Msg$View as Default>::default().raw_msg()) }
}
}
)rs");
}
}
} // NOLINT(readability/fn_size)

Expand Down
Loading