Protocol Buffers - Google's data interchange format (grpc依赖) https://developers.google.com/protocol-buffers/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

257 lines
9.3 KiB

// 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())
}
}