Change CppInterop traits to operate on *const or *mut c_void instead of protobuf::__runtime::RawMessage

PiperOrigin-RevId: 665332958
pull/17861/head
Protobuf Team Bot 3 months ago committed by Copybara-Service
parent 57ba42815e
commit b0db5bd029
  1. 30
      rust/codegen_traits.rs
  2. 6
      rust/cpp.rs
  3. 22
      rust/test/cpp/interop/main.rs
  4. 58
      src/google/protobuf/compiler/rust/message.cc

@ -8,7 +8,6 @@
//! Traits that are implemeted by codegen types. //! Traits that are implemeted by codegen types.
use crate::__internal::SealedInternal; use crate::__internal::SealedInternal;
use crate::__runtime::RawMessage;
use crate::{MutProxied, MutProxy, ViewProxy}; use crate::{MutProxied, MutProxy, ViewProxy};
use create::Parse; use create::Parse;
use interop::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop}; use interop::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop};
@ -114,20 +113,21 @@ pub(crate) mod write {
/// These traits are deliberately not available on the prelude, as they should /// These traits are deliberately not available on the prelude, as they should
/// be used rarely and with great care. /// be used rarely and with great care.
pub(crate) mod interop { pub(crate) mod interop {
use super::{RawMessage, SealedInternal}; use super::SealedInternal;
use std::ffi::c_void;
/// Traits related to owned message interop. Note that these trait fns /// Traits related to owned message interop. Note that these trait fns
/// are only available on C++ kernel as upb interop of owned messages /// are only available on C++ kernel as upb interop of owned messages
/// requires more work to handle the Arena behavior. /// requires more work to handle the Arena behavior.
pub trait OwnedMessageInterop: SealedInternal { pub trait OwnedMessageInterop: SealedInternal {
/// Drops `self` and returns the `RawMessage` that it was wrapping /// Drops `self` and returns an underlying pointer that it was wrapping
/// without deleting it. /// without deleting it.
/// ///
/// The caller is responsible for ensuring the returned RawMessage is /// The caller is responsible for ensuring the returned pointer is
/// subsequently deleted (eg by moving it into a std::unique_ptr in /// subsequently deleted (eg by moving it into a std::unique_ptr in
/// C++), or else it will leak. /// C++), or else it will leak.
#[cfg(cpp_kernel)] #[cfg(cpp_kernel)]
fn __unstable_leak_raw_message(self) -> RawMessage; fn __unstable_leak_raw_message(self) -> *mut c_void;
/// Takes exclusive ownership of the `raw_message`. /// Takes exclusive ownership of the `raw_message`.
/// ///
@ -136,49 +136,51 @@ pub(crate) mod interop {
/// - The pointer passed in must not be used by the caller after being /// - The pointer passed in must not be used by the caller after being
/// passed here (must not be read, written, or deleted) /// passed here (must not be read, written, or deleted)
#[cfg(cpp_kernel)] #[cfg(cpp_kernel)]
unsafe fn __unstable_take_ownership_of_raw_message(raw_message: RawMessage) -> Self; unsafe fn __unstable_take_ownership_of_raw_message(raw_message: *mut c_void) -> Self;
} }
/// Traits related to message view interop. /// Traits related to message view interop.
pub trait MessageViewInterop<'msg>: SealedInternal { pub trait MessageViewInterop<'msg>: SealedInternal {
/// Borrows `self` as an underlying `RawMessage`. /// Borrows `self` as an underlying C++ raw pointer.
/// ///
/// Note that the returned Value must be used under the same constraints /// Note that the returned Value must be used under the same constraints
/// as though it were a borrow of `self`: it should be treated as a /// as though it were a borrow of `self`: it should be treated as a
/// `const Message*` in C++, and not be mutated in any way, and any /// `const Message*` in C++, and not be mutated in any way, and any
/// mutation to the parent message may invalidate it, and it /// mutation to the parent message may invalidate it, and it
/// must not be deleted. /// must not be deleted.
fn __unstable_as_raw_message(&self) -> RawMessage; fn __unstable_as_raw_message(&self) -> *const c_void;
/// Wraps the provided `RawMessage` as a MessageView. /// Wraps the provided pointer as a MessageView. This takes a ref
/// of a pointer so that a stack variable's lifetime can be used
/// to help make the borrow checker safer.
/// ///
/// # Safety /// # Safety
/// - The underlying message must be for the same type as `Self` /// - The underlying message must be for the same type as `Self`
/// - The underlying message must be alive for 'msg and not mutated /// - The underlying message must be alive for 'msg and not mutated
/// while the wrapper is live. /// while the wrapper is live.
unsafe fn __unstable_wrap_raw_message(raw: &'msg RawMessage) -> Self; unsafe fn __unstable_wrap_raw_message(raw: &'msg *const c_void) -> Self;
} }
/// Traits related to message mut interop. Note that these trait fns /// Traits related to message mut interop. Note that these trait fns
/// are only available on C++ kernel as upb interop of owned messages /// are only available on C++ kernel as upb interop of owned messages
/// requires more work to handle the Arena behavior. /// requires more work to handle the Arena behavior.
pub trait MessageMutInterop<'msg>: SealedInternal { pub trait MessageMutInterop<'msg>: SealedInternal {
/// Exclusive borrows `self` as a `RawMessage`. /// Exclusive borrows `self` as an underlying mutable C++ raw pointer.
/// ///
/// Note that the returned Value must be used under the same constraints /// Note that the returned Value must be used under the same constraints
/// as though it were a mut borrow of `self`: it should be treated as a /// as though it were a mut borrow of `self`: it should be treated as a
/// non-owned `Message*` in C++. And any mutation to the parent message /// non-owned `Message*` in C++. And any mutation to the parent message
/// may invalidate it, and it must not be deleted. /// may invalidate it, and it must not be deleted.
#[cfg(cpp_kernel)] #[cfg(cpp_kernel)]
fn __unstable_as_raw_message_mut(&mut self) -> RawMessage; fn __unstable_as_raw_message_mut(&mut self) -> *mut c_void;
/// Wraps the provided `RawMessage` as a MessageMut. /// Wraps the provided C++ pointer as a MessageMut.
/// ///
/// # Safety /// # Safety
/// - The underlying message must be for the same type as `Self` /// - The underlying message must be for the same type as `Self`
/// - The underlying message must be alive for 'msg and not read or /// - The underlying message must be alive for 'msg and not read or
/// mutated while the wrapper is live. /// mutated while the wrapper is live.
#[cfg(cpp_kernel)] #[cfg(cpp_kernel)]
unsafe fn __unstable_wrap_raw_message_mut(raw: &'msg mut RawMessage) -> Self; unsafe fn __unstable_wrap_raw_message_mut(raw: &'msg mut *mut c_void) -> Self;
} }
} }

@ -365,6 +365,12 @@ impl<'msg> MutatorMessageRef<'msg> {
MutatorMessageRef { msg: msg.msg, _phantom: PhantomData } MutatorMessageRef { msg: msg.msg, _phantom: PhantomData }
} }
/// # Safety
/// - The underlying pointer must be sound and live for the lifetime 'msg.
pub unsafe fn wrap_raw(_private: Private, raw: RawMessage) -> Self {
MutatorMessageRef { msg: raw, _phantom: PhantomData }
}
pub fn from_parent( pub fn from_parent(
_private: Private, _private: Private,
_parent_msg: MutatorMessageRef<'msg>, _parent_msg: MutatorMessageRef<'msg>,

@ -8,8 +8,9 @@
use googletest::prelude::*; use googletest::prelude::*;
use protobuf_cpp::prelude::*; use protobuf_cpp::prelude::*;
use protobuf_cpp::__runtime::{PtrAndLen, RawMessage}; use protobuf_cpp::__runtime::PtrAndLen;
use protobuf_cpp::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop}; use protobuf_cpp::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop};
use std::ffi::c_void;
use unittest_rust_proto::{TestAllExtensions, TestAllTypes, TestAllTypesMut, TestAllTypesView}; use unittest_rust_proto::{TestAllExtensions, TestAllTypes, TestAllTypesMut, TestAllTypesView};
macro_rules! proto_assert_eq { macro_rules! proto_assert_eq {
@ -26,14 +27,14 @@ macro_rules! proto_assert_eq {
// Helper functions invoking C++ Protobuf APIs directly in C++. // Helper functions invoking C++ Protobuf APIs directly in C++.
// Defined in `test_utils.cc`. // Defined in `test_utils.cc`.
extern "C" { extern "C" {
fn TakeOwnershipAndGetOptionalInt32(msg: RawMessage) -> i32; fn TakeOwnershipAndGetOptionalInt32(msg: *mut c_void) -> i32;
fn DeserializeTestAllTypes(data: *const u8, len: usize) -> RawMessage; fn DeserializeTestAllTypes(data: *const u8, len: usize) -> *mut c_void;
fn MutateTestAllTypes(msg: RawMessage); fn MutateTestAllTypes(msg: *mut c_void);
fn SerializeTestAllTypes(msg: RawMessage) -> protobuf_cpp::__runtime::SerializedData; fn SerializeTestAllTypes(msg: *const c_void) -> protobuf_cpp::__runtime::SerializedData;
fn DeleteTestAllTypes(msg: RawMessage); fn DeleteTestAllTypes(msg: *mut c_void);
fn NewWithExtension() -> RawMessage; fn NewWithExtension() -> *mut c_void;
fn GetBytesExtension(msg: RawMessage) -> PtrAndLen; fn GetBytesExtension(msg: *const c_void) -> PtrAndLen;
} }
#[gtest] #[gtest]
@ -113,7 +114,8 @@ fn deserialize_in_cpp_into_view() {
let data = msg1.serialize().unwrap(); let data = msg1.serialize().unwrap();
let raw_msg = unsafe { DeserializeTestAllTypes((*data).as_ptr(), data.len()) }; let raw_msg = unsafe { DeserializeTestAllTypes((*data).as_ptr(), data.len()) };
let msg2 = unsafe { TestAllTypesView::__unstable_wrap_raw_message(&raw_msg) }; let const_msg = raw_msg as *const _;
let msg2 = unsafe { TestAllTypesView::__unstable_wrap_raw_message(&const_msg) };
proto_assert_eq!(msg1, msg2); proto_assert_eq!(msg1, msg2);

@ -1315,61 +1315,61 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
if (ctx.is_cpp()) { if (ctx.is_cpp()) {
ctx.Emit({{"Msg", RsSafeName(msg.name())}}, R"rs( ctx.Emit({{"Msg", RsSafeName(msg.name())}}, R"rs(
impl<'a> $Msg$Mut<'a> { impl<'a> $Msg$Mut<'a> {
//~ msg is a &mut so that the borrow checker enforces exclusivity to pub unsafe fn __unstable_wrap_cpp_grant_permission_to_break(
//~ prevent constructing multiple Muts/Views from the same RawMessage. msg: &'a mut *mut std::ffi::c_void) -> Self {
pub fn __unstable_wrap_cpp_grant_permission_to_break(
msg: &'a mut $pbr$::RawMessage) -> Self {
Self { Self {
inner: $pbr$::MutatorMessageRef::from_raw_msg($pbi$::Private, msg) inner: $pbr$::MutatorMessageRef::wrap_raw(
$pbi$::Private,
$pbr$::RawMessage::new(*msg as *mut _).unwrap())
} }
} }
pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> $pbr$::RawMessage { pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> *mut std::ffi::c_void {
self.raw_msg() self.raw_msg().as_ptr() as *mut _
} }
} }
impl<'a> $Msg$View<'a> { impl<'a> $Msg$View<'a> {
//~ msg is a & so that the caller can claim the message is live for the
//~ corresponding lifetime.
pub fn __unstable_wrap_cpp_grant_permission_to_break( pub fn __unstable_wrap_cpp_grant_permission_to_break(
msg: &'a $pbr$::RawMessage) -> Self { msg: &'a *const std::ffi::c_void) -> Self {
Self::new($pbi$::Private, *msg) Self::new($pbi$::Private, $pbr$::RawMessage::new(*msg as *mut _).unwrap())
} }
pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> $pbr$::RawMessage { pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> *const std::ffi::c_void {
self.msg self.msg.as_ptr() as *const _
} }
} }
impl $pb$::OwnedMessageInterop for $Msg$ { impl $pb$::OwnedMessageInterop for $Msg$ {
unsafe fn __unstable_take_ownership_of_raw_message(msg: $pbr$::RawMessage) -> Self { unsafe fn __unstable_take_ownership_of_raw_message(msg: *mut std::ffi::c_void) -> Self {
Self { inner: $pbr$::MessageInner { msg } } Self { inner: $pbr$::MessageInner { msg: $pbr$::RawMessage::new(msg as *mut _).unwrap() } }
} }
fn __unstable_leak_raw_message(self) -> $pbr$::RawMessage { fn __unstable_leak_raw_message(self) -> *mut std::ffi::c_void {
let s = std::mem::ManuallyDrop::new(self); let s = std::mem::ManuallyDrop::new(self);
s.raw_msg() s.raw_msg().as_ptr() as *mut _
} }
} }
impl<'a> $pb$::MessageMutInterop<'a> for $Msg$Mut<'a> { impl<'a> $pb$::MessageMutInterop<'a> for $Msg$Mut<'a> {
unsafe fn __unstable_wrap_raw_message_mut( unsafe fn __unstable_wrap_raw_message_mut(
msg: &'a mut $pbr$::RawMessage) -> Self { msg: &'a mut *mut std::ffi::c_void) -> Self {
Self { Self {
inner: $pbr$::MutatorMessageRef::from_raw_msg($pbi$::Private, msg) inner: $pbr$::MutatorMessageRef::wrap_raw(
$pbi$::Private,
$pbr$::RawMessage::new(*msg as *mut _).unwrap())
} }
} }
fn __unstable_as_raw_message_mut(&mut self) -> $pbr$::RawMessage { fn __unstable_as_raw_message_mut(&mut self) -> *mut std::ffi::c_void {
self.raw_msg() self.raw_msg().as_ptr() as *mut _
} }
} }
impl<'a> $pb$::MessageViewInterop<'a> for $Msg$View<'a> { impl<'a> $pb$::MessageViewInterop<'a> for $Msg$View<'a> {
unsafe fn __unstable_wrap_raw_message( unsafe fn __unstable_wrap_raw_message(
msg: &'a $pbr$::RawMessage) -> Self { msg: &'a *const std::ffi::c_void) -> Self {
Self::new($pbi$::Private, *msg) Self::new($pbi$::Private, $pbr$::RawMessage::new(*msg as *mut _).unwrap())
} }
fn __unstable_as_raw_message(&self) -> $pbr$::RawMessage { fn __unstable_as_raw_message(&self) -> *const std::ffi::c_void {
self.msg self.msg.as_ptr() as *const _
} }
} }
)rs"); )rs");
@ -1381,11 +1381,11 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
impl<'a> $pb$::MessageViewInterop<'a> for $Msg$View<'a> { impl<'a> $pb$::MessageViewInterop<'a> for $Msg$View<'a> {
unsafe fn __unstable_wrap_raw_message( unsafe fn __unstable_wrap_raw_message(
msg: &'a $pbr$::RawMessage) -> Self { msg: &'a *const std::ffi::c_void) -> Self {
Self::new($pbi$::Private, *msg) Self::new($pbi$::Private, $pbr$::RawMessage::new(*msg as *mut _).unwrap())
} }
fn __unstable_as_raw_message(&self) -> $pbr$::RawMessage { fn __unstable_as_raw_message(&self) -> *const std::ffi::c_void {
self.msg self.msg.as_ptr() as *const _
} }
} }
)rs"); )rs");

Loading…
Cancel
Save