2026-03-20 11:10:52 -07:00
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
unsafe extern "C" {
|
|
|
|
|
pub fn proto2_rust_Message_delete(m: RawMessage);
|
|
|
|
|
pub fn proto2_rust_Message_clear(m: RawMessage);
|
|
|
|
|
pub fn proto2_rust_Message_parse(m: RawMessage, input: PtrAndLen) -> bool;
|
|
|
|
|
pub fn proto2_rust_Message_parse_dont_enforce_required(m: RawMessage, input: PtrAndLen)
|
|
|
|
|
-> bool;
|
|
|
|
|
pub fn proto2_rust_Message_serialize(m: RawMessage, output: &mut SerializedData) -> bool;
|
2026-04-23 14:28:59 -07:00
|
|
|
pub fn proto2_rust_Message_serialized_len(m: RawMessage) -> usize;
|
2026-03-20 11:10:52 -07:00
|
|
|
pub fn proto2_rust_Message_copy_from(dst: RawMessage, src: RawMessage);
|
|
|
|
|
pub fn proto2_rust_Message_merge_from(dst: RawMessage, src: RawMessage);
|
2026-07-20 13:10:52 -07:00
|
|
|
pub fn proto2_rust_Message_take_from(dst: RawMessage, src: RawMessage);
|
2026-03-20 11:10:52 -07:00
|
|
|
pub fn proto2_rust_Message_get_descriptor(m: RawMessage) -> *const std::ffi::c_void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsafe extern "C" {
|
|
|
|
|
/// From compare.h
|
|
|
|
|
///
|
|
|
|
|
/// # Safety
|
|
|
|
|
/// - `raw1` and `raw2` legally dereferenceable MessageLite* pointers.
|
|
|
|
|
#[link_name = "proto2_rust_messagelite_equals"]
|
|
|
|
|
pub fn raw_message_equals(raw1: RawMessage, raw2: RawMessage) -> bool;
|
2026-08-13 09:23:09 -07:00
|
|
|
|
|
|
|
|
/// From compare.h
|
|
|
|
|
///
|
|
|
|
|
/// # Safety
|
|
|
|
|
/// - `actual` and `expected` legally dereferenceable MessageLite* pointers.
|
|
|
|
|
#[link_name = "proto2_rust_messagelite_partially_equals"]
|
|
|
|
|
pub fn raw_message_partially_equals(actual: RawMessage, expected: RawMessage) -> bool;
|
2026-03-20 11:10:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
#[repr(transparent)]
|
|
|
|
|
pub struct OwnedMessageInner<T> {
|
|
|
|
|
raw: RawMessage,
|
|
|
|
|
_phantom: PhantomData<T>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Message> OwnedMessageInner<T> {
|
|
|
|
|
/// # Safety
|
|
|
|
|
/// - `raw` must point to a message of type `T` and outlive `Self`.
|
|
|
|
|
pub unsafe fn wrap_raw(raw: RawMessage) -> Self {
|
|
|
|
|
OwnedMessageInner { raw, _phantom: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn raw(&self) -> RawMessage {
|
|
|
|
|
self.raw
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Mutators that point to their original message use this to do so.
|
|
|
|
|
///
|
|
|
|
|
/// Since C++ messages manage their own memory, this can just copy the
|
|
|
|
|
/// `RawMessage` instead of referencing an arena like UPB must.
|
|
|
|
|
///
|
2026-03-24 05:47:45 -07:00
|
|
|
/// The following invariants must be upheld:
|
2026-03-20 11:10:52 -07:00
|
|
|
///
|
|
|
|
|
/// - No concurrent mutation for any two fields in a message: this means
|
|
|
|
|
/// mutators cannot be `Send` but are `Sync`.
|
|
|
|
|
/// - If there are multiple accessible `Mut` to a single message at a time, they
|
|
|
|
|
/// must be different fields, and not be in the same oneof. As such, a `Mut`
|
|
|
|
|
/// cannot be `Clone` but *can* reborrow itself with `.as_mut()`, which
|
|
|
|
|
/// converts `&'b mut Mut<'a, T>` to `Mut<'b, T>`.
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
#[repr(transparent)]
|
|
|
|
|
pub struct MessageMutInner<'msg, T> {
|
|
|
|
|
raw: RawMessage,
|
|
|
|
|
_phantom: PhantomData<(&'msg mut (), T)>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'msg, T: Message> MessageMutInner<'msg, T> {
|
|
|
|
|
#[allow(clippy::needless_pass_by_ref_mut)] // Sound construction requires mutable access.
|
|
|
|
|
pub fn mut_of_owned(msg: &'msg mut OwnedMessageInner<T>) -> Self {
|
|
|
|
|
MessageMutInner { raw: msg.raw, _phantom: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// # Safety
|
|
|
|
|
/// - The underlying pointer must be mutable, of type `T` and live for the lifetime 'msg.
|
|
|
|
|
pub unsafe fn wrap_raw(raw: RawMessage) -> Self {
|
|
|
|
|
MessageMutInner { raw, _phantom: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn from_parent<ParentT: Message>(
|
|
|
|
|
_parent_msg: MessageMutInner<'msg, ParentT>,
|
|
|
|
|
message_field_ptr: RawMessage,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Self { raw: message_field_ptr, _phantom: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn raw(&self) -> RawMessage {
|
|
|
|
|
self.raw
|
|
|
|
|
}
|
2026-03-24 05:47:45 -07:00
|
|
|
|
|
|
|
|
pub fn as_view(&self) -> MessageViewInner<'msg, T> {
|
|
|
|
|
MessageViewInner { raw: self.raw, _phantom: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn reborrow<'shorter>(&mut self) -> MessageMutInner<'shorter, T>
|
|
|
|
|
where
|
|
|
|
|
'msg: 'shorter,
|
|
|
|
|
{
|
|
|
|
|
MessageMutInner { raw: self.raw, _phantom: PhantomData }
|
|
|
|
|
}
|
2026-03-20 11:10:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
#[repr(transparent)]
|
|
|
|
|
pub struct MessageViewInner<'msg, T> {
|
|
|
|
|
raw: RawMessage,
|
|
|
|
|
_phantom: PhantomData<(&'msg (), T)>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'msg, T: Message> Clone for MessageViewInner<'msg, T> {
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
*self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl<'msg, T: Message> Copy for MessageViewInner<'msg, T> {}
|
|
|
|
|
|
|
|
|
|
impl<'msg, T: Message> MessageViewInner<'msg, T> {
|
|
|
|
|
/// # Safety
|
|
|
|
|
/// - The underlying pointer must of type `T` and live for the lifetime 'msg.
|
|
|
|
|
pub unsafe fn wrap_raw(raw: RawMessage) -> Self {
|
|
|
|
|
MessageViewInner { raw, _phantom: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn view_of_owned(msg: &'msg OwnedMessageInner<T>) -> Self {
|
|
|
|
|
MessageViewInner { raw: msg.raw, _phantom: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn view_of_mut(msg: MessageMutInner<'msg, T>) -> Self {
|
|
|
|
|
MessageViewInner { raw: msg.raw, _phantom: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn raw(&self) -> RawMessage {
|
|
|
|
|
self.raw
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Internal-only trait to support blanket impls that need const access to raw messages
|
|
|
|
|
/// on codegen. Should never be used by application code.
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
pub unsafe trait CppGetRawMessage: SealedInternal {
|
|
|
|
|
fn get_raw_message(&self, _private: Private) -> RawMessage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The generated code only implements this trait on View proxies, so we use a blanket
|
|
|
|
|
// implementation for owned messages and Mut proxies.
|
|
|
|
|
unsafe impl<T> CppGetRawMessage for T
|
|
|
|
|
where
|
|
|
|
|
Self: AsMut + AsView,
|
|
|
|
|
for<'a> View<'a, <Self as AsView>::Proxied>: CppGetRawMessage,
|
|
|
|
|
{
|
|
|
|
|
fn get_raw_message(&self, _private: Private) -> RawMessage {
|
|
|
|
|
self.as_view().get_raw_message(_private)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Internal-only trait to support blanket impls that need mutable access to raw messages
|
|
|
|
|
/// on codegen. Must not be implemented on View proxies. Should never be used by application code.
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
pub unsafe trait CppGetRawMessageMut: SealedInternal {
|
|
|
|
|
fn get_raw_message_mut(&mut self, _private: Private) -> RawMessage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The generated code only implements this trait on Mut proxies, so we use a blanket implementation
|
|
|
|
|
// for owned messages.
|
|
|
|
|
unsafe impl<T> CppGetRawMessageMut for T
|
|
|
|
|
where
|
|
|
|
|
Self: MutProxied,
|
|
|
|
|
for<'a> Mut<'a, Self>: CppGetRawMessageMut,
|
|
|
|
|
{
|
|
|
|
|
fn get_raw_message_mut(&mut self, _private: Private) -> RawMessage {
|
|
|
|
|
self.as_mut().get_raw_message_mut(_private)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-31 12:02:02 -07:00
|
|
|
pub trait KernelMessage: CppGetRawMessage + CppGetRawMessageMut + OwnedMessageInterop {}
|
|
|
|
|
impl<T: CppGetRawMessage + CppGetRawMessageMut + OwnedMessageInterop> KernelMessage for T {}
|
2026-03-20 11:10:52 -07:00
|
|
|
|
Added infrastructure for Rust Extensions support, but left it disabled for now.
This code makes use of some Rust features that are not supported in Rust 1.85 (our currently supported version), so we cannot enable the codegen for this feature yet.
This CL introduces support for [Protobuf Extensions](https://engdoc.corp.google.com/eng/doc/devguide/proto/programming-guides/proto2.html#extensions) to the Rust Protobuf library, a key feature for full Proto2 API parity.
Key changes include:
1. **Code Generation:**
* Added `compiler/rust/extension.cc` and `extension.h` to handle the generation of Rust code for extension definitions.
* Updated `generator.cc` and `message.cc` to invoke extension generation for both top-level and nested extensions.
* Generates `ExtensionId` constants for each extension.
2. **Runtime API (`rust/extension.rs`):**
* Introduced the generic `ExtensionId<Extendee, T>` type to identify and type-check extensions.
* Defined traits for extension operations: `ExtHas`, `ExtGet`, `ExtSet`, `ExtClear`, and `ExtGetMut`.
* Implemented methods on `ExtensionId` that dispatch to the trait implementations provided by the active kernel.
3. **Kernel Implementations:**
* **C++ Kernel (`rust/cpp_kernel/extension.rs`):** Implemented extension traits by calling into new C++ FFI functions (defined in `rust/cpp_kernel/extension.cc`) that interact with the C++ `ExtensionSet`.
* **UPB Kernel (`rust/upb_kernel/extension.rs`):** Implemented extension traits using UPB's MiniTable-based extension API. Extension MiniTables are registered at static initialization time using the `linkme` crate.
4. **Build System:**
* Updated `protobuf/rust/BUILD` and `protobuf/compiler/rust/BUILD` to include new files.
* Added a dependency on `//third_party/rust/linkme/v0_3` for the UPB kernel's extension registration.
5. **Testing:**
* Added `test/extensions.proto` and `test/extensions_separate_file.proto` to define various extension types.
* Added `test/shared/extensions_test.rs` with comprehensive tests covering presence, getters, setters, defaults, nested extensions, submessage extensions, repeated extensions, serialization, and `MergeFrom`.
This change enables Rust users to define and interact with Protobuf extensions in a type-safe manner, compatible with both the C++ and UPB runtimes.
PiperOrigin-RevId: 896506594
2026-04-08 08:06:15 -07:00
|
|
|
pub trait KernelMessageView<'msg>:
|
|
|
|
|
CppGetRawMessage + MessageViewInterop<'msg> + AsView + From<MessageViewInner<'msg, Self::KMessage>>
|
|
|
|
|
{
|
|
|
|
|
type KMessage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'msg, T> KernelMessageView<'msg> for T
|
|
|
|
|
where
|
|
|
|
|
T: CppGetRawMessage
|
|
|
|
|
+ MessageViewInterop<'msg>
|
|
|
|
|
+ AsView
|
|
|
|
|
+ From<MessageViewInner<'msg, T::Proxied>>,
|
|
|
|
|
{
|
|
|
|
|
type KMessage = T::Proxied;
|
|
|
|
|
}
|
2026-03-20 11:10:52 -07:00
|
|
|
|
Added infrastructure for Rust Extensions support, but left it disabled for now.
This code makes use of some Rust features that are not supported in Rust 1.85 (our currently supported version), so we cannot enable the codegen for this feature yet.
This CL introduces support for [Protobuf Extensions](https://engdoc.corp.google.com/eng/doc/devguide/proto/programming-guides/proto2.html#extensions) to the Rust Protobuf library, a key feature for full Proto2 API parity.
Key changes include:
1. **Code Generation:**
* Added `compiler/rust/extension.cc` and `extension.h` to handle the generation of Rust code for extension definitions.
* Updated `generator.cc` and `message.cc` to invoke extension generation for both top-level and nested extensions.
* Generates `ExtensionId` constants for each extension.
2. **Runtime API (`rust/extension.rs`):**
* Introduced the generic `ExtensionId<Extendee, T>` type to identify and type-check extensions.
* Defined traits for extension operations: `ExtHas`, `ExtGet`, `ExtSet`, `ExtClear`, and `ExtGetMut`.
* Implemented methods on `ExtensionId` that dispatch to the trait implementations provided by the active kernel.
3. **Kernel Implementations:**
* **C++ Kernel (`rust/cpp_kernel/extension.rs`):** Implemented extension traits by calling into new C++ FFI functions (defined in `rust/cpp_kernel/extension.cc`) that interact with the C++ `ExtensionSet`.
* **UPB Kernel (`rust/upb_kernel/extension.rs`):** Implemented extension traits using UPB's MiniTable-based extension API. Extension MiniTables are registered at static initialization time using the `linkme` crate.
4. **Build System:**
* Updated `protobuf/rust/BUILD` and `protobuf/compiler/rust/BUILD` to include new files.
* Added a dependency on `//third_party/rust/linkme/v0_3` for the UPB kernel's extension registration.
5. **Testing:**
* Added `test/extensions.proto` and `test/extensions_separate_file.proto` to define various extension types.
* Added `test/shared/extensions_test.rs` with comprehensive tests covering presence, getters, setters, defaults, nested extensions, submessage extensions, repeated extensions, serialization, and `MergeFrom`.
This change enables Rust users to define and interact with Protobuf extensions in a type-safe manner, compatible with both the C++ and UPB runtimes.
PiperOrigin-RevId: 896506594
2026-04-08 08:06:15 -07:00
|
|
|
pub trait KernelMessageMut<'msg>:
|
|
|
|
|
CppGetRawMessageMut + MessageMutInterop<'msg> + AsMut + From<MessageMutInner<'msg, Self::KMessage>>
|
|
|
|
|
{
|
|
|
|
|
type KMessage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'msg, T> KernelMessageMut<'msg> for T
|
|
|
|
|
where
|
|
|
|
|
T: CppGetRawMessageMut
|
|
|
|
|
+ MessageMutInterop<'msg>
|
|
|
|
|
+ AsMut
|
|
|
|
|
+ From<MessageMutInner<'msg, T::MutProxied>>,
|
|
|
|
|
{
|
|
|
|
|
type KMessage = T::MutProxied;
|
|
|
|
|
}
|
2026-03-20 11:10:52 -07:00
|
|
|
|
|
|
|
|
/// Message equality definition which may have both false-negatives and false-positives in the face
|
|
|
|
|
/// of unknown fields.
|
|
|
|
|
///
|
|
|
|
|
/// This behavior is deliberately held back from being exposed as an `Eq` trait for messages. The
|
|
|
|
|
/// reason is that it is impossible to properly compare unknown fields for message equality, since
|
|
|
|
|
/// without the schema you cannot know how to interpret the wire format properly for comparison.
|
|
|
|
|
///
|
|
|
|
|
/// False negative cases (where message_eq will return false on unknown fields where it
|
|
|
|
|
/// would return true if the fields were known) are common and will occur in production: for
|
|
|
|
|
/// example, as map and repeated fields look exactly the same, map field order is unstable, the
|
|
|
|
|
/// comparison cannot know to treat it as unordered and will return false when it was the same
|
|
|
|
|
/// map but in a different order.
|
|
|
|
|
///
|
|
|
|
|
/// False positives cases (where message_eq will return true on unknown fields where it would have
|
|
|
|
|
/// return false if the fields were known) are possible but uncommon in practice. One example
|
|
|
|
|
/// of this direction can occur if two fields are defined in the same oneof and both are present on
|
|
|
|
|
/// the wire but in opposite order, without the schema these messages appear equal but with the
|
|
|
|
|
/// schema they are not-equal.
|
|
|
|
|
///
|
|
|
|
|
/// This lossy behavior in the face of unknown fields is especially problematic in the face of
|
|
|
|
|
/// extensions and other treeshaking behaviors where a given field being known or not to binary is a
|
|
|
|
|
/// spooky-action-at-a-distance behavior, which may lead to surprising changes in outcome in
|
|
|
|
|
/// equality tests based on changes made arbitrarily distant from the code performing the equality
|
|
|
|
|
/// check.
|
|
|
|
|
///
|
|
|
|
|
/// Broadly this is recommended for use in tests (where unknown field behaviors are rarely a
|
|
|
|
|
/// concern), and in limited/targeted cases where the lossy behavior in the face of unknown fields
|
|
|
|
|
/// behavior is unlikely to be a problem.
|
|
|
|
|
pub fn message_eq<T>(a: &T, b: &T) -> bool
|
|
|
|
|
where
|
|
|
|
|
T: AsView + Debug,
|
|
|
|
|
for<'a> View<'a, <T as AsView>::Proxied>: CppGetRawMessage,
|
|
|
|
|
{
|
|
|
|
|
unsafe {
|
|
|
|
|
raw_message_equals(
|
|
|
|
|
a.as_view().get_raw_message(Private),
|
|
|
|
|
b.as_view().get_raw_message(Private),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-13 09:23:09 -07:00
|
|
|
/// Message equality definition for checking partial equality of two messages. Fields that are not
|
|
|
|
|
/// set in the expected message are ignored when comparing against the actual message.
|
|
|
|
|
///
|
|
|
|
|
/// This should only be used for testing purposes.
|
|
|
|
|
pub fn message_partially_eq<T>(actual: &T, expected: &T) -> bool
|
|
|
|
|
where
|
|
|
|
|
T: AsView + Debug,
|
|
|
|
|
for<'a> View<'a, <T as AsView>::Proxied>: CppGetRawMessage,
|
|
|
|
|
{
|
|
|
|
|
// Safety: we provide valid pointers and the C++ code does not retain them.
|
|
|
|
|
unsafe {
|
|
|
|
|
raw_message_partially_equals(
|
|
|
|
|
actual.as_view().get_raw_message(Private),
|
|
|
|
|
expected.as_view().get_raw_message(Private),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-20 11:10:52 -07:00
|
|
|
impl<T> MatcherEq for T
|
|
|
|
|
where
|
|
|
|
|
Self: AsView + Debug,
|
|
|
|
|
for<'a> View<'a, <Self as AsView>::Proxied>: CppGetRawMessage,
|
|
|
|
|
{
|
|
|
|
|
fn matches(&self, o: &Self) -> bool {
|
|
|
|
|
message_eq(self, o)
|
|
|
|
|
}
|
2026-08-13 09:23:09 -07:00
|
|
|
|
|
|
|
|
fn matches_partially(&self, expected: &Self) -> bool {
|
|
|
|
|
message_partially_eq(self, expected)
|
|
|
|
|
}
|
2026-03-20 11:10:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: CppGetRawMessageMut> Clear for T {
|
|
|
|
|
fn clear(&mut self) {
|
|
|
|
|
unsafe { proto2_rust_Message_clear(self.get_raw_message_mut(Private)) }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: CppGetRawMessageMut> ClearAndParse for T {
|
|
|
|
|
fn clear_and_parse(&mut self, data: &[u8]) -> Result<(), ParseError> {
|
|
|
|
|
unsafe { proto2_rust_Message_parse(self.get_raw_message_mut(Private), data.into()) }
|
|
|
|
|
.then_some(())
|
|
|
|
|
.ok_or(ParseError)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clear_and_parse_dont_enforce_required(&mut self, data: &[u8]) -> Result<(), ParseError> {
|
|
|
|
|
unsafe {
|
|
|
|
|
proto2_rust_Message_parse_dont_enforce_required(
|
|
|
|
|
self.get_raw_message_mut(Private),
|
|
|
|
|
data.into(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
.then_some(())
|
|
|
|
|
.ok_or(ParseError)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: CppGetRawMessage> Serialize for T {
|
|
|
|
|
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
|
|
|
|
|
let mut serialized_data = SerializedData::new();
|
|
|
|
|
let success = unsafe {
|
|
|
|
|
proto2_rust_Message_serialize(self.get_raw_message(Private), &mut serialized_data)
|
|
|
|
|
};
|
|
|
|
|
if success {
|
|
|
|
|
Ok(serialized_data.into_vec())
|
|
|
|
|
} else {
|
|
|
|
|
Err(SerializeError)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-23 14:28:59 -07:00
|
|
|
|
|
|
|
|
fn serialized_len(&self) -> usize {
|
|
|
|
|
unsafe { proto2_rust_Message_serialized_len(self.get_raw_message(Private)) }
|
|
|
|
|
}
|
2026-03-20 11:10:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> TakeFrom for T
|
|
|
|
|
where
|
2026-07-20 13:10:52 -07:00
|
|
|
Self: AsMut,
|
|
|
|
|
for<'a> Mut<'a, Self::Proxied>: CppGetRawMessageMut,
|
2026-03-20 11:10:52 -07:00
|
|
|
{
|
|
|
|
|
fn take_from(&mut self, mut src: impl AsMut<MutProxied = Self::Proxied>) {
|
2026-07-20 13:10:52 -07:00
|
|
|
unsafe {
|
|
|
|
|
proto2_rust_Message_take_from(
|
|
|
|
|
self.as_mut().get_raw_message_mut(Private),
|
|
|
|
|
src.as_mut().get_raw_message_mut(Private),
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-03-20 11:10:52 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> CopyFrom for T
|
|
|
|
|
where
|
|
|
|
|
Self: AsMut,
|
|
|
|
|
for<'a> View<'a, Self::Proxied>: CppGetRawMessage,
|
|
|
|
|
for<'a> Mut<'a, Self::Proxied>: CppGetRawMessageMut,
|
|
|
|
|
{
|
|
|
|
|
fn copy_from(&mut self, src: impl AsView<Proxied = Self::Proxied>) {
|
|
|
|
|
unsafe {
|
|
|
|
|
proto2_rust_Message_copy_from(
|
|
|
|
|
self.as_mut().get_raw_message_mut(Private),
|
|
|
|
|
src.as_view().get_raw_message(Private),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> MergeFrom for T
|
|
|
|
|
where
|
|
|
|
|
Self: AsMut,
|
|
|
|
|
for<'a> View<'a, Self::Proxied>: CppGetRawMessage,
|
|
|
|
|
for<'a> Mut<'a, Self::Proxied>: CppGetRawMessageMut,
|
|
|
|
|
{
|
|
|
|
|
fn merge_from(&mut self, src: impl AsView<Proxied = Self::Proxied>) {
|
|
|
|
|
// SAFETY: self and src are both valid `T`s.
|
|
|
|
|
unsafe {
|
|
|
|
|
proto2_rust_Message_merge_from(
|
|
|
|
|
self.as_mut().get_raw_message_mut(Private),
|
|
|
|
|
src.as_view().get_raw_message(Private),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|