blob: b9e3e211a1d6e0cfdee6e5941ad9e10714cf78f9 [file]
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//! Traits related to interop with the underlying C++ Proto types.
//!
//! These traits are deliberately not available on the prelude, as they should
//! be used rarely and with great care.
//!
//! The raw pointers vended and accepted by these traits are only guaranteed to
//! point to a `proto2::MessageLite`. The pointer is only guaranteed to be a full `proto2::Message*`
//! if the Rust type also implements the `WithReflection` trait. Casting a pointer to
//! `proto2::Message*` for a type that does not implement `WithReflection` is
//! undefined behavior.
use super::*;
/// Methods for converting to and from a raw, owned C++ message pointer.
pub trait OwnedMessageInterop: SealedInternal {
/// Drops `self` and returns an underlying pointer that it was wrapping
/// without deleting it. The pointer is a `MessageLite*` in C++ (and only a
/// `Message*` if `Self` implements `WithReflection`, see the module docs).
///
/// The caller is responsible for ensuring the returned pointer is
/// subsequently deleted (eg by moving it into a std::unique_ptr in
/// C++), or else it will leak.
fn __unstable_leak_raw_message(self) -> *mut std::ffi::c_void;
/// Takes exclusive ownership of the `raw_message`.
///
/// # Safety
/// - The underlying message must be for the same type as `Self`
/// - The pointer passed in must not be used by the caller after being passed here (must not
/// be read, written, or deleted)
unsafe fn __unstable_take_ownership_of_raw_message(raw_message: *mut std::ffi::c_void) -> Self;
}
/// Methods for converting to and from a raw C++ message view pointer.
pub trait MessageViewInterop<'msg>: SealedInternal {
/// Borrows `self` as an underlying C++ raw pointer.
///
/// 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
/// `const MessageLite*` in C++ (and only as a `const Message*` if `Self`
/// implements `WithReflection`, see the module docs), and not be mutated
/// in any way, and any mutation to the parent message may invalidate it,
/// and it must not be deleted.
fn __unstable_as_raw_message(&self) -> *const std::ffi::c_void;
/// Wraps the provided pointer as a MessageView.
///
/// This takes a ref of a pointer so that a stack variable's lifetime
/// can be used for a safe lifetime; under most cases this is
/// the correct lifetime and this should be used as:
/// ```ignore
/// fn called_from_cpp(msg: *const c_void) {
/// // `msg` is known live for the current stack frame, so view's
/// // lifetime is also tied to the current stack frame here:
/// let view = unsafe { __unstable_wrap_raw_message(&msg) };
/// do_something_with_view(view);
/// }
/// ```
///
/// # Safety
/// - The underlying message must be for the same type as `Self`
/// - The underlying message must be alive for 'msg and not mutated while the wrapper is live.
unsafe fn __unstable_wrap_raw_message(raw: &'msg *const std::ffi::c_void) -> Self;
/// Wraps the provided pointer as a MessageView.
///
/// Unlike `__unstable_wrap_raw_message` this has no constraints
/// on lifetime: the caller has a free choice for the lifetime.
///
/// As this is much easier to get the lifetime wrong than
/// `__unstable_wrap_raw_message`, prefer using that wherever
/// your lifetime can be tied to a stack lifetime, and only use this one
/// if its not possible (e.g. with a 'static lifetime).
///
/// # Safety
/// - The underlying message must be for the same type as `Self`
/// - The underlying message must be alive for the caller-chosen 'msg and not mutated while
/// the wrapper is live.
unsafe fn __unstable_wrap_raw_message_unchecked_lifetime(raw: *const std::ffi::c_void) -> Self;
/// Converts this view into a reference to the underlying C++ `proto2::MessageLite`.
///
/// This is most commonly used to pass messages to C++ functions which accept
/// `const proto2::MessageLite&` or `const proto2::MessageLite*`.
///
/// The returned `T` is the Rust binding for `proto2::MessageLite` (see
/// [`CppMessageLiteType`]). It is normally inferred from the parameter type
/// of the C++ function being called.
///
/// To get a mutable reference, see [`MessageMutInterop::as_cpp_message_lite_mut`].
#[allow(clippy::wrong_self_convention)]
fn as_cpp_message_lite<T: CppMessageLiteType>(self) -> &'msg T
where
Self: Sized,
{
// SAFETY: `self` is a view, so the message is live and not mutated, other than through
// C++ `mutable` members, for `'msg`. With the C++ kernel, the raw message pointer is a
// `proto2::MessageLite*`, so we can reinterpret it as a `&'msg proto2::MessageLite`.
unsafe { &*(self.__unstable_as_raw_message() as *const T) }
}
}
// TODO: Add an equivalent `CppMessageType` and
// `as_cpp_message{,_mut}` (bounded on `WithReflection`) once `proto2::Message`
// has Crubit bindings.
/// A trait to be implemented exclusively by the Rust binding for the C++ `proto2::MessageLite`
/// class (and not subclasses).
///
/// This trait is used to allow [`MessageViewInterop::as_cpp_message_lite`] and
/// [`MessageMutInterop::as_cpp_message_lite_mut`] to cast views and muts to the underlying C++
/// `proto2::MessageLite` type without creating a build-time dependency from this crate on the
/// `proto2` bindings.
///
/// There is not yet an equivalent for `proto2::Message` (which does not yet
/// have Crubit bindings, and would require a `WithReflection` bound since
/// messages using the lite runtime are not `proto2::Message`s). C++ APIs that
/// need reflection can take a `proto2::MessageLite` and use
/// `proto2::DynamicCastMessage<proto2::Message>`.
///
/// # Safety
///
/// This trait must only be implemented by the Crubit-generated Rust binding for
/// `proto2::MessageLite` so that `as_cpp_message_lite{,_mut}` can reinterpret the
/// `proto2::MessageLite*` of any message borrowed by a view or mut as a `&Self` or
/// `Pin<&mut Self>`.
///
/// Additionally, the Crubit binding of `proto2::MessageLite` must continue to meet these
/// requirements: it has the same layout as the C++ class, is `!Unpin`, and
/// only contains `Cell<MaybeUninit<u8>>` storage.
pub unsafe trait CppMessageLiteType {}
/// Methods for converting to and from a raw, mutable C++ message pointer.
pub trait MessageMutInterop<'msg>: SealedInternal {
/// Exclusive borrows `self` as an underlying mutable C++ raw pointer.
///
/// 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
/// non-owned `MessageLite*` in C++ (and only as a `Message*` if `Self`
/// implements `WithReflection`, see the module docs). And any mutation to
/// the parent message may invalidate it, and it must not be deleted.
fn __unstable_as_raw_message_mut(&mut self) -> *mut std::ffi::c_void;
/// Wraps the provided C++ pointer as a MessageMut.
///
/// This takes a ref of a pointer so that a stack variable's lifetime
/// can be used for a safe lifetime; under most cases this is
/// the correct lifetime and this should be used as:
/// ```ignore
/// fn called_from_cpp(msg: *mut c_void) {
/// // `msg` is known live for the current stack frame, so mut's
/// // lifetime is also tied to the current stack frame here:
/// let m = unsafe { __unstable_wrap_raw_message_mut(&mut msg) };
/// do_something_with_mut(m);
/// }
/// ```
///
/// # Safety
/// - The underlying message must be for the same type as `Self`
/// - The underlying message must be alive for 'msg and not read or mutated while the wrapper
/// is live.
unsafe fn __unstable_wrap_raw_message_mut(raw: &'msg mut *mut std::ffi::c_void) -> Self;
/// Wraps the provided pointer as a MessageMut.
///
/// Unlike `__unstable_wrap_raw_message_mut` this has no constraints
/// on lifetime: the caller has a free choice for the lifetime.
///
/// As this is much easier to get the lifetime wrong than
/// `__unstable_wrap_raw_message_mut`, prefer using that wherever
/// the lifetime can be tied to a stack lifetime, and only use this one
/// if its not possible (e.g. with a 'static lifetime).
///
/// # Safety
/// - The underlying message must be for the same type as `Self`
/// - The underlying message must be alive for the caller-chosen 'msg and not mutated while
/// the wrapper is live.
unsafe fn __unstable_wrap_raw_message_mut_unchecked_lifetime(
raw: *mut std::ffi::c_void,
) -> Self;
/// Converts this mut into a mutable reference to the underlying C++ `proto2::MessageLite`.
///
/// This is most commonly used to pass messages to C++ functions which accept
/// `proto2::MessageLite&` or `proto2::MessageLite*`.
///
/// The returned `T` is the Rust binding for `proto2::MessageLite` (see
/// [`CppMessageLiteType`]). It is normally inferred from the parameter type
/// of the C++ function being called.
///
/// To get a shared reference, see [`MessageViewInterop::as_cpp_message_lite`].
#[allow(clippy::wrong_self_convention)]
fn as_cpp_message_lite_mut<T: CppMessageLiteType>(mut self) -> std::pin::Pin<&'msg mut T>
where
Self: Sized,
{
// SAFETY: `self` is mut, so the message is live and exclusively borrowed for `'msg`.
//
// With the C++ kernel, the raw message pointer is a
// `proto2::MessageLite*`, which `T: CppMessageLiteType` allows
// reinterpreting as a `Pin<&'msg mut T>` under these conditions. The
// message is a C++ object that Rust never moves, so pinning it is sound.
unsafe {
std::pin::Pin::new_unchecked(&mut *(self.__unstable_as_raw_message_mut() as *mut T))
}
}
}
/// Note that this is only implemented for the types implementing `proto2::Message`.
#[cfg(not(lite_runtime))]
pub trait MessageDescriptorInterop {
/// Returns a pointer to a `proto2::Descriptor` or `nullptr` if the
/// descriptor is not available.
fn __unstable_get_descriptor() -> *const std::ffi::c_void;
}
impl<'a, T> MessageMutInterop<'a> for T
where
Self: AsMut + CppGetRawMessageMut + From<MessageMutInner<'a, <Self as AsMut>::MutProxied>>,
<Self as AsMut>::MutProxied: Message,
{
unsafe fn __unstable_wrap_raw_message_mut(msg: &'a mut *mut std::ffi::c_void) -> Self {
let raw = RawMessage::new(*msg as *mut _).unwrap();
let inner = unsafe { MessageMutInner::wrap_raw(raw) };
inner.into()
}
unsafe fn __unstable_wrap_raw_message_mut_unchecked_lifetime(
msg: *mut std::ffi::c_void,
) -> Self {
let raw = RawMessage::new(msg as *mut _).unwrap();
let inner = unsafe { MessageMutInner::wrap_raw(raw) };
inner.into()
}
fn __unstable_as_raw_message_mut(&mut self) -> *mut std::ffi::c_void {
self.get_raw_message_mut(Private).as_ptr() as *mut _
}
}