Rework Repeated and primitives with traits for use by out-of-crate items

PiperOrigin-RevId: 591007327
pull/15076/head
Alyssa Haroldsen 1 year ago committed by Copybara-Service
parent d159913c0d
commit 6ae76fd6ed
  1. 187
      rust/cpp.rs
  2. 2
      rust/internal.rs
  3. 169
      rust/primitive.rs
  4. 26
      rust/proxied.rs
  5. 473
      rust/repeated.rs
  6. 2
      rust/shared.rs
  7. 198
      rust/upb.rs
  8. 152
      rust/vtable.rs
  9. 66
      src/google/protobuf/compiler/rust/accessors/repeated_scalar.cc
  10. 17
      src/google/protobuf/compiler/rust/accessors/singular_scalar.cc
  11. 17
      src/google/protobuf/compiler/rust/message.cc

@ -9,6 +9,7 @@
use crate::ProtoStr;
use crate::__internal::{Private, PtrAndLen, RawArena, RawMap, RawMessage, RawRepeatedField};
use crate::{Mut, ProxiedInRepeated, Repeated, View};
use core::fmt::Debug;
use paste::paste;
use std::alloc::Layout;
@ -195,130 +196,85 @@ pub fn copy_bytes_in_arena_if_needed_by_runtime<'msg>(
val
}
/// RepeatedField impls delegate out to `extern "C"` functions exposed by
/// `cpp_api.h` and store either a RepeatedField* or a RepeatedPtrField*
/// depending on the type.
/// The raw type-erased pointer version of `RepeatedMut`.
///
/// Note: even though this type is `Copy`, it should only be copied by
/// protobuf internals that can maintain mutation invariants:
///
/// - No concurrent mutation for any two fields in a message: this means
/// mutators cannot be `Send` but are `Sync`.
/// - If there are multiple accessible `Mut` to a single message at a time, they
/// must be different fields, and not be in the same oneof. As such, a `Mut`
/// cannot be `Clone` but *can* reborrow itself with `.as_mut()`, which
/// converts `&'b mut Mut<'a, T>` to `Mut<'b, T>`.
#[derive(Debug)]
pub struct RepeatedField<'msg, T: ?Sized> {
inner: RepeatedFieldInner<'msg>,
_phantom: PhantomData<&'msg mut T>,
}
/// CPP runtime-specific arguments for initializing a RepeatedField.
/// See RepeatedField comment about mutation invariants for when this type can
/// be copied.
/// Contains a `proto2::RepeatedField*` or `proto2::RepeatedPtrField*`.
#[derive(Clone, Copy, Debug)]
pub struct RepeatedFieldInner<'msg> {
pub raw: RawRepeatedField,
pub _phantom: PhantomData<&'msg ()>,
pub struct InnerRepeatedMut<'msg> {
pub(crate) raw: RawRepeatedField,
_phantom: PhantomData<&'msg ()>,
}
impl<'msg, T: ?Sized> RepeatedField<'msg, T> {
pub fn from_inner(_private: Private, inner: RepeatedFieldInner<'msg>) -> Self {
RepeatedField { inner, _phantom: PhantomData }
impl<'msg> InnerRepeatedMut<'msg> {
#[doc(hidden)]
pub fn new(_private: Private, raw: RawRepeatedField) -> Self {
InnerRepeatedMut { raw, _phantom: PhantomData }
}
}
impl<'msg, T: ?Sized> Copy for RepeatedField<'msg, T> {}
impl<'msg, T: ?Sized> Clone for RepeatedField<'msg, T> {
fn clone(&self) -> RepeatedField<'msg, T> {
*self
}
}
pub trait RepeatedScalarOps {
fn new_repeated_field() -> RawRepeatedField;
fn push(f: RawRepeatedField, v: Self);
fn len(f: RawRepeatedField) -> usize;
fn get(f: RawRepeatedField, i: usize) -> Self;
fn set(f: RawRepeatedField, i: usize, v: Self);
fn copy_from(src: RawRepeatedField, dst: RawRepeatedField);
}
macro_rules! impl_repeated_scalar_ops {
($($t: ty),*) => {
paste! { $(
macro_rules! impl_repeated_primitives {
(@impl $($t:ty => [
$new_thunk:ident,
$add_thunk:ident,
$size_thunk:ident,
$get_thunk:ident,
$set_thunk:ident,
$copy_from_thunk:ident $(,)?
]),* $(,)?) => {
$(
// TODO: Add clear, free
extern "C" {
fn [< __pb_rust_RepeatedField_ $t _new >]() -> RawRepeatedField;
fn [< __pb_rust_RepeatedField_ $t _add >](f: RawRepeatedField, v: $t);
fn [< __pb_rust_RepeatedField_ $t _size >](f: RawRepeatedField) -> usize;
fn [< __pb_rust_RepeatedField_ $t _get >](f: RawRepeatedField, i: usize) -> $t;
fn [< __pb_rust_RepeatedField_ $t _set >](f: RawRepeatedField, i: usize, v: $t);
fn [< __pb_rust_RepeatedField_ $t _copy_from >](src: RawRepeatedField, dst: RawRepeatedField);
fn $new_thunk() -> RawRepeatedField;
fn $add_thunk(f: RawRepeatedField, v: $t);
fn $size_thunk(f: RawRepeatedField) -> usize;
fn $get_thunk(f: RawRepeatedField, i: usize) -> $t;
fn $set_thunk(f: RawRepeatedField, i: usize, v: $t);
fn $copy_from_thunk(src: RawRepeatedField, dst: RawRepeatedField);
}
impl RepeatedScalarOps for $t {
fn new_repeated_field() -> RawRepeatedField {
unsafe { [< __pb_rust_RepeatedField_ $t _new >]() }
unsafe impl ProxiedInRepeated for $t {
#[allow(dead_code)]
fn repeated_new(_: Private) -> Repeated<$t> {
unsafe {
Repeated::from_inner(InnerRepeatedMut::new(Private, $new_thunk()))
}
}
fn push(f: RawRepeatedField, v: Self) {
unsafe { [< __pb_rust_RepeatedField_ $t _add >](f, v) }
fn repeated_len(f: View<Repeated<$t>>) -> usize {
unsafe { $size_thunk(f.as_raw(Private)) }
}
fn len(f: RawRepeatedField) -> usize {
unsafe { [< __pb_rust_RepeatedField_ $t _size >](f) }
fn repeated_push(mut f: Mut<Repeated<$t>>, v: View<$t>) {
unsafe { $add_thunk(f.as_raw(Private), v) }
}
fn get(f: RawRepeatedField, i: usize) -> Self {
unsafe { [< __pb_rust_RepeatedField_ $t _get >](f, i) }
unsafe fn repeated_get_unchecked(f: View<Repeated<$t>>, i: usize) -> View<$t> {
unsafe { $get_thunk(f.as_raw(Private), i) }
}
fn set(f: RawRepeatedField, i: usize, v: Self) {
unsafe { [< __pb_rust_RepeatedField_ $t _set >](f, i, v) }
unsafe fn repeated_set_unchecked(mut f: Mut<Repeated<$t>>, i: usize, v: View<$t>) {
unsafe { $set_thunk(f.as_raw(Private), i, v) }
}
fn copy_from(src: RawRepeatedField, dst: RawRepeatedField) {
unsafe { [< __pb_rust_RepeatedField_ $t _copy_from >](src, dst) }
fn repeated_copy_from(src: View<Repeated<$t>>, mut dest: Mut<Repeated<$t>>) {
unsafe { $copy_from_thunk(src.as_raw(Private), dest.as_raw(Private)) }
}
}
)* }
)*
};
}
impl_repeated_scalar_ops!(i32, u32, i64, u64, f32, f64, bool);
impl<'msg, T: RepeatedScalarOps> RepeatedField<'msg, T> {
#[allow(clippy::new_without_default, dead_code)]
/// new() is not currently used in our normal pathways, it is only used
/// for testing. Existing `RepeatedField<>`s are owned by, and retrieved
/// from, the containing `Message`.
pub fn new() -> Self {
Self::from_inner(
Private,
RepeatedFieldInner::<'msg> { raw: T::new_repeated_field(), _phantom: PhantomData },
)
}
pub fn push(&mut self, val: T) {
T::push(self.inner.raw, val)
}
pub fn len(&self) -> usize {
T::len(self.inner.raw)
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&self, index: usize) -> Option<T> {
if index >= self.len() {
return None;
($($t:ty),* $(,)?) => {
paste!{
impl_repeated_primitives!(@impl $(
$t => [
[< __pb_rust_RepeatedField_ $t _new >],
[< __pb_rust_RepeatedField_ $t _add >],
[< __pb_rust_RepeatedField_ $t _size >],
[< __pb_rust_RepeatedField_ $t _get >],
[< __pb_rust_RepeatedField_ $t _set >],
[< __pb_rust_RepeatedField_ $t _copy_from >],
],
)*);
}
Some(T::get(self.inner.raw, index))
}
pub fn set(&mut self, index: usize, val: T) {
if index >= self.len() {
return;
}
T::set(self.inner.raw, index, val)
}
pub fn copy_from(&mut self, src: &RepeatedField<'_, T>) {
T::copy_from(src.inner.raw, self.inner.raw)
}
};
}
impl_repeated_primitives!(i32, u32, i64, u64, f32, f64, bool);
#[derive(Debug)]
pub struct MapInner<'msg, K: ?Sized, V: ?Sized> {
pub raw: RawMap,
@ -514,29 +470,6 @@ mod tests {
assert_that!(&*serialized_data, eq(b"Hello world"));
}
#[test]
fn repeated_field() {
let mut r = RepeatedField::<i32>::new();
assert_that!(r.len(), eq(0));
r.push(32);
assert_that!(r.get(0), eq(Some(32)));
let mut r = RepeatedField::<u32>::new();
assert_that!(r.len(), eq(0));
r.push(32);
assert_that!(r.get(0), eq(Some(32)));
let mut r = RepeatedField::<f64>::new();
assert_that!(r.len(), eq(0));
r.push(0.1234f64);
assert_that!(r.get(0), eq(Some(0.1234)));
let mut r = RepeatedField::<bool>::new();
assert_that!(r.len(), eq(0));
r.push(true);
assert_that!(r.get(0), eq(Some(true)));
}
#[test]
fn i32_i32_map() {
let mut map: MapInner<'_, i32, i32> = Default::default();

@ -11,7 +11,7 @@
pub use crate::vtable::{
new_vtable_field_entry, BytesMutVTable, BytesOptionalMutVTable, PrimitiveOptionalMutVTable,
PrimitiveVTable, RawVTableMutator,
PrimitiveVTable, PrimitiveWithRawVTable, RawVTableMutator,
};
use std::ptr::NonNull;
use std::slice;

@ -5,105 +5,109 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
use std::fmt::Debug;
use crate::__internal::Private;
use crate::__runtime::InnerPrimitiveMut;
use crate::vtable::{
PrimitiveOptionalMutVTable, PrimitiveVTable, ProxiedWithRawOptionalVTable,
ProxiedWithRawVTable, RawVTableOptionalMutatorData,
};
use crate::vtable::{PrimitiveWithRawVTable, ProxiedWithRawVTable, RawVTableOptionalMutatorData};
use crate::{Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy};
#[derive(Debug)]
/// A mutator for a primitive (numeric or enum) value of `T`.
///
/// This type is `protobuf::Mut<'msg, T>`.
pub struct PrimitiveMut<'msg, T: ProxiedWithRawVTable> {
inner: InnerPrimitiveMut<'msg, T>,
}
impl<'msg, T: ProxiedWithRawVTable> Debug for PrimitiveMut<'msg, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PrimitiveMut").field("inner", &self.inner).finish()
}
}
impl<'msg, T: ProxiedWithRawVTable> PrimitiveMut<'msg, T> {
/// # Safety
/// `inner` must be valid and non-aliased for `T` for `'msg`
#[doc(hidden)]
pub fn from_inner(_private: Private, inner: InnerPrimitiveMut<'msg, T>) -> Self {
pub unsafe fn from_inner(_private: Private, inner: InnerPrimitiveMut<'msg, T>) -> Self {
Self { inner }
}
}
unsafe impl<'msg, T: ProxiedWithRawVTable> Sync for PrimitiveMut<'msg, T> {}
impl<'msg, T> PrimitiveMut<'msg, T>
where
T: PrimitiveWithRawVTable,
{
pub fn get(&self) -> View<'_, T> {
T::make_view(Private, self.inner)
}
pub fn set(&mut self, val: impl SettableValue<T>) {
MutProxy::set(self, val)
}
}
impl<'msg, T> ViewProxy<'msg> for PrimitiveMut<'msg, T>
where
T: PrimitiveWithRawVTable,
{
type Proxied = T;
fn as_view(&self) -> View<'_, Self::Proxied> {
self.get()
}
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> {
self.get()
}
}
impl<'msg, T> MutProxy<'msg> for PrimitiveMut<'msg, T>
where
T: PrimitiveWithRawVTable,
{
fn as_mut(&mut self) -> Mut<'_, Self::Proxied> {
PrimitiveMut { inner: self.inner }
}
fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied>
where
'msg: 'shorter,
{
self
}
}
macro_rules! impl_singular_primitives {
($($t:ty),*) => {
$(
impl Proxied for $t {
type View<'msg> = $t;
type Mut<'msg> = PrimitiveMut<'msg, $t>;
}
impl<'msg> ViewProxy<'msg> for $t {
type Proxied = $t;
fn as_view(&self) -> View<'_, Self::Proxied> {
*self
}
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> {
self
}
}
impl<'msg> PrimitiveMut<'msg, $t> {
pub fn get(&self) -> View<'_, $t> {
self.inner.get()
}
pub fn set(&mut self, val: impl SettableValue<$t>) {
val.set_on(Private, self.as_mut());
}
}
impl<'msg> ViewProxy<'msg> for PrimitiveMut<'msg, $t> {
type Proxied = $t;
fn as_view(&self) -> View<'_, Self::Proxied> {
self.get()
}
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> {
self.get()
}
}
impl<'msg> MutProxy<'msg> for PrimitiveMut<'msg, $t> {
fn as_mut(&mut self) -> Mut<'_, Self::Proxied> {
PrimitiveMut { inner: self.inner }
}
fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied>
where 'msg: 'shorter,
{
self
}
}
impl SettableValue<$t> for $t {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, $t>) where $t: 'msg {
// SAFETY: the raw mutator is valid for `'msg` as enforced by `Mut`
unsafe { mutator.inner.set(self) }
}
}
impl ProxiedWithRawVTable for $t {
type VTable = PrimitiveVTable<$t>;
fn make_view(
_private: Private,
mut_inner: InnerPrimitiveMut<'_, Self>
) -> View<'_, Self> {
mut_inner.get()
impl Proxied for $t {
type View<'msg> = $t;
type Mut<'msg> = PrimitiveMut<'msg, $t>;
}
impl<'msg> ViewProxy<'msg> for $t {
type Proxied = $t;
fn as_view(&self) -> View<'_, Self::Proxied> {
*self
}
fn make_mut(_private: Private, inner: InnerPrimitiveMut<'_, Self>) -> Mut<'_, Self> {
PrimitiveMut::from_inner(Private, inner)
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> {
self
}
}
}
impl ProxiedWithPresence for $t {
impl SettableValue<$t> for $t {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, $t>) where $t: 'msg {
// SAFETY: the raw mutator is valid for `'msg` as enforced by `Mut`
unsafe { mutator.inner.set(self) }
}
}
impl ProxiedWithPresence for $t {
type PresentMutData<'msg> = RawVTableOptionalMutatorData<'msg, $t>;
type AbsentMutData<'msg> = RawVTableOptionalMutatorData<'msg, $t>;
@ -118,18 +122,11 @@ macro_rules! impl_singular_primitives {
) -> Self::PresentMutData<'_> {
absent_mutator.set_absent_to_default()
}
}
}
impl ProxiedWithRawOptionalVTable for $t {
type OptionalVTable = PrimitiveOptionalMutVTable<$t>;
impl PrimitiveWithRawVTable for $t {}
fn upcast_vtable(
_private: Private,
optional_vtable: &'static Self::OptionalVTable,
) -> &'static Self::VTable {
&optional_vtable.base
}
}
// ProxiedInRepeated is implemented in {cpp,upb}.rs
)*
}
}

@ -44,7 +44,9 @@
//! 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;
use std::marker::{Send, Sync};
@ -205,6 +207,7 @@ pub trait MutProxy<'msg>: ViewProxy<'msg> {
'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
@ -233,14 +236,14 @@ pub trait SettableValue<T>: Sized
where
T: Proxied + ?Sized,
{
/// Consumes `self` to set the given mutator to its value.
/// 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
/// a value.
/// the value of `self`.
#[doc(hidden)]
fn set_on_absent(
self,
@ -256,7 +259,7 @@ where
}
/// Consumes `self` and `present_mutator` to set the given present field
/// to a value.
/// to the value of `self`.
#[doc(hidden)]
fn set_on_present(self, _private: Private, mut present_mutator: T::PresentMutData<'_>)
where
@ -264,6 +267,23 @@ where
{
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!()
}
}
#[cfg(test)]

@ -5,190 +5,397 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
use std::fmt::{self, Debug};
use std::iter;
/// Repeated scalar fields are implemented around the runtime-specific
/// `RepeatedField` struct. `RepeatedField` stores an opaque pointer to the
/// runtime-specific representation of a repeated scalar (`upb_Array*` on upb,
/// and `RepeatedField<T>*` on cpp).
use std::marker::PhantomData;
use std::ops::Deref;
use crate::{
Mut, MutProxy, Proxied, SettableValue, View, ViewProxy,
__internal::{Private, RawRepeatedField},
__runtime::{RepeatedField, RepeatedFieldInner},
vtable::ProxiedWithRawVTable,
__runtime::InnerRepeatedMut,
};
#[derive(Clone, Copy)]
pub struct RepeatedFieldRef<'msg> {
pub repeated_field: RawRepeatedField,
pub _phantom: PhantomData<&'msg mut ()>,
}
unsafe impl<'msg> Send for RepeatedFieldRef<'msg> {}
unsafe impl<'msg> Sync for RepeatedFieldRef<'msg> {}
#[derive(Clone, Copy)]
/// Views the elements in a `repeated` field of `T`.
#[repr(transparent)]
pub struct RepeatedView<'msg, T: ?Sized> {
inner: RepeatedField<'msg, T>,
// This does not need to carry an arena in upb, so it can be just the raw repeated field
raw: RawRepeatedField,
_phantom: PhantomData<&'msg T>,
}
unsafe impl<'msg, T: ProxiedWithRawVTable> Sync for RepeatedView<'msg, T> {}
unsafe impl<'msg, T: ProxiedWithRawVTable> Send for RepeatedView<'msg, T> {}
impl<'msg, T: ?Sized> RepeatedView<'msg, T> {
pub fn from_inner(_private: Private, inner: RepeatedFieldInner<'msg>) -> Self {
Self { inner: RepeatedField::<'msg>::from_inner(_private, inner) }
impl<'msg, T: ?Sized> Copy for RepeatedView<'msg, T> {}
impl<'msg, T: ?Sized> Clone for RepeatedView<'msg, T> {
fn clone(&self) -> Self {
*self
}
}
pub struct RepeatedFieldIter<'msg, T> {
inner: RepeatedField<'msg, T>,
current_index: usize,
}
unsafe impl<'msg, T: ?Sized> Sync for RepeatedView<'msg, T> {}
unsafe impl<'msg, T: ?Sized> Send for RepeatedView<'msg, T> {}
impl<'msg, T> std::fmt::Debug for RepeatedView<'msg, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("RepeatedView").finish()
impl<'msg, T: ?Sized> Debug for RepeatedView<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RepeatedView").field("raw", &self.raw).finish()
}
}
/// Mutates the elements in a `repeated` field of `T`.
#[repr(transparent)]
#[derive(Debug)]
pub struct RepeatedMut<'msg, T: ?Sized> {
inner: RepeatedField<'msg, T>,
pub(crate) inner: InnerRepeatedMut<'msg>,
_phantom: PhantomData<&'msg mut T>,
}
unsafe impl<'msg, T: ProxiedWithRawVTable> Sync for RepeatedMut<'msg, T> {}
unsafe impl<'msg, T: ?Sized> Sync for RepeatedMut<'msg, T> {}
impl<'msg, T: ?Sized> RepeatedMut<'msg, T> {
pub fn from_inner(_private: Private, inner: RepeatedFieldInner<'msg>) -> Self {
Self { inner: RepeatedField::from_inner(_private, inner) }
}
pub fn as_mut(&self) -> RepeatedMut<'_, T> {
Self { inner: self.inner }
}
}
impl<'msg, T> std::ops::Deref for RepeatedMut<'msg, T> {
impl<'msg, T: ?Sized> Deref for RepeatedMut<'msg, T> {
type Target = RepeatedView<'msg, T>;
fn deref(&self) -> &Self::Target {
// SAFETY:
// - `Repeated{View,Mut}<'msg, T>` are both `#[repr(transparent)]` over
// `RepeatedField<'msg, T>`.
// - `Repeated{View,Mut}<'msg, T>` are both `#[repr(transparent)]` over
// `RepeatedField<'msg, T>`.
// - `RepeatedField` is a type alias for `NonNull`.
unsafe { &*(self as *const Self as *const RepeatedView<'msg, T>) }
}
}
pub struct Repeated<T>(PhantomData<T>);
impl<'msg, T: ?Sized> Debug for RepeatedMut<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RepeatedMut").field("raw", &self.raw).finish()
}
}
macro_rules! impl_repeated_primitives {
($($t:ty),*) => {
$(
impl Proxied for Repeated<$t> {
type View<'msg> = RepeatedView<'msg, $t>;
type Mut<'msg> = RepeatedMut<'msg, $t>;
}
impl<'msg, T> RepeatedView<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,
{
#[doc(hidden)]
pub fn as_raw(&self, _private: Private) -> RawRepeatedField {
self.raw
}
impl<'msg> ViewProxy<'msg> for RepeatedView<'msg, $t> {
type Proxied = Repeated<$t>;
/// # Safety
/// - `inner` must be valid to read from for `'msg`
#[doc(hidden)]
pub unsafe fn from_raw(_private: Private, raw: RawRepeatedField) -> Self {
Self { raw, _phantom: PhantomData }
}
pub fn len(&self) -> usize {
T::repeated_len(*self)
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(self, index: usize) -> Option<View<'msg, T>> {
if index >= self.len() {
return None;
}
// SAFETY: `index` has been checked to be in-bounds
Some(unsafe { T::repeated_get_unchecked(self, index) })
}
pub fn iter(self) -> RepeatedIter<'msg, T> {
self.into_iter()
}
}
fn as_view(&self) -> View<'_, Self::Proxied> {
*self
}
impl<'msg, T> RepeatedMut<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,
{
// TODO: Add clear, free
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied>
where 'msg: 'shorter,
{
RepeatedView { inner: self.inner }
}
}
/// # Safety
/// - `inner` must be valid to read and write from for `'msg`
/// - There must be no aliasing references or mutations on the same
/// underlying object.
#[doc(hidden)]
pub unsafe fn from_inner(_private: Private, inner: InnerRepeatedMut<'msg>) -> Self {
Self { inner, _phantom: PhantomData }
}
impl<'msg> ViewProxy<'msg> for RepeatedMut<'msg, $t> {
type Proxied = Repeated<$t>;
#[doc(hidden)]
pub fn as_raw(&mut self, _private: Private) -> RawRepeatedField {
self.inner.raw
}
fn as_view(&self) -> View<'_, Self::Proxied> {
**self
}
/// Appends `val` to the end of the repeated field.
pub fn push(&mut self, val: View<T>) {
T::repeated_push(self.as_mut(), val);
}
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied>
where 'msg: 'shorter,
{
*self.into_mut::<'shorter>()
}
}
/// Sets the value at `index` to the value `val`.
///
/// # Panics
/// Panics if `index >= len`
pub fn set(&mut self, index: usize, val: View<T>) {
let len = self.len();
if index >= len {
panic!("index {index} >= repeated len {len}");
}
// SAFETY: `index` has been checked to be in-bounds.
unsafe { T::repeated_set_unchecked(self.as_mut(), index, val) }
}
impl<'msg> MutProxy<'msg> for RepeatedMut<'msg, $t> {
fn as_mut(&mut self) -> Mut<'_, Self::Proxied> {
RepeatedMut { inner: self.inner }
}
/// Returns the value at `index`.
// This is defined as an inherent function to prevent `MutProxy::get` from being
// preferred over `RepeatedView::get`. The former gets priority as it does
// not require a deref.
pub fn get(&self, index: usize) -> Option<View<T>> {
self.as_view().get(index)
}
fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied>
where 'msg: 'shorter,
{
RepeatedMut { inner: self.inner }
}
}
/// Copies from the `src` repeated field into this one.
///
/// Also provided by [`MutProxy::set`].
pub fn copy_from(&mut self, src: RepeatedView<'_, T>) {
T::repeated_copy_from(src, self.as_mut())
}
}
impl <'msg> SettableValue<Repeated<$t>> for RepeatedView<'msg, $t> {
fn set_on<'b> (self, _private: Private, mut mutator: Mut<'b, Repeated<$t>>)
where
Repeated<$t>: 'b {
mutator.copy_from(self);
}
}
/// Types that can appear in a `Repeated<T>`.
///
/// This trait is implemented by generated code to communicate how the proxied
/// type can be manipulated for a repeated field.
///
/// Scalars and messages implement `ProxiedInRepeated`.
///
/// # Safety
/// - It must be sound to call `*_unchecked*(x)` with an `index` less than
/// `repeated_len(x)`.
pub unsafe trait ProxiedInRepeated: Proxied {
// TODO: Add clear, free
/// Constructs a new owned `Repeated` field.
#[doc(hidden)]
fn repeated_new(_private: Private) -> Repeated<Self> {
unimplemented!("not required")
}
impl<'msg> RepeatedView<'msg, $t> {
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&self, index: usize) -> Option<$t> {
self.inner.get(index)
}
pub fn iter(&self) -> RepeatedFieldIter<'_, $t> {
(*self).into_iter()
}
}
/// Gets the length of the repeated field.
fn repeated_len(repeated: View<Repeated<Self>>) -> usize;
impl<'msg> RepeatedMut<'msg, $t> {
pub fn push(&mut self, val: $t) {
self.inner.push(val)
}
pub fn set(&mut self, index: usize, val: $t) {
self.inner.set(index, val)
}
pub fn iter(&self) -> RepeatedFieldIter<'_, $t> {
self.as_view().into_iter()
}
pub fn copy_from(&mut self, src: RepeatedView<'_, $t>) {
self.inner.copy_from(&src.inner);
}
}
/// Appends a new element to the end of the repeated field.
fn repeated_push(repeated: Mut<Repeated<Self>>, val: View<Self>);
impl<'msg> std::iter::Iterator for RepeatedFieldIter<'msg, $t> {
type Item = $t;
fn next(&mut self) -> Option<Self::Item> {
let val = self.inner.get(self.current_index);
if val.is_some() {
self.current_index += 1;
}
val
}
}
/// # Safety
/// `index` must be less than `Self::repeated_len(repeated)`
unsafe fn repeated_get_unchecked(repeated: View<Repeated<Self>>, index: usize) -> View<Self>;
impl<'msg> std::iter::IntoIterator for RepeatedView<'msg, $t> {
type Item = $t;
type IntoIter = RepeatedFieldIter<'msg, $t>;
fn into_iter(self) -> Self::IntoIter {
RepeatedFieldIter { inner: self.inner, current_index: 0 }
}
}
)*
/// # Safety
/// `index` must be less than `Self::repeated_len(repeated)`
unsafe fn repeated_set_unchecked(repeated: Mut<Repeated<Self>>, index: usize, val: View<Self>);
/// Copies the values in the `src` repeated field into `dest`.
fn repeated_copy_from(src: View<Repeated<Self>>, dest: Mut<Repeated<Self>>);
}
/// An iterator over the values inside of a [`View<Repeated<T>>`](RepeatedView).
pub struct RepeatedIter<'msg, T: ?Sized> {
view: RepeatedView<'msg, T>,
current_index: usize,
}
impl<'msg, T: ?Sized> Debug for RepeatedIter<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RepeatedIter")
.field("view", &self.view)
.field("current_index", &self.current_index)
.finish()
}
}
impl_repeated_primitives!(i32, u32, bool, f32, f64, i64, u64);
/// An iterator over the mutators inside of a [`Mut<Repeated<T>>`](RepeatedMut).
pub struct RepeatedIterMut<'msg, T: ?Sized> {
mutator: RepeatedMut<'msg, T>,
current_index: usize,
}
impl<'msg, T: ?Sized> Debug for RepeatedIterMut<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RepeatedIterMut")
.field("mutator", &self.mutator)
.field("current_index", &self.current_index)
.finish()
}
}
/// A `repeated` field of `T`, used as the owned target for `Proxied`.
///
/// Users will generally write [`View<Repeated<T>>`](RepeatedView) or
/// [`Mut<Repeated<T>>`](RepeatedMut) to access the repeated elements
pub struct Repeated<T: ?Sized + ProxiedInRepeated> {
inner: InnerRepeatedMut<'static>,
_phantom: PhantomData<T>,
}
#[allow(dead_code)]
impl<T: ?Sized + ProxiedInRepeated> Repeated<T> {
pub(crate) fn new() -> Self {
T::repeated_new(Private)
}
pub(crate) unsafe fn from_inner(inner: InnerRepeatedMut<'static>) -> Self {
Self { inner, _phantom: PhantomData }
}
pub(crate) fn inner(&mut self) -> InnerRepeatedMut<'static> {
self.inner
}
pub(crate) fn as_mut(&mut self) -> RepeatedMut<'_, T> {
RepeatedMut { inner: self.inner, _phantom: PhantomData }
}
}
// SAFETY: `Repeated` does not allow for shared mutability.
unsafe impl<T: ProxiedInRepeated> Sync for Repeated<T> {}
impl<T> Proxied for Repeated<T>
where
T: ProxiedInRepeated + ?Sized,
{
type View<'msg> = RepeatedView<'msg, T> where Repeated<T>: 'msg;
type Mut<'msg> = RepeatedMut<'msg, T> where Repeated<T>: 'msg;
}
impl<'msg, T> ViewProxy<'msg> for RepeatedView<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,
{
type Proxied = Repeated<T>;
fn as_view(&self) -> View<'_, Self::Proxied> {
*self
}
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied>
where
'msg: 'shorter,
{
RepeatedView { raw: self.raw, _phantom: PhantomData }
}
}
impl<'msg, T> ViewProxy<'msg> for RepeatedMut<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,
{
type Proxied = Repeated<T>;
fn as_view(&self) -> View<'_, Self::Proxied> {
**self
}
fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied>
where
'msg: 'shorter,
{
*self.into_mut::<'shorter>()
}
}
impl<'msg, T> MutProxy<'msg> for RepeatedMut<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,
{
fn as_mut(&mut self) -> Mut<'_, Self::Proxied> {
RepeatedMut { inner: self.inner, _phantom: PhantomData }
}
fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied>
where
'msg: 'shorter,
{
RepeatedMut { inner: self.inner, _phantom: PhantomData }
}
}
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)
}
}
// TODO: impl ExactSizeIterator
impl<'msg, T> iter::Iterator for RepeatedIter<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,
{
type Item = View<'msg, T>;
fn next(&mut self) -> Option<Self::Item> {
let val = self.view.get(self.current_index);
if val.is_some() {
self.current_index += 1;
}
val
}
}
impl<'msg, T> iter::IntoIterator for RepeatedView<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,
{
type Item = View<'msg, T>;
type IntoIter = RepeatedIter<'msg, T>;
fn into_iter(self) -> Self::IntoIter {
RepeatedIter { view: self, current_index: 0 }
}
}
#[cfg(test)]
mod tests {
use super::*;
use googletest::prelude::*;
#[test]
fn test_primitive_repeated() {
macro_rules! primitive_repeated_tests {
($($t:ty => [$($vals:expr),* $(,)?]),* $(,)?) => {
$({
// Constructs a new, owned, `Repeated`, only used for tests.
let mut r = Repeated::<$t>::new();
let mut r = r.as_mut();
assert_that!(r.len(), eq(0));
assert!(r.iter().next().is_none(), "starts with empty iter");
assert!(r.iter().next().is_none(), "starts with empty mut iter");
assert!(r.is_empty(), "starts is_empty");
let mut expected_len = 0usize;
$(
let val: View<$t> = $vals;
r.push(val);
assert_that!(r.get(expected_len), eq(Some(val)));
expected_len += 1;
assert_that!(r.len(), eq(expected_len));
)*
assert_that!(
r.iter().collect::<Vec<$t>>(), elements_are![$(eq($vals)),*]);
r.set(0, <$t as Default>::default());
assert_that!(r.get(0).expect("elem 0"), eq(<$t as Default>::default()));
})*
}
}
primitive_repeated_tests!(
u32 => [1,2,3],
i32 => [1,2],
f64 => [10.0, 0.1234f64],
bool => [false, true, true, false],
);
}
}

@ -28,7 +28,7 @@ pub mod __public {
pub use crate::proxied::{
Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy,
};
pub use crate::repeated::{RepeatedFieldRef, RepeatedMut, RepeatedView};
pub use crate::repeated::{ProxiedInRepeated, Repeated, RepeatedMut, RepeatedView};
pub use crate::string::{BytesMut, ProtoStr, ProtoStrMut};
}
pub use __public::*;

@ -9,18 +9,20 @@
use crate::ProtoStr;
use crate::__internal::{Private, PtrAndLen, RawArena, RawMap, RawMessage, RawRepeatedField};
use crate::{Mut, ProxiedInRepeated, Repeated, RepeatedMut, RepeatedView, View, ViewProxy};
use core::fmt::Debug;
use paste::paste;
use std::alloc;
use std::alloc::Layout;
use std::cell::UnsafeCell;
use std::ffi::c_int;
use std::fmt;
use std::marker::PhantomData;
use std::mem::{size_of, MaybeUninit};
use std::ops::Deref;
use std::ptr::{self, NonNull};
use std::slice;
use std::sync::Once;
use std::sync::{Once, OnceLock};
/// See `upb/port/def.inc`.
const UPB_MALLOC_ALIGN: usize = 8;
@ -295,40 +297,28 @@ pub fn copy_bytes_in_arena_if_needed_by_runtime<'msg>(
}
}
/// RepeatedFieldInner contains a `upb_Array*` as well as a reference to an
/// `Arena`, most likely that of the containing `Message`. upb requires an Arena
/// to perform mutations on a repeated field.
/// The raw type-erased pointer version of `RepeatedMut`.
///
/// Contains a `upb_Array*` as well as `RawArena`, most likely that of the
/// containing message. upb requires a `RawArena` to perform mutations on
/// a repeated field.
///
/// An owned `Repeated` stores a `InnerRepeatedMut<'static>` and manages the
/// contained `RawArena`.
#[derive(Clone, Copy, Debug)]
pub struct RepeatedFieldInner<'msg> {
pub raw: RawRepeatedField,
pub arena: &'msg Arena,
}
#[derive(Debug)]
pub struct RepeatedField<'msg, T: ?Sized> {
inner: RepeatedFieldInner<'msg>,
_phantom: PhantomData<&'msg mut T>,
pub struct InnerRepeatedMut<'msg> {
pub(crate) raw: RawRepeatedField,
// Storing a `RawArena` instead of `&Arena` allows this to be used for
// both `RepeatedMut<T>` and `Repeated<T>`.
arena: RawArena,
_phantom: PhantomData<&'msg Arena>,
}
// 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> Copy for RepeatedField<'msg, T> {}
impl<'msg, T: ?Sized> Clone for RepeatedField<'msg, T> {
fn clone(&self) -> RepeatedField<'msg, T> {
*self
}
}
impl<'msg, T: ?Sized> RepeatedField<'msg, T> {
pub fn len(&self) -> usize {
unsafe { upb_Array_Size(self.inner.raw) }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn from_inner(_private: Private, inner: RepeatedFieldInner<'msg>) -> Self {
Self { inner, _phantom: PhantomData }
impl<'msg> InnerRepeatedMut<'msg> {
#[doc(hidden)]
#[allow(clippy::needless_pass_by_ref_mut)] // Sound construction requires mutable access.
pub fn new(_private: Private, raw: RawRepeatedField, arena: &'msg Arena) -> Self {
InnerRepeatedMut { raw, arena: arena.raw(), _phantom: PhantomData }
}
}
@ -367,7 +357,6 @@ pub enum UpbCType {
}
extern "C" {
#[allow(dead_code)]
fn upb_Array_New(a: RawArena, r#type: std::ffi::c_int) -> RawRepeatedField;
fn upb_Array_Size(arr: RawRepeatedField) -> usize;
fn upb_Array_Set(arr: RawRepeatedField, i: usize, val: upb_MessageValue);
@ -379,56 +368,53 @@ extern "C" {
}
macro_rules! impl_repeated_primitives {
($(($rs_type:ty, $ufield:ident, $upb_tag:expr)),*) => {
($(($t:ty, $ufield:ident, $upb_tag:expr)),* $(,)?) => {
$(
impl<'msg> RepeatedField<'msg, $rs_type> {
// TODO: Add clear, free
unsafe impl ProxiedInRepeated for $t {
#[allow(dead_code)]
fn new(arena: &'msg Arena) -> Self {
Self {
inner: RepeatedFieldInner {
raw: unsafe { upb_Array_New(arena.raw, $upb_tag as std::ffi::c_int) },
arena,
},
_phantom: PhantomData,
fn repeated_new(_: Private) -> Repeated<$t> {
let arena = Arena::new();
let raw_arena = arena.raw();
std::mem::forget(arena);
unsafe {
Repeated::from_inner(InnerRepeatedMut {
raw: upb_Array_New(raw_arena, $upb_tag as c_int),
arena: raw_arena,
_phantom: PhantomData,
})
}
}
pub fn push(&mut self, val: $rs_type) {
unsafe { upb_Array_Append(
self.inner.raw,
upb_MessageValue { $ufield: val },
self.inner.arena.raw(),
) }
fn repeated_len(f: View<Repeated<$t>>) -> usize {
unsafe { upb_Array_Size(f.as_raw(Private)) }
}
pub fn get(&self, i: usize) -> Option<$rs_type> {
if i >= self.len() {
None
} else {
unsafe { Some(upb_Array_Get(self.inner.raw, i).$ufield) }
fn repeated_push(mut f: Mut<Repeated<$t>>, v: View<$t>) {
unsafe {
upb_Array_Append(
f.as_raw(Private),
upb_MessageValue { $ufield: v },
f.raw_arena(Private))
}
}
pub fn set(&self, i: usize, val: $rs_type) {
if i >= self.len() {
return;
}
unsafe { upb_Array_Set(
self.inner.raw,
i,
upb_MessageValue { $ufield: val },
) }
unsafe fn repeated_get_unchecked(f: View<Repeated<$t>>, i: usize) -> View<$t> {
unsafe { upb_Array_Get(f.as_raw(Private), i).$ufield }
}
pub fn copy_from(&mut self, src: &RepeatedField<'_, $rs_type>) {
unsafe fn repeated_set_unchecked(mut f: Mut<Repeated<$t>>, i: usize, v: View<$t>) {
unsafe { upb_Array_Set(f.as_raw(Private), i, upb_MessageValue { $ufield: v }) }
}
fn repeated_copy_from(src: View<Repeated<$t>>, mut dest: Mut<Repeated<$t>>) {
// SAFETY:
// - `upb_Array_Resize` is unsafe but assumed to be always sound to call.
// - `copy_nonoverlapping` is unsafe but here we guarantee that both pointers
// are valid, the pointers are `#[repr(u8)]`, and the size is correct.
unsafe {
if (!upb_Array_Resize(self.inner.raw, src.len(), self.inner.arena.raw())) {
if (!upb_Array_Resize(dest.as_raw(Private), src.len(), dest.inner.arena)) {
panic!("upb_Array_Resize failed.");
}
ptr::copy_nonoverlapping(
upb_Array_DataPtr(src.inner.raw).cast::<u8>(),
upb_Array_MutableDataPtr(self.inner.raw).cast::<u8>(),
size_of::<$rs_type>() * src.len());
upb_Array_DataPtr(src.as_raw(Private)).cast::<u8>(),
upb_Array_MutableDataPtr(dest.as_raw(Private)).cast::<u8>(),
size_of::<$t>() * src.len());
}
}
}
@ -436,6 +422,14 @@ macro_rules! impl_repeated_primitives {
}
}
impl<'msg, T: ?Sized> RepeatedMut<'msg, T> {
// Returns a `RawArena` which is live for at least `'msg`
#[doc(hidden)]
pub fn raw_arena(&self, _private: Private) -> RawArena {
self.inner.arena
}
}
impl_repeated_primitives!(
(bool, bool_val, UpbCType::Bool),
(f32, float_val, UpbCType::Float),
@ -443,29 +437,28 @@ impl_repeated_primitives!(
(i32, int32_val, UpbCType::Int32),
(u32, uint32_val, UpbCType::UInt32),
(i64, int64_val, UpbCType::Int64),
(u64, uint64_val, UpbCType::UInt64)
(u64, uint64_val, UpbCType::UInt64),
);
/// Returns a static thread-local empty RepeatedFieldInner for use in a
/// RepeatedView.
///
/// # Safety
/// The returned array must never be mutated.
///
/// TODO: Split RepeatedFieldInner into mut and const variants to
/// enforce safety. The returned array must never be mutated.
pub unsafe fn empty_array() -> RepeatedFieldInner<'static> {
// TODO: Consider creating empty array in C.
fn new_repeated_field_inner() -> RepeatedFieldInner<'static> {
let arena = Box::leak::<'static>(Box::new(Arena::new()));
// Provide `i32` as a placeholder type.
RepeatedField::<'static, i32>::new(arena).inner
}
thread_local! {
static REPEATED_FIELD: RepeatedFieldInner<'static> = new_repeated_field_inner();
}
/// Returns a static empty RepeatedView.
pub fn empty_array<T: ?Sized + ProxiedInRepeated>() -> RepeatedView<'static, T> {
// TODO: Consider creating a static empty array in C.
REPEATED_FIELD.with(|inner| *inner)
// Use `i32` for a shared empty repeated for all repeated types on a thread.
static EMPTY_REPEATED_VIEW: OnceLock<RepeatedView<'static, i32>> = OnceLock::new();
// SAFETY:
// - Because the repeated is never mutated, the repeated type is unused and
// therefore valid for `T`.
// - The view is leaked for `'static`.
unsafe {
RepeatedView::from_raw(
Private,
EMPTY_REPEATED_VIEW
.get_or_init(|| Box::leak(Box::new(Repeated::new())).as_mut().into_view())
.as_raw(Private),
)
}
}
/// Returns a static thread-local empty MapInner for use in a
@ -722,37 +715,6 @@ mod tests {
assert_that!(&*serialized_data, eq(b"Hello world"));
}
#[test]
fn i32_array() {
let arena = Arena::new();
let mut arr = RepeatedField::<i32>::new(&arena);
assert_that!(arr.len(), eq(0));
arr.push(1);
assert_that!(arr.get(0), eq(Some(1)));
assert_that!(arr.len(), eq(1));
arr.set(0, 3);
assert_that!(arr.get(0), eq(Some(3)));
for i in 0..2048 {
arr.push(i);
assert_that!(arr.get(arr.len() - 1), eq(Some(i)));
}
}
#[test]
fn u32_array() {
let mut arena = Arena::new();
let mut arr = RepeatedField::<u32>::new(&mut arena);
assert_that!(arr.len(), eq(0));
arr.push(1);
assert_that!(arr.get(0), eq(Some(1)));
assert_that!(arr.len(), eq(1));
arr.set(0, 3);
assert_that!(arr.get(0), eq(Some(3)));
for i in 0..2048 {
arr.push(i);
assert_that!(arr.get(arr.len() - 1), eq(Some(i)));
}
}
#[test]
fn i32_i32_map() {
let mut arena = Arena::new();

@ -6,10 +6,12 @@
// https://developers.google.com/open-source/licenses/bsd
use crate::__internal::{Private, PtrAndLen, RawMessage};
use crate::__runtime::{copy_bytes_in_arena_if_needed_by_runtime, MutatorMessageRef};
use crate::__runtime::{
copy_bytes_in_arena_if_needed_by_runtime, InnerPrimitiveMut, MutatorMessageRef,
};
use crate::{
AbsentField, FieldEntry, Mut, MutProxy, Optional, PresentField, Proxied, ProxiedWithPresence,
View, ViewProxy,
AbsentField, FieldEntry, Mut, MutProxy, Optional, PresentField, PrimitiveMut, Proxied,
ProxiedWithPresence, View, ViewProxy,
};
use std::fmt::{self, Debug};
@ -291,32 +293,6 @@ impl<T> PrimitiveOptionalMutVTable<T> {
}
}
macro_rules! impl_raw_vtable_mutator_get_set {
($($t:ty),*) => {
$(
impl RawVTableMutator<'_, $t> {
pub(crate) fn get(self) -> $t {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by the
// caller of `new`.
unsafe { (self.vtable.getter)(self.msg_ref.msg()) }
}
/// # Safety
/// - `msg_ref` must be valid for the lifetime of `RawVTableMutator`.
pub(crate) unsafe fn set(self, val: $t) {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by the
// caller of `new`.
unsafe { (self.vtable.setter)(self.msg_ref.msg(), val) }
}
}
)*
}
}
impl_raw_vtable_mutator_get_set!(bool, f32, f64, i32, i64, u32, u64);
/// A generic thunk vtable for mutating a present `bytes` or `string` field.
#[doc(hidden)]
#[derive(Debug)]
@ -421,35 +397,89 @@ impl<'msg> RawVTableOptionalMutatorData<'msg, [u8]> {
}
}
macro_rules! impl_raw_vtable_optional_mutator_data {
($($t:ty),*) => {
$(
impl<'msg> RawVTableOptionalMutatorData<'msg, $t> {
pub(crate) fn set_absent_to_default(self) -> Self {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as
// promised by the caller of `new`.
self.set(self.vtable.default)
}
pub(crate) fn set(self, val: $t) -> Self {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as
// promised by the caller of `new`.
unsafe { (self.vtable.base.setter)(self.msg_ref.msg(), val.into()) }
self
}
pub(crate) fn clear(self) -> Self {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as
// promised by the caller of `new`.
unsafe { (self.vtable.clearer)(self.msg_ref.msg()) }
self
}
}
)*
}
}
impl_raw_vtable_optional_mutator_data!(bool, f32, f64, i32, i64, u32, u64);
/// Primitive types using a vtable for message access that are trivial to copy
/// and have a `'static` lifetime.
///
/// Implementing this trait automatically implements `ProxiedWithRawVTable`,
/// `ProxiedWithRawOptionalVTable`, and get/set/clear methods on
/// `RawVTableMutator` and `RawVTableOptionalMutatorData` that use the vtable.
///
/// It doesn't implement `Proxied`, `ViewProxy`, `SettableValue` or
/// `ProxiedWithPresence` for `Self` to avoid future conflicting blanket impls
/// on those traits.
pub trait PrimitiveWithRawVTable:
Copy
+ Debug
+ 'static
+ ProxiedWithPresence
+ for<'msg> Proxied<View<'msg> = Self, Mut<'msg> = PrimitiveMut<'msg, Self>>
{
}
impl<T: PrimitiveWithRawVTable> ProxiedWithRawVTable for T {
type VTable = PrimitiveVTable<T>;
fn make_view(_private: Private, mut_inner: InnerPrimitiveMut<'_, Self>) -> Self {
mut_inner.get()
}
fn make_mut(_private: Private, inner: InnerPrimitiveMut<'_, Self>) -> PrimitiveMut<'_, Self> {
// SAFETY: `inner` is valid for the necessary lifetime and `T` as promised by
// the caller of `InnerPrimitiveMut::new`.
unsafe { PrimitiveMut::from_inner(Private, inner) }
}
}
impl<T: PrimitiveWithRawVTable> ProxiedWithRawOptionalVTable for T {
type OptionalVTable = PrimitiveOptionalMutVTable<T>;
fn upcast_vtable(
_private: Private,
optional_vtable: &'static Self::OptionalVTable,
) -> &'static Self::VTable {
&optional_vtable.base
}
}
impl<T: PrimitiveWithRawVTable> RawVTableMutator<'_, T> {
pub(crate) fn get(self) -> T {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by
// the caller of `new`.
unsafe { (self.vtable.getter)(self.msg_ref.msg()) }
}
/// # Safety
/// - `msg_ref` must be valid for the lifetime of `RawVTableMutator`.
pub(crate) unsafe fn set(self, val: T) {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by
// the caller of `new`.
unsafe { (self.vtable.setter)(self.msg_ref.msg(), val) }
}
}
impl<'msg, T: PrimitiveWithRawVTable> RawVTableOptionalMutatorData<'msg, T> {
pub(crate) fn set_absent_to_default(self) -> Self {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as
// promised by the caller of `new`.
self.set(self.vtable.default)
}
pub(crate) fn set(self, val: T) -> Self {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as
// promised by the caller of `new`.
unsafe { (self.vtable.base.setter)(self.msg_ref.msg(), val) }
self
}
pub(crate) fn clear(self) -> Self {
// SAFETY:
// - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as
// promised by the caller of `new`.
unsafe { (self.vtable.clearer)(self.msg_ref.msg()) }
self
}
}

@ -27,27 +27,28 @@ void RepeatedScalar::InMsgImpl(Context<FieldDescriptor> field) const {
if (field.is_upb()) {
field.Emit({}, R"rs(
pub fn r#$field$(&self) -> $pb$::RepeatedView<'_, $Scalar$> {
let inner = unsafe {
unsafe {
$getter_thunk$(
self.inner.msg,
/* optional size pointer */ std::ptr::null(),
) }
.map_or_else(|| unsafe {$pbr$::empty_array()}, |raw| {
$pbr$::RepeatedFieldInner{ raw, arena: &self.inner.arena }
});
$pb$::RepeatedView::from_inner($pbi$::Private, inner)
.map_or_else(
$pbr$::empty_array::<$Scalar$>,
|raw| unsafe {
$pb$::RepeatedView::from_raw($pbi$::Private, raw)
}
)
}
)rs");
} else {
field.Emit({}, R"rs(
pub fn r#$field$(&self) -> $pb$::RepeatedView<'_, $Scalar$> {
$pb$::RepeatedView::from_inner(
$pbi$::Private,
$pbr$::RepeatedFieldInner{
raw: unsafe { $getter_thunk$(self.inner.msg) },
_phantom: std::marker::PhantomData,
},
)
unsafe {
$pb$::RepeatedView::from_raw(
$pbi$::Private,
unsafe { $getter_thunk$(self.inner.msg) },
)
}
}
)rs");
}
@ -58,29 +59,34 @@ void RepeatedScalar::InMsgImpl(Context<FieldDescriptor> field) const {
if (field.is_upb()) {
field.Emit({}, R"rs(
pub fn r#$field$_mut(&mut self) -> $pb$::RepeatedMut<'_, $Scalar$> {
$pb$::RepeatedMut::from_inner(
$pbi$::Private,
$pbr$::RepeatedFieldInner{
raw: unsafe { $getter_mut_thunk$(
self.inner.msg,
/* optional size pointer */ std::ptr::null(),
self.inner.arena.raw(),
) },
arena: &self.inner.arena,
},
)
unsafe {
$pb$::RepeatedMut::from_inner(
$pbi$::Private,
$pbr$::InnerRepeatedMut::new(
$pbi$::Private,
$getter_mut_thunk$(
self.inner.msg,
/* optional size pointer */ std::ptr::null(),
self.inner.arena.raw(),
),
&self.inner.arena,
),
)
}
}
)rs");
} else {
field.Emit({}, R"rs(
pub fn r#$field$_mut(&mut self) -> $pb$::RepeatedMut<'_, $Scalar$> {
$pb$::RepeatedMut::from_inner(
$pbi$::Private,
$pbr$::RepeatedFieldInner{
raw: unsafe { $getter_mut_thunk$(self.inner.msg)},
_phantom: std::marker::PhantomData,
},
)
unsafe {
$pb$::RepeatedMut::from_inner(
$pbi$::Private,
$pbr$::InnerRepeatedMut::new(
$pbi$::Private,
$getter_mut_thunk$(self.inner.msg),
),
)
}
}
)rs");
}

@ -85,18 +85,23 @@ void SingularScalar::InMsgImpl(Context<FieldDescriptor> field) const {
$setter_thunk$,
);
$pb$::PrimitiveMut::from_inner(
$pbi$::Private,
unsafe {
// SAFETY:
// - The message is valid for the output lifetime.
// - The vtable is valid for the field.
// - There is no way to mutate the element for the output
// lifetime except through this mutator.
unsafe {
$pb$::PrimitiveMut::from_inner(
$pbi$::Private,
$pbi$::RawVTableMutator::new(
$pbi$::Private,
$pbr$::MutatorMessageRef::new(
$pbi$::Private, &mut self.inner
),
&VTABLE,
)
},
)
),
)
}
}
)rs");
}

@ -316,13 +316,16 @@ void GetterForViewOrMut(Context<FieldDescriptor> field, bool is_mut) {
$pbi$::Private,
$getter_thunk$,
$setter_thunk$);
$pb$::PrimitiveMut::from_inner(
$pbi$::Private,
unsafe {
$pbi$::RawVTableMutator::new($pbi$::Private,
self.inner,
&VTABLE)
})
unsafe {
$pb$::PrimitiveMut::from_inner(
$pbi$::Private,
$pbi$::RawVTableMutator::new(
$pbi$::Private,
self.inner,
&VTABLE
),
)
}
}
)rs");
}

Loading…
Cancel
Save