* SettableValue * ProxiedWithPresence * FieldEntry PiperOrigin-RevId: 629363417pull/16660/head
parent
e181855abe
commit
959903d199
15 changed files with 8 additions and 1338 deletions
@ -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(), |
||||
} |
||||
} |
||||
} |
@ -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()) |
||||
} |
||||
} |
Loading…
Reference in new issue