Remove the now unused vtable types. In particular,

* SettableValue
 * ProxiedWithPresence
 * FieldEntry

PiperOrigin-RevId: 629363417
pull/16660/head
Jakob Buchgraber 2024-04-30 04:01:45 -07:00 committed by Copybara-Service
parent e181855abe
commit 959903d199
15 changed files with 8 additions and 1338 deletions

View File

@ -54,7 +54,6 @@ PROTOBUF_SHARED = [
"repeated.rs",
"shared.rs",
"string.rs",
"vtable.rs",
"map.rs",
"proto_macro.rs",
]

View File

@ -233,31 +233,8 @@ pub fn debug_string(_private: Private, msg: RawMessage, f: &mut fmt::Formatter<'
write!(f, "{dbg_str}")
}
pub type MessagePresentMutData<'msg, T> = crate::vtable::RawVTableOptionalMutatorData<'msg, T>;
pub type MessageAbsentMutData<'msg, T> = crate::vtable::RawVTableOptionalMutatorData<'msg, T>;
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 RawMapIter = UntypedMapIterator;
#[derive(Debug)]
pub struct MessageVTable {
pub getter: unsafe extern "C" fn(msg: RawMessage) -> RawMessage,
pub mut_getter: unsafe extern "C" fn(msg: RawMessage) -> RawMessage,
pub clearer: unsafe extern "C" fn(msg: RawMessage),
}
impl MessageVTable {
pub const fn new(
_private: Private,
getter: unsafe extern "C" fn(msg: RawMessage) -> RawMessage,
mut_getter: unsafe extern "C" fn(msg: RawMessage) -> RawMessage,
clearer: unsafe extern "C" fn(msg: RawMessage),
) -> Self {
MessageVTable { getter, mut_getter, clearer }
}
}
/// The raw contents of every generated message.
#[derive(Debug)]
pub struct MessageInner {

View File

@ -13,10 +13,6 @@
pub use paste::paste;
pub use crate::r#enum::Enum;
pub use crate::vtable::{
new_vtable_field_entry, ProxiedWithRawOptionalVTable, ProxiedWithRawVTable, RawVTableMutator,
RawVTableOptionalMutatorData,
};
pub use crate::ProtoStr;
// TODO: Temporarily re-export these symbols which are now under

View File

@ -6,7 +6,7 @@
// https://developers.google.com/open-source/licenses/bsd
use crate::{
Mut, MutProxied, MutProxy, Proxied, SettableValue, View, ViewProxy,
Mut, MutProxied, MutProxy, Proxied, View, ViewProxy,
__internal::Private,
__runtime::{InnerMap, InnerMapMut, RawMap, RawMapIter},
};
@ -101,17 +101,6 @@ impl<K: Proxied + ?Sized, V: ProxiedInMapValue<K> + ?Sized> MutProxied for Map<K
type Mut<'msg> = MapMut<'msg, K, V> where K: 'msg, V: 'msg;
}
impl<'msg, K: Proxied + ?Sized, V: ProxiedInMapValue<K> + ?Sized> SettableValue<Map<K, V>>
for MapView<'msg, K, V>
{
fn set_on<'b>(self, _private: Private, mut mutator: Mut<'b, Map<K, V>>)
where
Map<K, V>: 'b,
{
mutator.copy_from(self);
}
}
impl<'msg, K: Proxied + ?Sized, V: ProxiedInMapValue<K> + ?Sized> ViewProxy<'msg>
for MapView<'msg, K, V>
{

View File

@ -10,9 +10,7 @@
#![allow(unused)]
use crate::__internal::Private;
use crate::{
Mut, MutProxied, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy,
};
use crate::{Mut, MutProxied, MutProxy, Proxied, View, ViewProxy};
use std::convert::{AsMut, AsRef};
use std::fmt::{self, Debug};
use std::panic;
@ -23,9 +21,6 @@ use std::ptr;
/// This can be pattern matched with `match` or `if let` to determine if the
/// field is set and access the field data.
///
/// [`FieldEntry`], a specific type alias for `Optional`, provides much of the
/// functionality for this type.
///
/// Two `Optional`s are equal if they match both presence and the field values.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Optional<SetVal, UnsetVal = SetVal> {
@ -82,673 +77,3 @@ impl<T> From<Optional<T>> for Option<T> {
x.into_option()
}
}
/// A mutable view into the value of an optional field, which may be set or
/// unset.
pub type FieldEntry<'msg, T> = Optional<PresentField<'msg, T>, AbsentField<'msg, T>>;
/// Methods for `_mut()` accessors of optional types.
///
/// The most common methods are [`set`] and [`or_default`].
impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> FieldEntry<'msg, T> {
// is_set() is provided by `impl<T, A> Optional<T, A>`
/// Gets a mutator for this field. Sets to the default value if not set.
pub fn or_default(self) -> Mut<'msg, T> {
match self {
Optional::Set(x) => x.into_mut(),
Optional::Unset(x) => x.set_default().into_mut(),
}
}
/// Gets a mutator for this field. Sets to the given `val` if not set.
///
/// If the field is already set, `val` is ignored.
pub fn or_set(self, val: impl SettableValue<T>) -> Mut<'msg, T> {
self.or_set_with(move || val)
}
/// Gets a mutator for this field. Sets using the given `val` function if
/// not set.
///
/// If the field is already set, `val` is not invoked.
pub fn or_set_with<S>(self, val: impl FnOnce() -> S) -> Mut<'msg, T>
where
S: SettableValue<T>,
{
match self {
Optional::Set(x) => x.into_mut(),
Optional::Unset(x) => x.set(val()).into_mut(),
}
}
/// Sets the value of this field to `val`.
///
/// Equivalent to `self.or_default().set(val)`, but does not consume `self`.
///
/// `set` has the same parameters as in [`MutProxy`], so making a field
/// `optional` will switch to using this method. This makes transitioning
/// from implicit to explicit presence easier.
pub fn set(&mut self, val: impl SettableValue<T>) {
transform_mut(self, |mut self_| match self_ {
Optional::Set(ref mut present) => {
present.set(val);
self_
}
Optional::Unset(absent) => Optional::Set(absent.set(val)),
})
}
/// Clears the field; `is_set()` will return `false`.
pub fn clear(&mut self) {
transform_mut(self, |self_| match self_ {
Optional::Set(present) => Optional::Unset(present.clear()),
absent => absent,
})
}
/// Gets an immutable view of this field, using its default value if not
/// set. This is shorthand for `as_view`.
///
/// This provides a shorter lifetime than `into_view` but can also be called
/// multiple times - if the result of `get` is not living long enough
/// for your use, use that instead.
///
/// `get` has the same parameters as in [`MutProxy`], so making a field
/// `optional` will switch to using this method. This makes transitioning
/// from implicit to explicit presence easier.
pub fn get(&self) -> View<'_, T> {
self.as_view()
}
/// Converts to an immutable view of this optional field, preserving the
/// field's presence.
pub fn into_optional_view(self) -> Optional<View<'msg, T>> {
let is_set = self.is_set();
Optional::new(self.into_view(), is_set)
}
/// Returns a field mutator if the field is set.
///
/// Returns `None` if the field is not set. This does not affect `is_set()`.
///
/// This returns `Option` and _not_ `Optional` since returning a defaulted
/// `Mut` would require mutating the presence of the field - for that
/// behavior, use `or_default()`.
pub fn try_into_mut(self) -> Option<Mut<'msg, T>> {
match self {
Optional::Set(x) => Some(x.into_mut()),
Optional::Unset(_) => None,
}
}
}
impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> ViewProxy<'msg> for FieldEntry<'msg, T> {
type Proxied = T;
fn as_view(&self) -> View<'_, T> {
match self {
Optional::Set(x) => x.as_view(),
Optional::Unset(x) => x.as_view(),
}
}
fn into_view<'shorter>(self) -> View<'shorter, T>
where
'msg: 'shorter,
{
match self {
Optional::Set(x) => x.into_view(),
Optional::Unset(x) => x.into_view(),
}
}
}
// `MutProxy` not implemented for `FieldEntry` since the field may not be set,
// and `as_mut`/`into_mut` should not insert.
/// A field mutator capable of clearing that is statically known to point to a
/// set field.
pub struct PresentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
pub(crate) inner: T::PresentMutData<'msg>,
}
impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> Debug for PresentField<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> PresentField<'msg, T> {
#[doc(hidden)]
pub fn from_inner(_private: Private, inner: T::PresentMutData<'msg>) -> Self {
Self { inner }
}
/// Gets an immutable view of this present field. This is shorthand for
/// `as_view`.
///
/// This provides a shorter lifetime than `into_view` but can also be called
/// multiple times - if the result of `get` is not living long enough
/// for your use, use that instead.
pub fn get(&self) -> View<'_, T> {
self.as_view()
}
pub fn set(&mut self, val: impl SettableValue<T>) {
val.set_on(Private, self.as_mut())
}
/// See [`FieldEntry::clear`].
pub fn clear(mut self) -> AbsentField<'msg, T> {
AbsentField { inner: T::clear_present_field(self.inner) }
}
// This cannot provide `reborrow` - `clear` consumes after setting the field
// because it would violate a condition of `PresentField` - the field being set.
}
impl<'msg, T> ViewProxy<'msg> for PresentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
type Proxied = T;
fn as_view(&self) -> View<'_, T> {
self.inner.as_view()
}
fn into_view<'shorter>(self) -> View<'shorter, T>
where
'msg: 'shorter,
{
self.inner.into_view()
}
}
impl<'msg, T> MutProxy<'msg> for PresentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
fn as_mut(&mut self) -> Mut<'_, T> {
self.inner.as_mut()
}
fn into_mut<'shorter>(self) -> Mut<'shorter, T>
where
'msg: 'shorter,
{
self.inner.into_mut()
}
}
/// A field mutator capable of setting that is statically known to point to a
/// non-set field.
pub struct AbsentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
pub(crate) inner: T::AbsentMutData<'msg>,
}
impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> Debug for AbsentField<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<'msg, T: ProxiedWithPresence + ?Sized> AbsentField<'msg, T> {
#[doc(hidden)]
pub fn from_inner(_private: Private, inner: T::AbsentMutData<'msg>) -> Self {
Self { inner }
}
/// Gets the default value for this unset field.
///
/// This is the same value that the primitive accessor would provide, though
/// with the shorter lifetime of `as_view`.
pub fn default_value(&self) -> View<'_, T> {
self.as_view()
}
/// See [`FieldEntry::set`]. Note that this consumes and returns a
/// `PresentField`.
pub fn set(self, val: impl SettableValue<T>) -> PresentField<'msg, T> {
PresentField { inner: val.set_on_absent(Private, self.inner) }
}
/// Sets this absent field to its default value.
pub fn set_default(self) -> PresentField<'msg, T> {
PresentField { inner: T::set_absent_to_default(self.inner) }
}
// This cannot provide `reborrow` - `set` consumes after setting the field
// because it would violate a condition of `AbsentField` - the field being
// unset.
}
impl<'msg, T> ViewProxy<'msg> for AbsentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
type Proxied = T;
fn as_view(&self) -> View<'_, T> {
self.inner.as_view()
}
fn into_view<'shorter>(self) -> View<'shorter, T>
where
'msg: 'shorter,
{
self.inner.into_view()
}
}
/// Transforms a mutable reference in-place, treating it as if it were owned.
///
/// The program will abort if `transform` panics.
///
/// This is the same operation as provided by [`take_mut::take`].
///
/// [`take_mut::take`]: https://docs.rs/take_mut/latest/take_mut/fn.take.html
fn transform_mut<T>(mut_ref: &mut T, transform: impl FnOnce(T) -> T) {
#[cold]
#[inline(never)]
fn panicked_in_transform_mut() -> ! {
use std::io::Write as _;
let backtrace = std::backtrace::Backtrace::force_capture();
let stderr = std::io::stderr();
let mut stderr = stderr.lock();
let _ = write!(&mut stderr, "BUG: A protobuf mutator panicked! Backtrace:\n{backtrace}\n");
let _ = stderr.flush();
std::process::abort()
}
// https://play.rust-lang.org/?edition=2021&gist=f3014e1f209013f0a38352e211f4a240
// provides a sample test to confirm this operation is sound in Miri.
// SAFETY:
// - `old_t` is not dropped without also replacing `*mut_ref`, preventing a
// double-free.
// - If `transform` panics, the process aborts since `*mut_ref` has no possible
// valid value.
// - After `ptr::write`, a valid `T` is located at `*mut_ref`
unsafe {
let p: *mut T = mut_ref;
let old_t = p.read();
let new_t = panic::catch_unwind(panic::AssertUnwindSafe(move || transform(old_t)))
.unwrap_or_else(|_| panicked_in_transform_mut());
p.write(new_t);
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::borrow::Cow;
/// A sample message with custom presence bits, meant to mirror a C++
/// message.
#[derive(Default, Debug)]
struct MyMessage {
/// has a default of `0`
a: i32,
/// has a default of `5`
b: i32,
/// Packed presence bitfield for `a` and `b`
presence: u8,
}
impl MyMessage {
fn a(&self) -> View<'_, VtableProxied> {
VtableProxiedView { val: get_a(self) }
}
fn a_opt(&self) -> Optional<View<'_, VtableProxied>> {
Optional::new(self.a(), has_a(self))
}
fn a_mut(&mut self) -> FieldEntry<'_, VtableProxied> {
static A_VTABLE: ProxyVtable =
ProxyVtable { get: get_a, set: set_a, clear: clear_a, has: has_a };
make_field_entry(self, &A_VTABLE)
}
fn b(&self) -> View<'_, VtableProxied> {
VtableProxiedView { val: get_b(self) }
}
fn b_opt(&self) -> Optional<View<'_, VtableProxied>> {
Optional::new(self.b(), has_b(self))
}
fn b_mut(&mut self) -> FieldEntry<'_, VtableProxied> {
static B_VTABLE: ProxyVtable =
ProxyVtable { get: get_b, set: set_b, clear: clear_b, has: has_b };
make_field_entry(self, &B_VTABLE)
}
}
fn make_field_entry<'msg>(
msg: &'msg mut MyMessage,
vtable: &'msg ProxyVtable,
) -> FieldEntry<'msg, VtableProxied> {
if (vtable.has)(&*msg) {
Optional::Set(PresentField::from_inner(Private, VtableProxiedMut { msg, vtable }))
} else {
Optional::Unset(AbsentField::from_inner(Private, VtableProxiedMut { msg, vtable }))
}
}
// Thunks used for the vtable. For a C++ message these would be defined in C++
// and exported via a C API
const A_BIT: u8 = 0;
const B_BIT: u8 = 1;
fn get_a(msg: &MyMessage) -> i32 {
if has_a(msg) { msg.a } else { 0 }
}
fn get_b(msg: &MyMessage) -> i32 {
if has_b(msg) { msg.b } else { 5 }
}
fn set_a(msg: &mut MyMessage, val: i32) {
msg.presence |= (1 << A_BIT);
msg.a = val;
}
fn set_b(msg: &mut MyMessage, val: i32) {
msg.presence |= (1 << B_BIT);
msg.b = val;
}
fn clear_a(msg: &mut MyMessage) {
msg.presence &= !(1 << A_BIT);
}
fn clear_b(msg: &mut MyMessage) {
msg.presence &= !(1 << B_BIT);
}
fn has_a(msg: &MyMessage) -> bool {
msg.presence & (1 << A_BIT) != 0
}
fn has_b(msg: &MyMessage) -> bool {
msg.presence & (1 << B_BIT) != 0
}
#[derive(Debug)]
struct ProxyVtable {
get: fn(&MyMessage) -> i32,
set: fn(&mut MyMessage, val: i32),
clear: fn(&mut MyMessage),
has: fn(&MyMessage) -> bool,
}
/// A proxy for a `i32` that is accessed through methods on a vtable.
struct VtableProxied;
impl Proxied for VtableProxied {
type View<'msg> = VtableProxiedView;
}
impl MutProxied for VtableProxied {
type Mut<'msg> = VtableProxiedMut<'msg>;
}
impl ProxiedWithPresence for VtableProxied {
// In this case, the `PresentMutData` and `AbsentMutData` are identical to the
// `Mut` in layout. Other types/runtimes could require otherwise, e.g. `Mut`
// could be defined to only have get/set functions in its vtable, and not
// has/clear.
type PresentMutData<'msg> = VtableProxiedMut<'msg>;
type AbsentMutData<'msg> = VtableProxiedMut<'msg>;
fn clear_present_field<'msg>(
present_mutator: Self::PresentMutData<'msg>,
) -> Self::AbsentMutData<'msg> {
(present_mutator.vtable.clear)(&mut *present_mutator.msg);
present_mutator
}
fn set_absent_to_default<'msg>(
absent_mutator: Self::AbsentMutData<'msg>,
) -> Self::PresentMutData<'msg> {
SettableValue::<VtableProxied>::set_on_absent(
absent_mutator.as_view().val(),
Private,
absent_mutator,
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct VtableProxiedView {
val: i32,
}
impl VtableProxiedView {
fn val(&self) -> i32 {
self.val
}
fn read(msg: &MyMessage, vtable: &ProxyVtable) -> Self {
VtableProxiedView { val: (vtable.get)(msg) }
}
}
impl<'msg> ViewProxy<'msg> for VtableProxiedView {
type Proxied = VtableProxied;
fn as_view(&self) -> View<'msg, VtableProxied> {
*self
}
fn into_view<'shorter>(self) -> View<'shorter, VtableProxied>
where
'msg: 'shorter,
{
self
}
}
#[derive(Debug)]
struct VtableProxiedMut<'msg> {
msg: &'msg mut MyMessage,
vtable: &'msg ProxyVtable,
}
impl<'msg> ViewProxy<'msg> for VtableProxiedMut<'msg> {
type Proxied = VtableProxied;
fn as_view(&self) -> View<'_, VtableProxied> {
VtableProxiedView::read(self.msg, self.vtable)
}
fn into_view<'shorter>(self) -> View<'shorter, VtableProxied>
where
'msg: 'shorter,
{
VtableProxiedView::read(self.msg, self.vtable)
}
}
impl<'msg> MutProxy<'msg> for VtableProxiedMut<'msg> {
fn as_mut(&mut self) -> Mut<'_, VtableProxied> {
VtableProxiedMut { msg: self.msg, vtable: self.vtable }
}
fn into_mut<'shorter>(self) -> Mut<'shorter, VtableProxied>
where
'msg: 'shorter,
{
self
}
}
impl SettableValue<VtableProxied> for View<'_, VtableProxied> {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, VtableProxied>)
where
VtableProxied: 'msg,
{
SettableValue::<VtableProxied>::set_on(self.val(), Private, mutator)
}
fn set_on_absent<'msg>(
self,
_private: Private,
absent_mutator: <VtableProxied as ProxiedWithPresence>::AbsentMutData<'msg>,
) -> <VtableProxied as ProxiedWithPresence>::PresentMutData<'msg> {
SettableValue::<VtableProxied>::set_on_absent(self.val(), Private, absent_mutator)
}
}
impl SettableValue<VtableProxied> for i32 {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, VtableProxied>)
where
VtableProxied: 'msg,
{
(mutator.vtable.set)(mutator.msg, self)
}
fn set_on_absent<'msg>(
self,
_private: Private,
absent_mutator: <VtableProxied as ProxiedWithPresence>::AbsentMutData<'msg>,
) -> <VtableProxied as ProxiedWithPresence>::PresentMutData<'msg> {
(absent_mutator.vtable.set)(absent_mutator.msg, self);
absent_mutator
}
}
#[test]
fn test_field_entry() {
use googletest::prelude::*;
let mut m1 = MyMessage::default();
let mut m2 = MyMessage::default();
let mut m1_a = m1.a_mut();
assert_that!(m1_a, matches_pattern!(Optional::Unset(_)));
assert_that!(m1_a.as_view().val(), eq(0));
assert_that!(m2.b().val(), eq(5));
let mut m2_b = m2.b_mut();
assert_that!(m2_b.is_unset(), eq(true));
assert_that!(m2_b.as_view().val(), eq(5));
m2_b.set(10);
assert_that!(m2_b.is_set(), eq(true));
assert_that!(m2_b, matches_pattern!(Optional::Set(_)));
assert_that!(m2_b.as_view().val(), eq(10));
assert_that!(m1_a.or_default().as_view().val(), eq(0));
assert_that!(m1.a_opt(), eq(Optional::Set(VtableProxiedView { val: 0 })));
m1.a_mut().clear();
assert_that!(m1.a().val(), eq(0));
assert_that!(m1.b().val(), eq(5));
assert_that!(m2.a().val(), eq(0));
assert_that!(m2.b().val(), eq(10));
}
#[test]
fn test_or_set() {
use googletest::prelude::*;
let mut m1 = MyMessage::default();
let mut m2 = MyMessage::default();
assert_that!(m1.a_mut().or_set(10).get().val(), eq(10));
assert_that!(m1.a_opt(), eq(Optional::Set(VtableProxiedView { val: 10 })));
assert_that!(m1.a_mut().or_set(20).get().val(), eq(10));
assert_that!(m1.a_opt(), eq(Optional::Set(VtableProxiedView { val: 10 })));
assert_that!(m2.a_mut().or_set_with(|| m1.a().val() + m1.b().val()).get().val(), eq(15));
assert_that!(m2.a_opt(), eq(Optional::Set(VtableProxiedView { val: 15 })));
assert_that!(m2.a_mut().or_set_with(|| None::<i32>.unwrap()).get().val(), eq(15));
assert_that!(m2.a_opt(), eq(Optional::Set(VtableProxiedView { val: 15 })));
}
#[test]
fn test_into_optional_view() {
use googletest::prelude::*;
let mut m1 = MyMessage::default();
assert_that!(
m1.a_mut().into_optional_view(),
eq(Optional::Unset(VtableProxiedView { val: 0 }))
);
m1.a_mut().set(10);
assert_that!(
m1.a_mut().into_optional_view(),
eq(Optional::Set(VtableProxiedView { val: 10 }))
);
assert_that!(
m1.b_mut().into_optional_view(),
eq(Optional::Unset(VtableProxiedView { val: 5 }))
);
}
#[test]
fn test_try_into_mut() {
use googletest::prelude::*;
let mut m1 = MyMessage::default();
assert_that!(m1.a_mut().try_into_mut().is_none(), eq(true));
m1.a_mut().set(10);
let mut a_mut = m1.a_mut().try_into_mut().expect("field to be set");
a_mut.set(20);
assert_that!(m1.a().val(), eq(20));
}
#[test]
fn test_present_field() {
use googletest::prelude::*;
let mut m = MyMessage::default();
m.a_mut().set(10);
match m.a_mut() {
Optional::Set(mut present) => {
assert_that!(present.as_view().val(), eq(10));
present.set(20);
assert_that!(present.as_view().val(), eq(20));
present.into_mut().set(30);
}
Optional::Unset(_) => unreachable!(),
}
assert_that!(m.a_opt(), eq(Optional::Set(VtableProxiedView { val: 30 })));
m.b_mut().set(20);
match m.b_mut() {
Optional::Set(present) => present.clear(),
Optional::Unset(_) => unreachable!(),
};
assert_that!(m.b_opt(), eq(Optional::Unset(VtableProxiedView { val: 5 })));
}
#[test]
fn test_absent_field() {
use googletest::prelude::*;
let mut m = MyMessage::default();
match m.a_mut() {
Optional::Set(_) => unreachable!(),
Optional::Unset(absent) => {
assert_that!(absent.as_view().val(), eq(0));
absent.set(20);
}
}
assert_that!(m.a_opt(), eq(Optional::Set(VtableProxiedView { val: 20 })));
match m.b_mut() {
Optional::Set(_) => unreachable!(),
Optional::Unset(absent) => {
assert_that!(absent.as_view().val(), eq(5));
absent.set_default();
}
}
assert_that!(m.b_opt(), eq(Optional::Set(VtableProxiedView { val: 5 })));
}
}

View File

@ -44,9 +44,7 @@
//! implemented the concept of "proxy" types. Proxy types are a reference-like
//! indirection between the user and the internal memory representation.
use crate::RepeatedMut;
use crate::__internal::Private;
use crate::repeated::ProxiedInRepeated;
use std::fmt::Debug;
/// A type that can be accessed through a reference-like proxy.
@ -167,13 +165,6 @@ where
self.as_view()
}
/// Sets this field to the given `val`.
///
/// Any borrowed data from `val` will be cloned.
fn set(&mut self, val: impl SettableValue<Self::Proxied>) {
val.set_on(Private, self.as_mut())
}
/// Converts a borrow into a `Mut` with the lifetime of that borrow.
///
/// This function enables calling multiple methods consuming `self`, for
@ -216,85 +207,6 @@ where
'msg: 'shorter;
}
// TODO: move this to `optional.rs` as it's only used for optionals
/// `Proxied` types that can be optionally set or unset.
///
/// All scalar and message types implement `ProxiedWithPresence`, while repeated
/// types don't.
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>;
/// The data necessary to store an absent field mutator proxying `Self`.
/// This is the contents of `AbsentField<'msg, Self>`.
type AbsentMutData<'msg>: ViewProxy<'msg, Proxied = Self>;
/// Clears a present field.
fn clear_present_field(present_mutator: Self::PresentMutData<'_>) -> Self::AbsentMutData<'_>;
/// Sets an absent field to its default value.
///
/// This can be more efficient than setting with a default value, e.g.
/// a default submessage could share resources with the parent message.
fn set_absent_to_default(absent_mutator: Self::AbsentMutData<'_>) -> Self::PresentMutData<'_>;
}
/// Values that can be used to set a field of `T`.
pub trait SettableValue<T>: Sized
where
T: MutProxied + ?Sized,
{
/// Consumes `self` to set the given mutator to the value of `self`.
#[doc(hidden)]
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, T>)
where
T: 'msg;
/// Consumes `self` and `absent_mutator` to set the given empty field to
/// the value of `self`.
#[doc(hidden)]
fn set_on_absent(
self,
_private: Private,
absent_mutator: T::AbsentMutData<'_>,
) -> T::PresentMutData<'_>
where
T: ProxiedWithPresence,
{
let mut present = T::set_absent_to_default(absent_mutator);
self.set_on(Private, present.as_mut());
present
}
/// Consumes `self` and `present_mutator` to set the given present field
/// to the value of `self`.
#[doc(hidden)]
fn set_on_present(self, _private: Private, mut present_mutator: T::PresentMutData<'_>)
where
T: ProxiedWithPresence,
{
self.set_on(Private, present_mutator.as_mut())
}
/// Consumes `self` and `repeated_mutator` to set the value at the
/// given index to the value of `self`.
///
/// # Safety
/// `index` must be less than `repeated_mutator.len()`
#[doc(hidden)]
unsafe fn set_on_repeated_unchecked(
self,
_private: Private,
mut _repeated_mutator: RepeatedMut<T>,
_index: usize,
) where
T: ProxiedInRepeated,
{
unimplemented!()
}
}
/// A value to `Proxied`-value conversion that consumes the input value.
///
/// All setter functions accept types that implement `IntoProxied`. The purpose
@ -395,45 +307,6 @@ mod tests {
}
}
impl SettableValue<MyProxied> for MyProxiedView<'_> {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, MyProxied>)
where
MyProxied: 'msg,
{
mutator.my_proxied_ref.val = self.my_proxied_ref.val.clone();
}
}
impl SettableValue<MyProxied> for String {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, MyProxied>)
where
MyProxied: 'msg,
{
mutator.my_proxied_ref.val = self;
}
}
impl SettableValue<MyProxied> for &'_ str {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, MyProxied>)
where
MyProxied: 'msg,
{
mutator.my_proxied_ref.val.replace_range(.., self);
}
}
impl SettableValue<MyProxied> for Cow<'_, str> {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, MyProxied>)
where
MyProxied: 'msg,
{
match self {
Cow::Owned(x) => <String as SettableValue<MyProxied>>::set_on(x, Private, mutator),
Cow::Borrowed(x) => <&str as SettableValue<MyProxied>>::set_on(x, Private, mutator),
}
}
}
#[test]
fn test_as_view() {
let my_proxied = MyProxied { val: "Hello World".to_string() };
@ -443,18 +316,6 @@ mod tests {
assert_that!(my_view.val(), eq(&my_proxied.val));
}
#[test]
fn test_as_mut() {
let mut my_proxied = MyProxied { val: "Hello World".to_string() };
let mut my_mut = my_proxied.as_mut();
my_mut.set("Hello indeed".to_string());
let val_after_set = my_mut.as_view().val().to_string();
assert_that!(my_proxied.val, eq(val_after_set));
assert_that!(my_proxied.val, eq("Hello indeed"));
}
fn reborrow_mut_into_view<'msg>(x: Mut<'msg, MyProxied>) -> View<'msg, MyProxied> {
// x.as_view() fails to compile with:
// `ERROR: attempt to return function-local borrowed content`
@ -578,17 +439,4 @@ mod tests {
reborrow_generic_mut_into_mut::<MyProxied>(my_mut, other_mut);
}
}
#[test]
fn test_set() {
let mut my_proxied = MyProxied::default();
my_proxied.as_mut().set("hello");
assert_that!(my_proxied.as_view().val(), eq("hello"));
my_proxied.as_mut().set(String::from("hello2"));
assert_that!(my_proxied.as_view().val(), eq("hello2"));
my_proxied.as_mut().set(Cow::Borrowed("hello3"));
assert_that!(my_proxied.as_view().val(), eq("hello3"));
}
}

View File

@ -15,7 +15,7 @@ use std::iter::FusedIterator;
use std::marker::PhantomData;
use crate::{
Mut, MutProxied, MutProxy, Proxied, SettableValue, View, ViewProxy,
Mut, MutProxied, MutProxy, Proxied, View, ViewProxy,
__internal::Private,
__runtime::{InnerRepeated, InnerRepeatedMut, RawRepeatedField},
};
@ -375,18 +375,6 @@ where
}
}
impl<'msg, T> SettableValue<Repeated<T>> for RepeatedView<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,
{
fn set_on<'b>(self, _private: Private, mutator: Mut<'b, Repeated<T>>)
where
Repeated<T>: 'b,
{
T::repeated_copy_from(self, mutator)
}
}
impl<'msg, T> iter::Iterator for RepeatedIter<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,

View File

@ -24,12 +24,9 @@ use std::fmt;
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::optional::Optional;
pub use crate::proto;
pub use crate::proxied::{
IntoProxied, Mut, MutProxied, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View,
ViewProxy,
};
pub use crate::proxied::{IntoProxied, Mut, MutProxied, MutProxy, Proxied, View, ViewProxy};
pub use crate::repeated::{
ProxiedInRepeated, Repeated, RepeatedIter, RepeatedMut, RepeatedView,
};
@ -63,7 +60,6 @@ mod proto_macro;
mod proxied;
mod repeated;
mod string;
mod vtable;
/// An error that happened during deserialization.
#[derive(Debug, Clone)]

View File

@ -10,13 +10,8 @@
#![allow(unused)]
use crate::__internal::Private;
use crate::__runtime::{
BytesAbsentMutData, BytesPresentMutData, InnerBytesMut, PtrAndLen, RawMessage,
};
use crate::{
AbsentField, FieldEntry, Mut, MutProxied, MutProxy, Optional, PresentField, Proxied,
ProxiedWithPresence, SettableValue, View, ViewProxy,
};
use crate::__runtime::{PtrAndLen, RawMessage};
use crate::{Mut, MutProxied, MutProxy, Optional, Proxied, View, ViewProxy};
use std::borrow::Cow;
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use std::convert::{AsMut, AsRef};

View File

@ -14,35 +14,7 @@
# Once we have a couple of these tests we will investigate ways to remove boilerplate (for example
# by introducing a build macro that registers 2 rust_test targets).
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
rust_library(
name = "matchers_upb",
testonly = True,
srcs = ["matchers.rs"],
aliases = {
"//rust:protobuf_upb_export": "protobuf",
},
visibility = ["//rust/test/shared:__subpackages__"],
deps = [
"//rust:protobuf_upb_export",
"@crate_index//:googletest",
],
)
rust_library(
name = "matchers_cpp",
testonly = True,
srcs = ["matchers.rs"],
aliases = {
"//rust:protobuf_cpp_export": "protobuf",
},
visibility = ["//rust/test/shared:__subpackages__"],
deps = [
"//rust:protobuf_cpp_export",
"@crate_index//:googletest",
],
)
load("@rules_rust//rust:defs.bzl", "rust_test")
rust_test(
name = "child_parent_upb_test",
@ -197,7 +169,6 @@ rust_test(
srcs = ["accessors_test.rs"],
aliases = {
"//rust:protobuf_cpp_export": "protobuf",
"//rust/test/shared:matchers_cpp": "matchers",
},
proc_macro_deps = [
"@crate_index//:paste",
@ -205,7 +176,6 @@ rust_test(
deps = [
"//rust:protobuf_cpp_export",
"//rust/test:unittest_cc_rust_proto",
"//rust/test/shared:matchers_cpp",
"@crate_index//:googletest",
],
)
@ -215,7 +185,6 @@ rust_test(
srcs = ["accessors_test.rs"],
aliases = {
"//rust:protobuf_upb_export": "protobuf",
"//rust/test/shared:matchers_upb": "matchers",
},
proc_macro_deps = [
"@crate_index//:paste",
@ -223,7 +192,6 @@ rust_test(
deps = [
"//rust:protobuf_upb_export",
"//rust/test:unittest_upb_rust_proto",
"//rust/test/shared:matchers_upb",
"@crate_index//:googletest",
],
)
@ -233,13 +201,11 @@ rust_test(
srcs = ["accessors_proto3_test.rs"],
aliases = {
"//rust:protobuf_cpp_export": "protobuf",
"//rust/test/shared:matchers_cpp": "matchers",
},
deps = [
"//rust:protobuf_cpp_export",
"//rust/test:unittest_proto3_cc_rust_proto",
"//rust/test:unittest_proto3_optional_cc_rust_proto",
"//rust/test/shared:matchers_cpp",
"@crate_index//:googletest",
],
)
@ -249,13 +215,11 @@ rust_test(
srcs = ["accessors_proto3_test.rs"],
aliases = {
"//rust:protobuf_upb_export": "protobuf",
"//rust/test/shared:matchers_upb": "matchers",
},
deps = [
"//rust:protobuf_upb_export",
"//rust/test:unittest_proto3_optional_upb_rust_proto",
"//rust/test:unittest_proto3_upb_rust_proto",
"//rust/test/shared:matchers_upb",
"@crate_index//:googletest",
],
)
@ -407,12 +371,10 @@ rust_test(
srcs = ["proto_macro_test.rs"],
aliases = {
"//rust:protobuf_cpp": "protobuf",
"//rust/test/shared:matchers_cpp": "matchers",
},
deps = [
"//rust:protobuf_cpp",
"//rust/test:unittest_cc_rust_proto",
"//rust/test/shared:matchers_cpp",
"@crate_index//:googletest",
],
)
@ -422,12 +384,10 @@ rust_test(
srcs = ["proto_macro_test.rs"],
aliases = {
"//rust:protobuf_upb": "protobuf",
"//rust/test/shared:matchers_upb": "matchers",
},
deps = [
"//rust:protobuf_upb",
"//rust/test:unittest_upb_rust_proto",
"//rust/test/shared:matchers_upb",
"@crate_index//:googletest",
],
)

View File

@ -1,59 +0,0 @@
use googletest::description::Description;
use googletest::matcher::MatcherResult;
use googletest::prelude::*;
use protobuf::{AbsentField, Optional, PresentField, ProxiedWithPresence};
use std::marker::PhantomData;
/// ===============================
/// IS_UNSET
/// ===============================
pub fn is_unset<'a, T: std::fmt::Debug + ProxiedWithPresence + ?Sized + 'a>()
-> impl Matcher<ActualT = Optional<PresentField<'a, T>, AbsentField<'a, T>>> {
UnsetMatcher::<T> { _phantom: PhantomData }
}
struct UnsetMatcher<'a, T: ProxiedWithPresence + ?Sized> {
_phantom: PhantomData<PresentField<'a, T>>,
}
impl<'a, T: std::fmt::Debug + ProxiedWithPresence + ?Sized> Matcher for UnsetMatcher<'a, T> {
type ActualT = Optional<PresentField<'a, T>, AbsentField<'a, T>>;
fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
actual.is_unset().into()
}
fn describe(&self, matcher_result: MatcherResult) -> Description {
match matcher_result {
MatcherResult::Match => "is not set".into(),
MatcherResult::NoMatch => "is set".into(),
}
}
}
/// ===============================
/// IS_SET
/// ===============================
pub fn is_set<'a, T: std::fmt::Debug + ProxiedWithPresence + ?Sized + 'a>()
-> impl Matcher<ActualT = Optional<PresentField<'a, T>, AbsentField<'a, T>>> {
SetMatcher::<T> { _phantom: PhantomData }
}
struct SetMatcher<'a, T: ProxiedWithPresence + ?Sized> {
_phantom: PhantomData<PresentField<'a, T>>,
}
impl<'a, T: std::fmt::Debug + ProxiedWithPresence + ?Sized> Matcher for SetMatcher<'a, T> {
type ActualT = Optional<PresentField<'a, T>, AbsentField<'a, T>>;
fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
actual.is_set().into()
}
fn describe(&self, matcher_result: MatcherResult) -> Description {
match matcher_result {
MatcherResult::Match => "is set".into(),
MatcherResult::NoMatch => "is not set".into(),
}
}
}

View File

@ -9,14 +9,12 @@ rust_test(
srcs = ["utf8_test.rs"],
aliases = {
"//rust:protobuf_cpp": "protobuf",
"//rust/test/shared:matchers_cpp": "matchers",
},
deps = [
":feature_verify_cc_rust_proto",
":no_features_proto2_cc_rust_proto",
":no_features_proto3_cc_rust_proto",
"//rust:protobuf_cpp",
"//rust/test/shared:matchers_cpp",
"@crate_index//:googletest",
],
)
@ -26,14 +24,12 @@ rust_test(
srcs = ["utf8_test.rs"],
aliases = {
"//rust:protobuf_upb": "protobuf",
"//rust/test/shared:matchers_upb": "matchers",
},
deps = [
":feature_verify_upb_rust_proto",
":no_features_proto2_upb_rust_proto",
":no_features_proto3_upb_rust_proto",
"//rust:protobuf_upb",
"//rust/test/shared:matchers_upb",
"@crate_index//:googletest",
],
)

View File

@ -60,31 +60,6 @@ impl ScratchSpace {
pub type SerializedData = upb::OwnedArenaBox<[u8]>;
// TODO: Investigate replacing this with direct access to UPB bits.
pub type MessagePresentMutData<'msg, T> = crate::vtable::RawVTableOptionalMutatorData<'msg, T>;
pub type MessageAbsentMutData<'msg, T> = crate::vtable::RawVTableOptionalMutatorData<'msg, T>;
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]>;
#[derive(Debug)]
pub struct MessageVTable {
pub getter: unsafe extern "C" fn(msg: RawMessage) -> Option<RawMessage>,
pub mut_getter: unsafe extern "C" fn(msg: RawMessage, arena: RawArena) -> RawMessage,
pub clearer: unsafe extern "C" fn(msg: RawMessage),
}
impl MessageVTable {
pub const fn new(
_private: Private,
getter: unsafe extern "C" fn(msg: RawMessage) -> Option<RawMessage>,
mut_getter: unsafe extern "C" fn(msg: RawMessage, arena: RawArena) -> RawMessage,
clearer: unsafe extern "C" fn(msg: RawMessage),
) -> Self {
MessageVTable { getter, mut_getter, clearer }
}
}
/// The raw contents of every generated message.
#[derive(Debug)]
pub struct MessageInner {

View File

@ -1,257 +0,0 @@
// 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
use crate::__internal::Private;
use crate::__runtime::MutatorMessageRef;
use crate::{
AbsentField, FieldEntry, Mut, MutProxied, MutProxy, Optional, PresentField,
ProxiedWithPresence, View, ViewProxy,
};
use std::fmt::{self, Debug};
use std::marker::PhantomData;
use std::ptr::NonNull;
/// A proxied type that can use a vtable to provide get/set access for a
/// present field.
///
/// 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: MutProxied {
/// The vtable for get/set access, stored in static memory.
type VTable: Debug + 'static;
fn make_view(_private: Private, mut_inner: RawVTableMutator<'_, Self>) -> View<'_, Self>;
fn make_mut(_private: Private, inner: RawVTableMutator<'_, Self>) -> Mut<'_, Self>;
}
/// A proxied type that can use a vtable to provide get/set/clear access for
/// an optional field.
///
/// 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 ProxiedWithRawOptionalVTable: ProxiedWithRawVTable + ProxiedWithPresence {
/// The vtable for get/set/clear, must contain `Self::VTable`.
type OptionalVTable: Debug + 'static;
/// Cast from a static reference of `OptionalVTable` to `VTable`.
/// This should mean `OptionalVTable` contains a `VTable`.
fn upcast_vtable(
_private: Private,
optional_vtable: &'static Self::OptionalVTable,
) -> &'static Self::VTable;
}
/// Constructs a new field entry from a raw message, a vtable for manipulation,
/// and an eager check for whether the value is present or not.
///
/// # Safety
/// - `msg_ref` must be valid to provide as an argument for `vtable`'s methods
/// for `'msg`.
/// - If given `msg_ref` as an argument, any values returned by `vtable` methods
/// must be valid for `'msg`.
/// - Operations on the vtable must be thread-compatible.
#[doc(hidden)]
pub unsafe fn new_vtable_field_entry<'msg, T: ProxiedWithRawOptionalVTable + ?Sized>(
_private: Private,
msg_ref: MutatorMessageRef<'msg>,
optional_vtable: &'static T::OptionalVTable,
is_set: bool,
) -> FieldEntry<'msg, T>
where
T: ProxiedWithPresence<
PresentMutData<'msg> = RawVTableOptionalMutatorData<'msg, T>,
AbsentMutData<'msg> = RawVTableOptionalMutatorData<'msg, T>,
>,
{
// SAFETY: safe as promised by the caller of the function
let data = unsafe { RawVTableOptionalMutatorData::new(Private, msg_ref, optional_vtable) };
if is_set {
Optional::Set(PresentField::from_inner(Private, data))
} else {
Optional::Unset(AbsentField::from_inner(Private, data))
}
}
/// The internal implementation type for a vtable-based `protobuf::Mut<T>`.
///
/// This stores the two components necessary to mutate the field:
/// borrowed message data and a vtable reference.
///
/// The borrowed message data varies per runtime: C++ needs a message pointer,
/// while UPB needs a message pointer and an `&Arena`.
///
/// Implementations of `ProxiedWithRawVTable` implement get/set
/// on top of `RawVTableMutator<T>`, and the top-level mutator (e.g.
/// `BytesMut`) calls these methods.
///
/// [`RawVTableOptionalMutatorData`] is similar, but also includes the
/// capability to has/clear.
pub struct RawVTableMutator<'msg, T: ?Sized> {
msg_ref: MutatorMessageRef<'msg>,
/// Stores `&'static <T as ProxiedWithRawVTable>::Vtable`
/// as a type-erased pointer to avoid a bound on the struct.
vtable: NonNull<()>,
_phantom: PhantomData<&'msg T>,
}
// These use manual impls instead of derives to avoid unnecessary bounds on `T`.
// This problem is referred to as "perfect derive".
// https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/
impl<'msg, T: ?Sized> Clone for RawVTableMutator<'msg, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'msg, T: ?Sized> Copy for RawVTableMutator<'msg, T> {}
impl<'msg, T: ProxiedWithRawVTable + ?Sized> Debug for RawVTableMutator<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawVTableMutator")
.field("msg_ref", &self.msg_ref)
.field("vtable", self.vtable())
.finish()
}
}
impl<'msg, T: ProxiedWithRawVTable + ?Sized> RawVTableMutator<'msg, T> {
/// # Safety
/// - `msg_ref` must be valid to provide as an argument for `vtable`'s
/// methods for `'msg`.
/// - If given `msg_ref` as an argument, any values returned by `vtable`
/// methods must be valid for `'msg`.
#[doc(hidden)]
pub unsafe fn new(
_private: Private,
msg_ref: MutatorMessageRef<'msg>,
vtable: &'static T::VTable,
) -> Self {
RawVTableMutator { msg_ref, vtable: NonNull::from(vtable).cast(), _phantom: PhantomData }
}
pub fn vtable(self) -> &'static T::VTable {
// SAFETY: This was cast from `&'static T::VTable`.
unsafe { self.vtable.cast().as_ref() }
}
pub fn msg_ref(self) -> MutatorMessageRef<'msg> {
self.msg_ref
}
}
/// [`RawVTableMutator`], but also includes has/clear.
///
/// This is used as the `PresentData` and `AbsentData` for `impl
/// ProxiedWithPresence for T`. In that implementation, `clear_present_field`
/// and `set_absent_to_default` will use methods implemented on
/// `RawVTableOptionalMutatorData<T>` to do the setting and clearing.
///
/// This has the same representation for "present" and "absent" data;
/// differences like default values are obviated by the vtable.
pub struct RawVTableOptionalMutatorData<'msg, T: ?Sized> {
msg_ref: MutatorMessageRef<'msg>,
/// Stores `&'static <T as ProxiedWithRawOptionalVTable>::Vtable`
/// as a type-erased pointer to avoid a bound on the struct.
optional_vtable: NonNull<()>,
_phantom: PhantomData<&'msg T>,
}
// SAFETY: all `T` that can perform mutations don't mutate through a shared
// reference.
unsafe impl<'msg, T: ?Sized> Sync for RawVTableOptionalMutatorData<'msg, T> {}
// These use manual impls instead of derives to avoid unnecessary bounds on `T`.
// This problem is referred to as "perfect derive".
// https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/
impl<'msg, T: ?Sized> Clone for RawVTableOptionalMutatorData<'msg, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'msg, T: ?Sized> Copy for RawVTableOptionalMutatorData<'msg, T> {}
impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Debug
for RawVTableOptionalMutatorData<'msg, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawVTableOptionalMutatorData")
.field("msg_ref", &self.msg_ref)
.field("vtable", self.optional_vtable())
.finish()
}
}
impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> RawVTableOptionalMutatorData<'msg, T> {
/// # Safety
/// - `msg_ref` must be valid to provide as an argument for `vtable`'s
/// methods for `'msg`.
/// - If given `msg_ref` as an argument, any values returned by `vtable`
/// methods must be valid for `'msg`.
#[doc(hidden)]
pub unsafe fn new(
_private: Private,
msg_ref: MutatorMessageRef<'msg>,
vtable: &'static T::OptionalVTable,
) -> Self {
Self { msg_ref, optional_vtable: NonNull::from(vtable).cast(), _phantom: PhantomData }
}
pub fn msg_ref(self) -> MutatorMessageRef<'msg> {
self.msg_ref
}
pub fn optional_vtable(self) -> &'static T::OptionalVTable {
// SAFETY: This was cast from `&'static T::OptionalVTable` in `new`.
unsafe { self.optional_vtable.cast().as_ref() }
}
fn into_raw_mut(self) -> RawVTableMutator<'msg, T> {
// SAFETY: the safety requirements have been met by the caller of `new`.
unsafe {
RawVTableMutator::new(
Private,
self.msg_ref,
T::upcast_vtable(Private, self.optional_vtable()),
)
}
}
}
impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized + 'msg> ViewProxy<'msg>
for RawVTableOptionalMutatorData<'msg, T>
{
type Proxied = T;
fn as_view(&self) -> View<'_, T> {
T::make_view(Private, self.into_raw_mut())
}
fn into_view<'shorter>(self) -> View<'shorter, T>
where
'msg: 'shorter,
{
T::make_view(Private, self.into_raw_mut())
}
}
// Note: though this raw value implements `MutProxy`, the `as_mut` is only valid
// when the field is known to be present. `FieldEntry` enforces this in its
// design: `AbsentField { inner: RawVTableOptionalMutatorData<T> }` does not
// implement `MutProxy`.
impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized + 'msg> MutProxy<'msg>
for RawVTableOptionalMutatorData<'msg, T>
{
fn as_mut(&mut self) -> Mut<'_, T> {
T::make_mut(Private, self.into_raw_mut())
}
fn into_mut<'shorter>(self) -> Mut<'shorter, T>
where
'msg: 'shorter,
{
T::make_mut(Private, self.into_raw_mut())
}
}

View File

@ -924,64 +924,6 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
}
}
impl $pbi$::ProxiedWithRawVTable for $Msg$ {
type VTable = $pbr$::MessageVTable;
fn make_view(_private: $pbi$::Private,
mut_inner: $pbi$::RawVTableMutator<'_, Self>)
-> $pb$::View<'_, Self> {
let msg = unsafe {
(mut_inner.vtable().getter)(mut_inner.msg_ref().msg())
};
$Msg$View::new($pbi$::Private, msg$unwrap_upb$)
}
fn make_mut(_private: $pbi$::Private,
inner: $pbi$::RawVTableMutator<'_, Self>)
-> $pb$::Mut<'_, Self> {
let raw_submsg = unsafe {
(inner.vtable().mut_getter)(inner.msg_ref().msg()$upb_arena$)
};
$Msg$Mut::from_parent($pbi$::Private, inner.msg_ref(), raw_submsg)
}
}
impl $pbi$::ProxiedWithRawOptionalVTable for $Msg$ {
type OptionalVTable = $pbr$::MessageVTable;
fn upcast_vtable(_private: $pbi$::Private,
optional_vtable: &'static Self::OptionalVTable)
-> &'static Self::VTable {
&optional_vtable
}
}
impl $pb$::ProxiedWithPresence for $Msg$ {
type PresentMutData<'a> = $pbr$::MessagePresentMutData<'a, $Msg$>;
type AbsentMutData<'a> = $pbr$::MessageAbsentMutData<'a, $Msg$>;
fn clear_present_field(present_mutator: Self::PresentMutData<'_>)
-> Self::AbsentMutData<'_> {
// SAFETY: The raw ptr msg_ref is valid
unsafe {
(present_mutator.optional_vtable().clearer)(present_mutator.msg_ref().msg());
$pbi$::RawVTableOptionalMutatorData::new($pbi$::Private,
present_mutator.msg_ref(),
present_mutator.optional_vtable())
}
}
fn set_absent_to_default(absent_mutator: Self::AbsentMutData<'_>)
-> Self::PresentMutData<'_> {
unsafe {
$pbi$::RawVTableOptionalMutatorData::new($pbi$::Private,
absent_mutator.msg_ref(),
absent_mutator.optional_vtable())
}
}
}
$into_proxied_impl$
$repeated_impl$