Remove the now unused vtable types. In particular,
* SettableValue * ProxiedWithPresence * FieldEntry PiperOrigin-RevId: 629363417pull/16660/head
parent
e181855abe
commit
959903d199
|
@ -54,7 +54,6 @@ PROTOBUF_SHARED = [
|
|||
"repeated.rs",
|
||||
"shared.rs",
|
||||
"string.rs",
|
||||
"vtable.rs",
|
||||
"map.rs",
|
||||
"proto_macro.rs",
|
||||
]
|
||||
|
|
23
rust/cpp.rs
23
rust/cpp.rs
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
13
rust/map.rs
13
rust/map.rs
|
@ -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>
|
||||
{
|
||||
|
|
677
rust/optional.rs
677
rust/optional.rs
|
@ -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 })));
|
||||
}
|
||||
}
|
||||
|
|
152
rust/proxied.rs
152
rust/proxied.rs
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
|
25
rust/upb.rs
25
rust/upb.rs
|
@ -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 {
|
||||
|
|
257
rust/vtable.rs
257
rust/vtable.rs
|
@ -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())
|
||||
}
|
||||
}
|
|
@ -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$
|
||||
|
|
Loading…
Reference in New Issue