diff --git a/rust/BUILD b/rust/BUILD index 4aa9cb028030..092cfd46dcd0 100644 --- a/rust/BUILD +++ b/rust/BUILD @@ -49,8 +49,8 @@ PROTOBUF_SHARED = [ "enum.rs", "internal.rs", "macros.rs", - "optional.rs", "primitive.rs", + "optional.rs", "proxied.rs", "repeated.rs", "shared.rs", diff --git a/rust/cpp.rs b/rust/cpp.rs index 225c97e5192b..fe726679a0fc 100644 --- a/rust/cpp.rs +++ b/rust/cpp.rs @@ -171,6 +171,13 @@ impl Deref for SerializedData { } } +// TODO: remove after IntoProxied has been implemented for bytes. +impl AsRef<[u8]> for SerializedData { + fn as_ref(&self) -> &[u8] { + self + } +} + impl Drop for SerializedData { fn drop(&mut self) { // SAFETY: `data` was allocated by the Rust global allocator with a @@ -185,15 +192,6 @@ impl fmt::Debug for SerializedData { } } -impl SettableValue<[u8]> for SerializedData { - fn set_on<'msg>(self, _private: Private, mut mutator: Mut<'msg, [u8]>) - where - [u8]: 'msg, - { - mutator.set(self.as_ref()) - } -} - /// A type to transfer an owned Rust string across the FFI boundary: /// * This struct is ABI-compatible with the equivalent C struct. /// * It owns its data but does not drop it. Immediately turn it into a @@ -240,7 +238,6 @@ pub type MessageAbsentMutData<'msg, T> = crate::vtable::RawVTableOptionalMutator pub type BytesPresentMutData<'msg> = crate::vtable::RawVTableOptionalMutatorData<'msg, [u8]>; pub type BytesAbsentMutData<'msg> = crate::vtable::RawVTableOptionalMutatorData<'msg, [u8]>; pub type InnerBytesMut<'msg> = crate::vtable::RawVTableMutator<'msg, [u8]>; -pub type InnerPrimitiveMut<'msg, T> = crate::vtable::RawVTableMutator<'msg, T>; pub type RawMapIter = UntypedMapIterator; #[derive(Debug)] diff --git a/rust/internal.rs b/rust/internal.rs index 4a9486e91acc..742423bc1072 100644 --- a/rust/internal.rs +++ b/rust/internal.rs @@ -14,9 +14,8 @@ pub use paste::paste; pub use crate::r#enum::Enum; pub use crate::vtable::{ - new_vtable_field_entry, BytesMutVTable, BytesOptionalMutVTable, PrimitiveOptionalMutVTable, - PrimitiveVTable, PrimitiveWithRawVTable, ProxiedWithRawOptionalVTable, ProxiedWithRawVTable, - RawVTableMutator, RawVTableOptionalMutatorData, + new_vtable_field_entry, BytesMutVTable, BytesOptionalMutVTable, ProxiedWithRawOptionalVTable, + ProxiedWithRawVTable, RawVTableMutator, RawVTableOptionalMutatorData, }; pub use crate::ProtoStr; diff --git a/rust/map.rs b/rust/map.rs index 5ce74047b6aa..367793668f86 100644 --- a/rust/map.rs +++ b/rust/map.rs @@ -6,7 +6,7 @@ // https://developers.google.com/open-source/licenses/bsd use crate::{ - Mut, MutProxy, Proxied, SettableValue, View, ViewProxy, + Mut, MutProxied, MutProxy, Proxied, SettableValue, View, ViewProxy, __internal::Private, __runtime::{InnerMap, InnerMapMut, RawMap, RawMapIter}, }; @@ -95,6 +95,9 @@ where impl + ?Sized> Proxied for Map { type View<'msg> = MapView<'msg, K, V> where K: 'msg, V: 'msg; +} + +impl + ?Sized> MutProxied for Map { type Mut<'msg> = MapMut<'msg, K, V> where K: 'msg, V: 'msg; } diff --git a/rust/optional.rs b/rust/optional.rs index 0268c61bfd79..741f12d4f573 100644 --- a/rust/optional.rs +++ b/rust/optional.rs @@ -10,7 +10,9 @@ #![allow(unused)] use crate::__internal::Private; -use crate::{Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy}; +use crate::{ + Mut, MutProxied, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy, +}; use std::convert::{AsMut, AsRef}; use std::fmt::{self, Debug}; use std::panic; @@ -495,6 +497,9 @@ mod tests { impl Proxied for VtableProxied { type View<'msg> = VtableProxiedView; + } + + impl MutProxied for VtableProxied { type Mut<'msg> = VtableProxiedMut<'msg>; } diff --git a/rust/primitive.rs b/rust/primitive.rs index 7c34795c9a60..75665eca2b13 100644 --- a/rust/primitive.rs +++ b/rust/primitive.rs @@ -4,101 +4,13 @@ // 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 - -use std::fmt::Debug; - -use crate::__internal::Private; -use crate::__runtime::InnerPrimitiveMut; -use crate::vtable::{PrimitiveWithRawVTable, ProxiedWithRawVTable, RawVTableOptionalMutatorData}; -use crate::{Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy}; - -/// A mutator for a primitive (numeric or enum) value of `T`. -/// -/// This type is `protobuf::Mut<'msg, T>`. -pub struct PrimitiveMut<'msg, T> { - inner: InnerPrimitiveMut<'msg, T>, -} - -impl<'msg, T> Debug for PrimitiveMut<'msg, T> -where - T: PrimitiveWithRawVTable, -{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("PrimitiveMut").field("inner", &self.inner).finish() - } -} - -impl<'msg, T> PrimitiveMut<'msg, T> { - /// # Safety - /// `inner` must be valid and non-aliased for `T` for `'msg` - #[doc(hidden)] - pub unsafe fn from_inner(_private: Private, inner: InnerPrimitiveMut<'msg, T>) -> Self { - Self { inner } - } -} - -// SAFETY: all `T` that can perform mutations don't mutate through a shared -// reference. -unsafe impl<'msg, T> Sync for PrimitiveMut<'msg, T> {} - -impl<'msg, T> PrimitiveMut<'msg, T> -where - T: PrimitiveWithRawVTable, -{ - /// Gets the current value of the field. - pub fn get(&self) -> View<'_, T> { - T::make_view(Private, self.inner) - } - - /// Sets a new value for the field. - pub fn set(&mut self, val: impl SettableValue) { - val.set_on(Private, self.as_mut()) - } - - #[doc(hidden)] - pub fn set_primitive(&mut self, _private: Private, value: T) { - // SAFETY: the raw mutator is valid for `'msg` as enforced by `Mut` - unsafe { self.inner.set(value) } - } -} - -impl<'msg, T> ViewProxy<'msg> for PrimitiveMut<'msg, T> -where - T: PrimitiveWithRawVTable, -{ - type Proxied = T; - - fn as_view(&self) -> View<'_, Self::Proxied> { - self.get() - } - - fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> { - self.get() - } -} - -impl<'msg, T> MutProxy<'msg> for PrimitiveMut<'msg, T> -where - T: PrimitiveWithRawVTable, -{ - fn as_mut(&mut self) -> Mut<'_, Self::Proxied> { - PrimitiveMut { inner: self.inner } - } - - fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied> - where - 'msg: 'shorter, - { - self - } -} +use crate::{Proxied, View, ViewProxy}; macro_rules! impl_singular_primitives { ($($t:ty),*) => { $( impl Proxied for $t { type View<'msg> = $t; - type Mut<'msg> = PrimitiveMut<'msg, $t>; } impl<'msg> ViewProxy<'msg> for $t { @@ -113,40 +25,6 @@ macro_rules! impl_singular_primitives { } } - impl SettableValue<$t> for $t { - fn set_on<'msg>(self, private: Private, mut mutator: Mut<'msg, $t>) where $t: 'msg { - mutator.set_primitive(private, self) - } - - fn set_on_absent( - self, - _private: Private, - absent_mutator: <$t as ProxiedWithPresence>::PresentMutData<'_>, - ) -> <$t as ProxiedWithPresence>::AbsentMutData<'_> - { - absent_mutator.set(Private, self) - } - } - - impl ProxiedWithPresence for $t { - type PresentMutData<'msg> = RawVTableOptionalMutatorData<'msg, $t>; - type AbsentMutData<'msg> = RawVTableOptionalMutatorData<'msg, $t>; - - fn clear_present_field( - present_mutator: Self::PresentMutData<'_>, - ) -> Self::AbsentMutData<'_> { - present_mutator.clear(Private) - } - - fn set_absent_to_default( - absent_mutator: Self::AbsentMutData<'_>, - ) -> Self::PresentMutData<'_> { - absent_mutator.set_absent_to_default(Private) - } - } - - impl PrimitiveWithRawVTable for $t {} - // ProxiedInRepeated is implemented in {cpp,upb}.rs )* } diff --git a/rust/proto_macro.rs b/rust/proto_macro.rs index d3da60766468..95b14232bf0c 100644 --- a/rust/proto_macro.rs +++ b/rust/proto_macro.rs @@ -53,13 +53,13 @@ macro_rules! proto_internal { // nested message (@msg $msg:ident $submsg:ident : $($msgtype:ident)::+ { $field:ident : $($value:tt)* }) => { { - let mut $msg: <$($msgtype)::+ as $crate::Proxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); + let mut $msg: <$($msgtype)::+ as $crate::MutProxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); proto_internal!(@msg $msg $field : $($value)*); } }; (@msg $msg:ident $submsg:ident : ::$($msgtype:ident)::+ { $field:ident : $($value:tt)* }) => { { - let mut $msg: <::$($msgtype)::+ as $crate::Proxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); + let mut $msg: <::$($msgtype)::+ as $crate::MutProxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); proto_internal!(@msg $msg $field : $($value)*); } }; @@ -77,12 +77,12 @@ macro_rules! proto_internal { // empty nested message (@msg $msg:ident $submsg:ident : $($msgtype:ident)::+ { }) => { { - let mut $msg: <$($msgtype)::+ as $crate::Proxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); + let mut $msg: <$($msgtype)::+ as $crate::MutProxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); } }; (@msg $msg:ident $submsg:ident : ::$($msgtype:ident)::+ { }) => { { - let mut $msg: <::$($msgtype)::+ as $crate::Proxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); + let mut $msg: <::$($msgtype)::+ as $crate::MutProxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); } }; diff --git a/rust/proxied.rs b/rust/proxied.rs index 8d9214d28e4a..beef53c15d01 100644 --- a/rust/proxied.rs +++ b/rust/proxied.rs @@ -51,18 +51,25 @@ use std::fmt::Debug; /// A type that can be accessed through a reference-like proxy. /// -/// An instance of a `Proxied` can be accessed -/// immutably via `Proxied::View` and mutably via `Proxied::Mut`. +/// An instance of a `Proxied` can be accessed immutably via `Proxied::View`. /// /// All Protobuf field types implement `Proxied`. pub trait Proxied { /// The proxy type that provides shared access to a `T`, like a `&'msg T`. /// /// Most code should use the type alias [`View`]. - type View<'msg>: ViewProxy<'msg, Proxied = Self> + Copy + Send + SettableValue + type View<'msg>: ViewProxy<'msg, Proxied = Self> + Copy + Send where Self: 'msg; +} +/// A type that can be be accessed through a reference-like proxy. +/// +/// An instance of a `MutProxied` can be accessed mutably via `MutProxied::Mut` +/// and immutably via `MutProxied::View`. +/// +/// `MutProxied` is implemented by message, map and repeated field types. +pub trait MutProxied: Proxied { /// The proxy type that provides exclusive mutable access to a `T`, like a /// `&'msg mut T`. /// @@ -83,7 +90,7 @@ pub type View<'msg, T> = ::View<'msg>; /// /// This is more concise than fully spelling the associated type. #[allow(dead_code)] -pub type Mut<'msg, T> = ::Mut<'msg>; +pub type Mut<'msg, T> = ::Mut<'msg>; /// Declares conversion operations common to all views. /// @@ -127,7 +134,7 @@ pub trait ViewProxy<'msg>: 'msg + Sync + Unpin + Sized + Debug { /// y: View<'b, T>, /// ) -> [View<'b, T>; 2] /// where - /// T: Proxied, + /// T: MutProxied, /// 'a: 'b, /// { /// // `[x, y]` fails to compile because `'a` is not the same as `'b` and the `View` @@ -147,7 +154,10 @@ pub trait ViewProxy<'msg>: 'msg + Sync + Unpin + Sized + Debug { /// /// This trait is intentionally made non-object-safe to prevent a potential /// future incompatible change. -pub trait MutProxy<'msg>: ViewProxy<'msg> { +pub trait MutProxy<'msg>: ViewProxy<'msg> +where + Self::Proxied: MutProxied, +{ /// Gets an immutable view of this field. This is shorthand for `as_view`. /// /// This provides a shorter lifetime than `into_view` but can also be called @@ -211,7 +221,7 @@ pub trait MutProxy<'msg>: ViewProxy<'msg> { /// /// All scalar and message types implement `ProxiedWithPresence`, while repeated /// types don't. -pub trait ProxiedWithPresence: Proxied { +pub trait ProxiedWithPresence: MutProxied { /// The data necessary to store a present field mutator proxying `Self`. /// This is the contents of `PresentField<'msg, Self>`. type PresentMutData<'msg>: MutProxy<'msg, Proxied = Self>; @@ -233,7 +243,7 @@ pub trait ProxiedWithPresence: Proxied { /// Values that can be used to set a field of `T`. pub trait SettableValue: Sized where - T: Proxied + ?Sized, + T: MutProxied + ?Sized, { /// Consumes `self` to set the given mutator to the value of `self`. #[doc(hidden)] @@ -285,6 +295,19 @@ where } } +/// A value to `Proxied`-value conversion that consumes the input value. +/// +/// All setter functions accept types that implement `IntoProxied`. The purpose +/// of `IntoProxied` is to allow setting arbitrary values on Protobuf fields +/// with the minimal number of copies. +/// +/// This trait must not be implemented on types outside the Protobuf codegen and +/// runtime. We expect it to change in backwards incompatible ways in the +/// future. +pub trait IntoProxied { + fn into(self, _private: Private) -> T; +} + #[cfg(test)] mod tests { use super::*; @@ -308,6 +331,9 @@ mod tests { impl Proxied for MyProxied { type View<'msg> = MyProxiedView<'msg>; + } + + impl MutProxied for MyProxied { type Mut<'msg> = MyProxiedMut<'msg>; } @@ -460,7 +486,7 @@ mod tests { y: &'b View<'a, T>, ) -> [View<'b, T>; 2] where - T: Proxied, + T: MutProxied, 'a: 'b, { // `[x, y]` fails to compile because `'a` is not the same as `'b` and the `View` @@ -509,7 +535,7 @@ mod tests { fn reborrow_generic_mut_into_view<'a, 'b, T>(x: Mut<'a, T>, y: View<'b, T>) -> [View<'b, T>; 2] where - T: Proxied, + T: MutProxied, 'a: 'b, { [x.into_view(), y] @@ -529,7 +555,7 @@ mod tests { fn reborrow_generic_mut_into_mut<'a, 'b, T>(x: Mut<'a, T>, y: Mut<'b, T>) -> [Mut<'b, T>; 2] where - T: Proxied, + T: MutProxied, 'a: 'b, { // `[x, y]` fails to compile because `'a` is not the same as `'b` and the `Mut` diff --git a/rust/repeated.rs b/rust/repeated.rs index 068dd9a5eccc..7253307fcdab 100644 --- a/rust/repeated.rs +++ b/rust/repeated.rs @@ -15,7 +15,7 @@ use std::iter::FusedIterator; use std::marker::PhantomData; use crate::{ - Mut, MutProxy, Proxied, SettableValue, View, ViewProxy, + Mut, MutProxied, MutProxy, Proxied, SettableValue, View, ViewProxy, __internal::Private, __runtime::{InnerRepeated, InnerRepeatedMut, RawRepeatedField}, }; @@ -314,6 +314,12 @@ where T: ProxiedInRepeated + ?Sized, { type View<'msg> = RepeatedView<'msg, T> where Repeated: 'msg; +} + +impl MutProxied for Repeated +where + T: ProxiedInRepeated + ?Sized, +{ type Mut<'msg> = RepeatedMut<'msg, T> where Repeated: 'msg; } diff --git a/rust/shared.rs b/rust/shared.rs index 531d4d4e8277..158b87bb4039 100644 --- a/rust/shared.rs +++ b/rust/shared.rs @@ -25,10 +25,10 @@ pub mod __public { pub use crate::r#enum::UnknownEnumValue; pub use crate::map::{Map, MapIter, MapMut, MapView, ProxiedInMapValue}; pub use crate::optional::{AbsentField, FieldEntry, Optional, PresentField}; - pub use crate::primitive::PrimitiveMut; pub use crate::proto; pub use crate::proxied::{ - Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy, + IntoProxied, Mut, MutProxied, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, + ViewProxy, }; pub use crate::repeated::{ ProxiedInRepeated, Repeated, RepeatedIter, RepeatedMut, RepeatedView, diff --git a/rust/string.rs b/rust/string.rs index a6277d4b79e1..e54ec44bc02d 100644 --- a/rust/string.rs +++ b/rust/string.rs @@ -15,8 +15,8 @@ use crate::__runtime::{ }; use crate::macros::impl_forwarding_settable_value; use crate::{ - AbsentField, FieldEntry, Mut, MutProxy, Optional, PresentField, Proxied, ProxiedWithPresence, - SettableValue, View, ViewProxy, + AbsentField, FieldEntry, Mut, MutProxied, MutProxy, Optional, PresentField, Proxied, + ProxiedWithPresence, SettableValue, View, ViewProxy, }; use std::borrow::Cow; use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; @@ -123,6 +123,9 @@ impl AsRef<[u8]> for BytesMut<'_> { impl Proxied for [u8] { type View<'msg> = &'msg [u8]; +} + +impl MutProxied for [u8] { type Mut<'msg> = BytesMut<'msg>; } @@ -182,53 +185,6 @@ impl<'msg> MutProxy<'msg> for BytesMut<'msg> { } } -impl SettableValue<[u8]> for &'_ [u8] { - fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, [u8]>) - where - [u8]: 'msg, - { - // SAFETY: this is a `bytes` field with no restriction on UTF-8. - unsafe { mutator.inner.set(self) } - } - - fn set_on_absent( - self, - _private: Private, - absent_mutator: <[u8] as ProxiedWithPresence>::AbsentMutData<'_>, - ) -> <[u8] as ProxiedWithPresence>::PresentMutData<'_> { - // SAFETY: this is a `bytes` field with no restriction on UTF-8. - unsafe { absent_mutator.set(self) } - } - - fn set_on_present( - self, - _private: Private, - present_mutator: <[u8] as ProxiedWithPresence>::PresentMutData<'_>, - ) { - // SAFETY: this is a `bytes` field with no restriction on UTF-8. - unsafe { - present_mutator.set(self); - } - } -} - -impl SettableValue<[u8]> for &'_ [u8; N] { - // forward to `self[..]` - impl_forwarding_settable_value!([u8], self => &self[..]); -} - -impl SettableValue<[u8]> for Vec { - // TODO: Investigate taking ownership of this when allowed by the - // runtime. - impl_forwarding_settable_value!([u8], self => &self[..]); -} - -impl SettableValue<[u8]> for Cow<'_, [u8]> { - // TODO: Investigate taking ownership of this when allowed by the - // runtime. - impl_forwarding_settable_value!([u8], self => &self[..]); -} - impl Hash for BytesMut<'_> { fn hash(&self, state: &mut H) { self.deref().hash(state) @@ -465,6 +421,9 @@ impl Ord for ProtoStr { impl Proxied for ProtoStr { type View<'msg> = &'msg ProtoStr; +} + +impl MutProxied for ProtoStr { type Mut<'msg> = ProtoStrMut<'msg>; } @@ -695,50 +654,28 @@ impl<'msg> MutProxy<'msg> for ProtoStrMut<'msg> { } } -impl SettableValue for &'_ ProtoStr { - fn set_on<'b>(self, _private: Private, mutator: Mut<'b, ProtoStr>) - where - ProtoStr: 'b, - { - // SAFETY: A `ProtoStr` has the same UTF-8 validity requirement as the runtime. - unsafe { mutator.bytes.inner.set(self.as_bytes()) } - } - - fn set_on_absent( - self, - _private: Private, - absent_mutator: ::AbsentMutData<'_>, - ) -> ::PresentMutData<'_> { - // SAFETY: A `ProtoStr` has the same UTF-8 validity requirement as the runtime. - StrPresentMutData(unsafe { absent_mutator.0.set(self.as_bytes()) }) - } - - fn set_on_present( - self, - _private: Private, - present_mutator: ::PresentMutData<'_>, - ) { - // SAFETY: A `ProtoStr` has the same UTF-8 validity requirement as the runtime. - unsafe { - present_mutator.0.set(self.as_bytes()); - } +// TODO: remove after IntoProxied has been implemented for +// ProtoStr. +impl AsRef for String { + fn as_ref(&self) -> &ProtoStr { + ProtoStr::from_str(self.as_str()) } } -impl SettableValue for &'_ str { - impl_forwarding_settable_value!(ProtoStr, self => ProtoStr::from_str(self)); -} - -impl SettableValue for String { - // TODO: Investigate taking ownership of this when allowed by the - // runtime. - impl_forwarding_settable_value!(ProtoStr, self => ProtoStr::from_str(&self)); +// TODO: remove after IntoProxied has been implemented for +// ProtoStr. +impl AsRef for &str { + fn as_ref(&self) -> &ProtoStr { + ProtoStr::from_str(self) + } } -impl SettableValue for Cow<'_, str> { - // TODO: Investigate taking ownership of this when allowed by the - // runtime. - impl_forwarding_settable_value!(ProtoStr, self => ProtoStr::from_str(&self)); +// TODO: remove after IntoProxied has been implemented for +// ProtoStr. +impl AsRef for &ProtoStr { + fn as_ref(&self) -> &ProtoStr { + self + } } impl Hash for ProtoStrMut<'_> { diff --git a/rust/test/shared/accessors_test.rs b/rust/test/shared/accessors_test.rs index fa11b86d0734..36caf8b00ca6 100644 --- a/rust/test/shared/accessors_test.rs +++ b/rust/test/shared/accessors_test.rs @@ -507,16 +507,9 @@ fn test_singular_msg_field() { assert_that!(msg.has_optional_nested_message(), eq(false)); let mut nested_msg_mut = msg.optional_nested_message_mut(); - // test reading an int inside a mut assert_that!(nested_msg_mut.bb(), eq(0)); - // Test setting an owned NestedMessage onto another message. - let mut new_nested = NestedMessage::new(); - new_nested.set_bb(7); - nested_msg_mut.set(new_nested); - assert_that!(nested_msg_mut.bb(), eq(7)); - assert_that!(msg.has_optional_nested_message(), eq(true)); } @@ -762,18 +755,6 @@ fn test_msg_oneof_default_accessors() { // TODO: Add tests covering a message-type field in a oneof. } -#[test] -fn test_set_message_from_view() { - use protobuf::MutProxy; - - let mut m1 = TestAllTypes::new(); - m1.set_optional_int32(1); - let mut m2 = TestAllTypes::new(); - m2.as_mut().set(m1.as_view()); - - assert_that!(m2.optional_int32(), eq(1i32)); -} - #[test] fn test_group() { let mut m = TestAllTypes::new(); diff --git a/rust/upb.rs b/rust/upb.rs index 5a0c07e47156..8bca74715eb7 100644 --- a/rust/upb.rs +++ b/rust/upb.rs @@ -97,18 +97,16 @@ impl Deref for SerializedData { } } -impl fmt::Debug for SerializedData { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self.deref(), f) +// TODO: remove after IntoProxied has been implemented for bytes. +impl AsRef<[u8]> for SerializedData { + fn as_ref(&self) -> &[u8] { + self } } -impl SettableValue<[u8]> for SerializedData { - fn set_on<'msg>(self, _private: Private, mut mutator: Mut<'msg, [u8]>) - where - [u8]: 'msg, - { - mutator.set(self.as_ref()) +impl fmt::Debug for SerializedData { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.deref(), f) } } @@ -118,7 +116,6 @@ pub type MessageAbsentMutData<'msg, T> = crate::vtable::RawVTableOptionalMutator pub type BytesPresentMutData<'msg> = crate::vtable::RawVTableOptionalMutatorData<'msg, [u8]>; pub type BytesAbsentMutData<'msg> = crate::vtable::RawVTableOptionalMutatorData<'msg, [u8]>; pub type InnerBytesMut<'msg> = crate::vtable::RawVTableMutator<'msg, [u8]>; -pub type InnerPrimitiveMut<'msg, T> = crate::vtable::RawVTableMutator<'msg, T>; #[derive(Debug)] pub struct MessageVTable { diff --git a/rust/upb/arena.rs b/rust/upb/arena.rs index 8610d4de5651..6e8045cefb69 100644 --- a/rust/upb/arena.rs +++ b/rust/upb/arena.rs @@ -95,6 +95,19 @@ impl Arena { // `UPB_MALLOC_ALIGN` boundary. unsafe { slice::from_raw_parts_mut(ptr.cast(), layout.size()) } } + + /// Fuse two arenas so they share the same lifetime. + pub fn fuse(&self, other: &Arena) { + // SAFETY: `self.raw()` and `other.raw()` are both valid UPB arenas. + let success = unsafe { upb_Arena_Fuse(self.raw(), other.raw()) }; + if !success { + // Fusing can fail if any of the arenas has an initial block i.e. the arena is + // backed by a preallocated chunk of memory that it doesn't own and thus cannot + // lifetime extend. This function panics because this is typically not a + // recoverable error but a logic bug in a program. + panic!("Could not fuse two UPB arenas."); + } + } } impl Default for Arena { @@ -117,6 +130,7 @@ extern "C" { fn upb_Arena_New() -> Option; fn upb_Arena_Free(arena: RawArena); fn upb_Arena_Malloc(arena: RawArena, size: usize) -> *mut u8; + fn upb_Arena_Fuse(arena1: RawArena, arena2: RawArena) -> bool; } #[cfg(test)] diff --git a/rust/vtable.rs b/rust/vtable.rs index 52a0d87bc22d..27f14db92236 100644 --- a/rust/vtable.rs +++ b/rust/vtable.rs @@ -7,11 +7,10 @@ use crate::__internal::Private; use crate::__runtime::{ - copy_bytes_in_arena_if_needed_by_runtime, InnerPrimitiveMut, MutatorMessageRef, PtrAndLen, - RawMessage, + copy_bytes_in_arena_if_needed_by_runtime, MutatorMessageRef, PtrAndLen, RawMessage, }; use crate::{ - AbsentField, FieldEntry, Mut, MutProxy, Optional, PresentField, PrimitiveMut, Proxied, + AbsentField, FieldEntry, Mut, MutProxied, MutProxy, Optional, PresentField, ProxiedWithPresence, View, ViewProxy, }; use std::fmt::{self, Debug}; @@ -23,7 +22,7 @@ use std::ptr::NonNull; /// /// This vtable should consist of `unsafe fn`s that call thunks that operate on /// `RawMessage`. The structure of this vtable is different per proxied type. -pub trait ProxiedWithRawVTable: Proxied { +pub trait ProxiedWithRawVTable: MutProxied { /// The vtable for get/set access, stored in static memory. type VTable: Debug + 'static; @@ -281,47 +280,6 @@ impl ProxiedWithRawOptionalVTable for [u8] { } } -/// A generic thunk vtable for mutating a present primitive field. -#[doc(hidden)] -#[derive(Debug)] -pub struct PrimitiveVTable { - pub(crate) setter: unsafe extern "C" fn(msg: RawMessage, val: T), - pub(crate) getter: unsafe extern "C" fn(msg: RawMessage) -> T, -} - -#[doc(hidden)] -#[derive(Debug)] -/// A generic thunk vtable for mutating an `optional` primitive field. -pub struct PrimitiveOptionalMutVTable { - pub(crate) base: PrimitiveVTable, - pub(crate) clearer: unsafe extern "C" fn(msg: RawMessage), - pub(crate) default: T, -} - -impl PrimitiveVTable { - #[doc(hidden)] - pub const fn new( - _private: Private, - getter: unsafe extern "C" fn(msg: RawMessage) -> T, - setter: unsafe extern "C" fn(msg: RawMessage, val: T), - ) -> Self { - Self { getter, setter } - } -} - -impl PrimitiveOptionalMutVTable { - #[doc(hidden)] - pub const fn new( - _private: Private, - getter: unsafe extern "C" fn(msg: RawMessage) -> T, - setter: unsafe extern "C" fn(msg: RawMessage, val: T), - clearer: unsafe extern "C" fn(msg: RawMessage), - default: T, - ) -> Self { - Self { base: PrimitiveVTable { getter, setter }, clearer, default } - } -} - /// A generic thunk vtable for mutating a present `bytes` or `string` field. #[doc(hidden)] #[derive(Debug)] @@ -425,92 +383,3 @@ impl<'msg> RawVTableOptionalMutatorData<'msg, [u8]> { self } } - -/// Primitive types using a vtable for message access that are trivial to copy -/// and have a `'static` lifetime. -/// -/// Implementing this trait automatically implements `ProxiedWithRawVTable`, -/// `ProxiedWithRawOptionalVTable`, and get/set/clear methods on -/// `RawVTableMutator` and `RawVTableOptionalMutatorData` that use the vtable. -/// -/// It doesn't implement `Proxied`, `ViewProxy`, `SettableValue` or -/// `ProxiedWithPresence` for `Self` to avoid future conflicting blanket impls -/// on those traits. -pub trait PrimitiveWithRawVTable: - Copy - + Debug - + 'static - + ProxiedWithPresence - + Sync - + Send - + for<'msg> Proxied = Self, Mut<'msg> = PrimitiveMut<'msg, Self>> -{ -} - -impl ProxiedWithRawVTable for T { - type VTable = PrimitiveVTable; - - fn make_view(_private: Private, mut_inner: InnerPrimitiveMut<'_, Self>) -> Self { - mut_inner.get() - } - - fn make_mut(_private: Private, inner: InnerPrimitiveMut<'_, Self>) -> PrimitiveMut<'_, Self> { - // SAFETY: `inner` is valid for the necessary lifetime and `T` as promised by - // the caller of `InnerPrimitiveMut::new`. - unsafe { PrimitiveMut::from_inner(Private, inner) } - } -} - -impl ProxiedWithRawOptionalVTable for T { - type OptionalVTable = PrimitiveOptionalMutVTable; - - fn upcast_vtable( - _private: Private, - optional_vtable: &'static Self::OptionalVTable, - ) -> &'static Self::VTable { - &optional_vtable.base - } -} - -impl RawVTableMutator<'_, T> { - pub(crate) fn get(self) -> T { - // SAFETY: - // - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by - // the caller of `new`. - unsafe { (self.vtable().getter)(self.msg_ref.msg()) } - } - - /// # Safety - /// - `msg_ref` must be valid for the lifetime of `RawVTableMutator`. - pub(crate) unsafe fn set(self, val: T) { - // SAFETY: - // - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by - // the caller of `new`. - unsafe { (self.vtable().setter)(self.msg_ref.msg(), val) } - } -} - -impl<'msg, T: PrimitiveWithRawVTable> RawVTableOptionalMutatorData<'msg, T> { - pub fn set_absent_to_default(self, private: Private) -> Self { - // SAFETY: - // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as - // promised by the caller of `new`. - self.set(private, self.optional_vtable().default) - } - - pub fn set(self, _private: Private, val: T) -> Self { - // SAFETY: - // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as - // promised by the caller of `new`. - unsafe { (self.optional_vtable().base.setter)(self.msg_ref.msg(), val) } - self - } - - pub fn clear(self, _private: Private) -> Self { - // SAFETY: - // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as - // promised by the caller of `new`. - unsafe { (self.optional_vtable().clearer)(self.msg_ref.msg()) } - self - } -} diff --git a/src/google/protobuf/compiler/rust/accessors/singular_message.cc b/src/google/protobuf/compiler/rust/accessors/singular_message.cc index 8f3ea9bfe0d5..628c209355c6 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_message.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_message.cc @@ -33,6 +33,7 @@ void SingularMessage::InMsgImpl(Context& ctx, const FieldDescriptor& field, {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, {"clearer_thunk", ThunkName(ctx, field, "clear")}, {"hazzer_thunk", ThunkName(ctx, field, "has")}, + {"setter_thunk", ThunkName(ctx, field, "set")}, { "getter_body", [&] { @@ -94,7 +95,7 @@ void SingularMessage::InMsgImpl(Context& ctx, const FieldDescriptor& field, unsafe { let has = self.has_$raw_field_name$(); $pbi$::new_vtable_field_entry($pbi$::Private, - self.as_mutator_message_ref(), + self.as_mutator_message_ref($pbi$::Private), &VTABLE, has) } @@ -111,14 +112,39 @@ void SingularMessage::InMsgImpl(Context& ctx, const FieldDescriptor& field, } )rs"); }}, + {"setter_body", + [&] { + if (accessor_case == AccessorCase::VIEW) return; + if (ctx.is_upb()) { + ctx.Emit({}, R"rs( + self.as_mutator_message_ref($pbi$::Private) + .arena($pbi$::Private) + .fuse(msg.as_mutator_message_ref($pbi$::Private).arena($pbi$::Private)); + + unsafe { + $setter_thunk$(self.as_mutator_message_ref($pbi$::Private).msg(), + msg.as_mutator_message_ref($pbi$::Private).msg()); + } + )rs"); + } else { + ctx.Emit({}, R"rs( + unsafe { + $setter_thunk$(self.as_mutator_message_ref($pbi$::Private).msg(), + msg.as_mutator_message_ref($pbi$::Private).msg()); + } + )rs"); + } + }}, {"setter", [&] { if (accessor_case == AccessorCase::VIEW) return; ctx.Emit(R"rs( - pub fn set_$raw_field_name$(&mut self, val: impl $pb$::SettableValue<$msg_type$>) { - //~ TODO: Optimize this to not go through the - //~ FieldEntry. - self.$raw_field_name$_entry().set(val); + pub fn set_$raw_field_name$(&mut self, + val: impl $pb$::IntoProxied<$msg_type$>) { + let val = val.into($pbi$::Private); + let mut msg = std::mem::ManuallyDrop::new(val); + + $setter_body$ } )rs"); }}, @@ -156,6 +182,7 @@ void SingularMessage::InExternC(Context& ctx, {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, {"clearer_thunk", ThunkName(ctx, field, "clear")}, {"hazzer_thunk", ThunkName(ctx, field, "has")}, + {"setter_thunk", ThunkName(ctx, field, "set")}, {"getter_mut", [&] { if (ctx.is_cpp()) { @@ -187,12 +214,16 @@ void SingularMessage::InExternC(Context& ctx, $getter_mut$ fn $clearer_thunk$(raw_msg: $pbr$::RawMessage); fn $hazzer_thunk$(raw_msg: $pbr$::RawMessage) -> bool; + fn $setter_thunk$(raw_msg: $pbr$::RawMessage, + field_msg: $pbr$::RawMessage); )rs"); } void SingularMessage::InThunkCc(Context& ctx, const FieldDescriptor& field) const { ctx.Emit({{"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, + {"FieldMsg", cpp::QualifiedClassName(field.message_type())}, + {"setter_thunk", ThunkName(ctx, field, "set")}, {"getter_thunk", ThunkName(ctx, field, "get")}, {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, {"clearer_thunk", ThunkName(ctx, field, "clear")}, @@ -207,6 +238,9 @@ void SingularMessage::InThunkCc(Context& ctx, } void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } bool $hazzer_thunk$($QualifiedMsg$* msg) { return msg->has_$field$(); } + void $setter_thunk$($QualifiedMsg$* msg, $FieldMsg$* sub_msg) { + msg->set_allocated_$field$(sub_msg); + } )cc"); } diff --git a/src/google/protobuf/compiler/rust/accessors/singular_string.cc b/src/google/protobuf/compiler/rust/accessors/singular_string.cc index afb3592e75eb..e0917b02b7de 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_string.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_string.cc @@ -9,7 +9,6 @@ #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/rust/accessors/accessor_case.h" #include "google/protobuf/compiler/rust/accessors/accessor_generator.h" -#include "google/protobuf/compiler/rust/accessors/helpers.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/naming.h" #include "google/protobuf/descriptor.h" @@ -42,18 +41,6 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, } }) .WithSuffix(""), // This lets `$transform_view$,` work. - {"transform_field_entry", - [&] { - if (field.type() == FieldDescriptor::TYPE_STRING) { - ctx.Emit(R"rs( - $pb$::ProtoStrMut::field_entry_from_bytes( - $pbi$::Private, out - ) - )rs"); - } else { - ctx.Emit("out"); - } - }}, {"view_lifetime", ViewLifetime(accessor_case)}, {"view_self", ViewReceiver(accessor_case)}, {"getter", @@ -80,12 +67,22 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, [&] { if (accessor_case == AccessorCase::VIEW) return; ctx.Emit(R"rs( - pub fn set_$raw_field_name$(&mut self, val: impl $pb$::SettableValue<$proxied_type$>) { - //~ TODO: Optimize this to not go through the - //~ FieldEntry. - self.$raw_field_name$_mut().set(val); + // TODO: Use IntoProxied once string/bytes types support it. + pub fn set_$raw_field_name$(&mut self, val: impl std::convert::AsRef<$proxied_type$>) { + let string_view: $pbr$::PtrAndLen = + $pbr$::copy_bytes_in_arena_if_needed_by_runtime( + self.as_mutator_message_ref($pbi$::Private), + val.as_ref().into() + ).into(); + + unsafe { + $setter_thunk$( + self.as_mutator_message_ref($pbi$::Private).msg(), + string_view + ); } - )rs"); + } + )rs"); }}, {"hazzer", [&] { @@ -104,74 +101,6 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, unsafe { $clearer_thunk$(self.raw_msg()) } })rs"); }}, - {"vtable_name", VTableName(field)}, - {"vtable", - [&] { - if (accessor_case != AccessorCase::OWNED) { - return; - } - if (field.has_presence()) { - ctx.Emit({{"default_value", DefaultValue(ctx, field)}}, - R"rs( - // SAFETY: for `string` fields, the default value is verified as valid UTF-8 - const $vtable_name$: &'static $pbi$::BytesOptionalMutVTable = &unsafe { - $pbi$::BytesOptionalMutVTable::new( - $pbi$::Private, - $getter_thunk$, - $setter_thunk$, - $clearer_thunk$, - $default_value$, - ) - }; - )rs"); - } else { - ctx.Emit(R"rs( - const $vtable_name$: &'static $pbi$::BytesMutVTable = - &$pbi$::BytesMutVTable::new( - $pbi$::Private, - $getter_thunk$, - $setter_thunk$, - ); - )rs"); - } - }}, - {"field_mutator_getter", - [&] { - if (accessor_case == AccessorCase::VIEW) { - return; - } - if (field.has_presence()) { - ctx.Emit(R"rs( - fn $raw_field_name$_mut(&mut self) -> $pb$::FieldEntry<'_, $proxied_type$> { - let out = unsafe { - let has = $hazzer_thunk$(self.raw_msg()); - $pbi$::new_vtable_field_entry( - $pbi$::Private, - self.as_mutator_message_ref(), - $Msg$::$vtable_name$, - has, - ) - }; - $transform_field_entry$ - } - )rs"); - } else { - ctx.Emit(R"rs( - fn $raw_field_name$_mut(&mut self) -> $pb$::Mut<'_, $proxied_type$> { - unsafe { - <$pb$::Mut<$proxied_type$>>::from_inner( - $pbi$::Private, - $pbi$::RawVTableMutator::new( - $pbi$::Private, - self.as_mutator_message_ref(), - $Msg$::$vtable_name$, - ) - ) - } - } - )rs"); - } - }}, }, R"rs( $getter$ @@ -179,8 +108,6 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, $setter$ $hazzer$ $clearer$ - $vtable$ - $field_mutator_getter$ )rs"); } diff --git a/src/google/protobuf/compiler/rust/enum.cc b/src/google/protobuf/compiler/rust/enum.cc index 4184ed09753f..521dcd3ce3bb 100644 --- a/src/google/protobuf/compiler/rust/enum.cc +++ b/src/google/protobuf/compiler/rust/enum.cc @@ -393,7 +393,6 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { impl $pb$::Proxied for $name$ { type View<'a> = $name$; - type Mut<'a> = $pb$::PrimitiveMut<'a, $name$>; } impl $pb$::ViewProxy<'_> for $name$ { @@ -408,33 +407,6 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { } } - impl $pb$::SettableValue<$name$> for $name$ { - fn set_on<'msg>( - self, - private: $pbi$::Private, - mut mutator: $pb$::Mut<'msg, $name$> - ) where $name$: 'msg { - mutator.set_primitive(private, self) - } - } - - impl $pb$::ProxiedWithPresence for $name$ { - type PresentMutData<'a> = $pbi$::RawVTableOptionalMutatorData<'a, $name$>; - type AbsentMutData<'a> = $pbi$::RawVTableOptionalMutatorData<'a, $name$>; - - fn clear_present_field( - present_mutator: Self::PresentMutData<'_>, - ) -> Self::AbsentMutData<'_> { - present_mutator.clear($pbi$::Private) - } - - fn set_absent_to_default( - absent_mutator: Self::AbsentMutData<'_>, - ) -> Self::PresentMutData<'_> { - absent_mutator.set_absent_to_default($pbi$::Private) - } - } - unsafe impl $pb$::ProxiedInRepeated for $name$ { fn repeated_len(r: $pb$::View<$pb$::Repeated>) -> usize { $pbr$::cast_enum_repeated_view($pbi$::Private, r).len() @@ -482,8 +454,6 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { } } - impl $pbi$::PrimitiveWithRawVTable for $name$ {} - // SAFETY: this is an enum type unsafe impl $pbi$::Enum for $name$ { const NAME: &'static str = "$name$"; diff --git a/src/google/protobuf/compiler/rust/message.cc b/src/google/protobuf/compiler/rust/message.cc index 6ee718fc181c..3cbef149307b 100644 --- a/src/google/protobuf/compiler/rust/message.cc +++ b/src/google/protobuf/compiler/rust/message.cc @@ -246,33 +246,44 @@ void MessageDrop(Context& ctx, const Descriptor& msg) { )rs"); } -void MessageSettableValueForView(Context& ctx, const Descriptor& msg) { +void IntoProxiedForMessage(Context& ctx, const Descriptor& msg) { switch (ctx.opts().kernel) { case Kernel::kCpp: ctx.Emit({{"copy_from_thunk", ThunkName(ctx, msg, "copy_from")}}, R"rs( - impl<'msg> $pb$::SettableValue<$Msg$> for $Msg$View<'msg> { - fn set_on<'dst>( - self, _private: $pbi$::Private, mutator: $pb$::Mut<'dst, $Msg$>) - where $Msg$: 'dst { - unsafe { $copy_from_thunk$(mutator.inner.msg(), self.msg) }; + impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$View<'msg> { + fn into(self, _private: $pbi$::Private) -> $Msg$ { + let dst = $Msg$::new(); + unsafe { $copy_from_thunk$(dst.inner.msg, self.msg) }; + dst } } + + impl $pb$::IntoProxied<$Msg$> for $Msg$ { + fn into(self, _private: $pbi$::Private) -> $Msg$ { + self + } + } )rs"); return; case Kernel::kUpb: - // TODO: Add owned SettableValue impl for upb messages. ctx.Emit({{"minitable", UpbMinitableName(msg)}}, R"rs( - impl<'msg> $pb$::SettableValue<$Msg$> for $Msg$View<'msg> { - fn set_on<'dst>( - self, _private: $pbi$::Private, mutator: $pb$::Mut<'dst, $Msg$>) - where $Msg$: 'dst { + impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$View<'msg> { + fn into(self, _private: $pbi$::Private) -> $Msg$ { + let dst = $Msg$::new(); unsafe { $pbr$::upb_Message_DeepCopy( - mutator.inner.msg(), + dst.inner.msg, self.msg, $std$::ptr::addr_of!($minitable$), - mutator.inner.arena($pbi$::Private).raw(), + dst.inner.arena.raw(), ) }; + dst + } + } + + impl $pb$::IntoProxied<$Msg$> for $Msg$ { + fn into(self, _private: $pbi$::Private) -> $Msg$ { + self } } )rs"); @@ -817,8 +828,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { AccessorCase::MUT); } }}, - {"settable_impl_for_view", - [&] { MessageSettableValueForView(ctx, msg); }}, + {"into_proxied_impl", [&] { IntoProxiedForMessage(ctx, msg); }}, {"repeated_impl", [&] { MessageProxiedInRepeated(ctx, msg); }}, {"map_value_impl", [&] { MessageProxiedInMapValue(ctx, msg); }}, {"unwrap_upb", @@ -865,6 +875,9 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { impl $pb$::Proxied for $Msg$ { type View<'msg> = $Msg$View<'msg>; + } + + impl $pb$::MutProxied for $Msg$ { type Mut<'msg> = $Msg$Mut<'msg>; } @@ -977,17 +990,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { } } - $settable_impl_for_view$ - - impl $pb$::SettableValue<$Msg$> for $Msg$ { - fn set_on<'dst>( - self, _private: $pbi$::Private, mutator: $pb$::Mut<'dst, $Msg$>) - where $Msg$: 'dst { - //~ TODO: b/320701507 - This current will copy the message and then - //~ drop it, this copy would be avoided on upb kernel. - self.as_view().set_on($pbi$::Private, mutator); - } - } + $into_proxied_impl$ $repeated_impl$ $map_value_impl$ @@ -1030,7 +1033,8 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { self.inner.msg() } - fn as_mutator_message_ref(&mut self) -> $pbr$::MutatorMessageRef<'msg> { + pub fn as_mutator_message_ref(&mut self, _private: $pbi$::Private) + -> $pbr$::MutatorMessageRef<'msg> { self.inner } @@ -1076,7 +1080,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { self.inner.msg } - fn as_mutator_message_ref(&mut self) -> $pbr$::MutatorMessageRef { + pub fn as_mutator_message_ref(&mut self, _private: $pbi$::Private) -> $pbr$::MutatorMessageRef { $pbr$::MutatorMessageRef::new($pbi$::Private, &mut self.inner) }