Migrate Repeated::{push, set} and Map::insert to use the IntoProxied trait.

* The public Repeated::{push, set} and Map::insert methods now accept any value that implements IntoProxied<T>, allowing us to move owned values instead of copying them.
  * This change also updates the FFI layer for strings/bytes in the repeated and maps thunks to accept a std::string* that can be moved rather than a PtrAndLen type that needs to be copied.
  * Tests are updated to no longer .as_view() when setting a message / string on a repeated / map field. The IntoProxied trait makes calling .as_view() obsolete.

PiperOrigin-RevId: 650580788
pull/17307/head
Jakob Buchgraber 5 months ago committed by Copybara-Service
parent e2c4d0f27e
commit 0d6e9794d1
  1. 77
      rust/cpp.rs
  2. 31
      rust/cpp_kernel/map.cc
  3. 163
      rust/cpp_kernel/map.h
  4. 79
      rust/cpp_kernel/repeated.cc
  5. 24
      rust/map.rs
  6. 9
      rust/primitive.rs
  7. 97
      rust/repeated.rs
  8. 6
      rust/string.rs
  9. 8
      rust/test/shared/accessors_map_test.rs
  10. 19
      rust/test/shared/accessors_repeated_test.rs
  11. 2
      rust/test/shared/edition2023_test.rs
  12. 4
      rust/test/upb/string_ctypes_test.rs
  13. 54
      rust/upb.rs
  14. 30
      src/google/protobuf/compiler/rust/enum.cc
  15. 79
      src/google/protobuf/compiler/rust/message.cc

@ -9,7 +9,7 @@
use crate::__internal::{Enum, Private}; use crate::__internal::{Enum, Private};
use crate::{ use crate::{
Map, MapIter, Mut, ProtoBytes, ProtoStr, ProtoString, Proxied, ProxiedInMapValue, IntoProxied, Map, MapIter, Mut, ProtoBytes, ProtoStr, ProtoString, Proxied, ProxiedInMapValue,
ProxiedInRepeated, Repeated, RepeatedMut, RepeatedView, View, ProxiedInRepeated, Repeated, RepeatedMut, RepeatedView, View,
}; };
use core::fmt::Debug; use core::fmt::Debug;
@ -18,7 +18,7 @@ use std::convert::identity;
use std::ffi::{c_int, c_void}; use std::ffi::{c_int, c_void};
use std::fmt; use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::MaybeUninit; use std::mem::{ManuallyDrop, MaybeUninit};
use std::ops::Deref; use std::ops::Deref;
use std::ptr::{self, NonNull}; use std::ptr::{self, NonNull};
use std::slice; use std::slice;
@ -393,20 +393,27 @@ impl<'msg> InnerRepeatedMut<'msg> {
} }
trait CppTypeConversions: Proxied { trait CppTypeConversions: Proxied {
type InsertElemType;
type ElemType; type ElemType;
fn elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self>; fn elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self>;
fn into_insertelem(v: Self) -> Self::InsertElemType;
} }
macro_rules! impl_cpp_type_conversions_for_scalars { macro_rules! impl_cpp_type_conversions_for_scalars {
($($t:ty),* $(,)?) => { ($($t:ty),* $(,)?) => {
$( $(
impl CppTypeConversions for $t { impl CppTypeConversions for $t {
type InsertElemType = Self;
type ElemType = Self; type ElemType = Self;
fn elem_to_view<'msg>(v: Self) -> View<'msg, Self> { fn elem_to_view<'msg>(v: Self) -> View<'msg, Self> {
v v
} }
fn into_insertelem(v: Self) -> Self {
v
}
} }
)* )*
} }
@ -415,19 +422,31 @@ macro_rules! impl_cpp_type_conversions_for_scalars {
impl_cpp_type_conversions_for_scalars!(i32, u32, i64, u64, f32, f64, bool); impl_cpp_type_conversions_for_scalars!(i32, u32, i64, u64, f32, f64, bool);
impl CppTypeConversions for ProtoString { impl CppTypeConversions for ProtoString {
type InsertElemType = CppStdString;
type ElemType = PtrAndLen; type ElemType = PtrAndLen;
fn elem_to_view<'msg>(v: PtrAndLen) -> View<'msg, ProtoString> { fn elem_to_view<'msg>(v: PtrAndLen) -> View<'msg, ProtoString> {
ptrlen_to_str(v) ptrlen_to_str(v)
} }
fn into_insertelem(v: Self) -> CppStdString {
let v = ManuallyDrop::new(v);
v.inner.owned_ptr
}
} }
impl CppTypeConversions for ProtoBytes { impl CppTypeConversions for ProtoBytes {
type InsertElemType = CppStdString;
type ElemType = PtrAndLen; type ElemType = PtrAndLen;
fn elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self> { fn elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self> {
ptrlen_to_bytes(v) ptrlen_to_bytes(v)
} }
fn into_insertelem(v: Self) -> CppStdString {
let v = ManuallyDrop::new(v);
v.inner.owned_ptr
}
} }
macro_rules! impl_repeated_primitives { macro_rules! impl_repeated_primitives {
@ -446,7 +465,7 @@ macro_rules! impl_repeated_primitives {
extern "C" { extern "C" {
fn $new_thunk() -> RawRepeatedField; fn $new_thunk() -> RawRepeatedField;
fn $free_thunk(f: RawRepeatedField); fn $free_thunk(f: RawRepeatedField);
fn $add_thunk(f: RawRepeatedField, v: <$t as CppTypeConversions>::ElemType); fn $add_thunk(f: RawRepeatedField, v: <$t as CppTypeConversions>::InsertElemType);
fn $size_thunk(f: RawRepeatedField) -> usize; fn $size_thunk(f: RawRepeatedField) -> usize;
fn $get_thunk( fn $get_thunk(
f: RawRepeatedField, f: RawRepeatedField,
@ -454,7 +473,7 @@ macro_rules! impl_repeated_primitives {
fn $set_thunk( fn $set_thunk(
f: RawRepeatedField, f: RawRepeatedField,
i: usize, i: usize,
v: <$t as CppTypeConversions>::ElemType); v: <$t as CppTypeConversions>::InsertElemType);
fn $clear_thunk(f: RawRepeatedField); fn $clear_thunk(f: RawRepeatedField);
fn $copy_from_thunk(src: RawRepeatedField, dst: RawRepeatedField); fn $copy_from_thunk(src: RawRepeatedField, dst: RawRepeatedField);
fn $reserve_thunk( fn $reserve_thunk(
@ -480,8 +499,8 @@ macro_rules! impl_repeated_primitives {
unsafe { $size_thunk(f.as_raw(Private)) } unsafe { $size_thunk(f.as_raw(Private)) }
} }
#[inline] #[inline]
fn repeated_push(mut f: Mut<Repeated<$t>>, v: View<$t>) { fn repeated_push(mut f: Mut<Repeated<$t>>, v: impl IntoProxied<$t>) {
unsafe { $add_thunk(f.as_raw(Private), v.into()) } unsafe { $add_thunk(f.as_raw(Private), <$t as CppTypeConversions>::into_insertelem(v.into_proxied(Private))) }
} }
#[inline] #[inline]
fn repeated_clear(mut f: Mut<Repeated<$t>>) { fn repeated_clear(mut f: Mut<Repeated<$t>>) {
@ -493,8 +512,8 @@ macro_rules! impl_repeated_primitives {
unsafe { $get_thunk(f.as_raw(Private), i) }) unsafe { $get_thunk(f.as_raw(Private), i) })
} }
#[inline] #[inline]
unsafe fn repeated_set_unchecked(mut f: Mut<Repeated<$t>>, i: usize, v: View<$t>) { unsafe fn repeated_set_unchecked(mut f: Mut<Repeated<$t>>, i: usize, v: impl IntoProxied<$t>) {
unsafe { $set_thunk(f.as_raw(Private), i, v.into()) } unsafe { $set_thunk(f.as_raw(Private), i, <$t as CppTypeConversions>::into_insertelem(v.into_proxied(Private))) }
} }
#[inline] #[inline]
fn repeated_copy_from(src: View<Repeated<$t>>, mut dest: Mut<Repeated<$t>>) { fn repeated_copy_from(src: View<Repeated<$t>>, mut dest: Mut<Repeated<$t>>) {
@ -686,18 +705,18 @@ extern "C" {
} }
macro_rules! impl_ProxiedInMapValue_for_non_generated_value_types { macro_rules! impl_ProxiedInMapValue_for_non_generated_value_types {
($key_t:ty, $ffi_key_t:ty, $to_ffi_key:expr, $from_ffi_key:expr, for $($t:ty, $ffi_t:ty, $to_ffi_value:expr, $from_ffi_value:expr;)*) => { ($key_t:ty, $ffi_key_t:ty, $to_ffi_key:expr, $from_ffi_key:expr, for $($t:ty, $ffi_view_t:ty, $ffi_value_t:ty, $to_ffi_value:expr, $from_ffi_value:expr;)*) => {
paste! { $( paste! { $(
extern "C" { extern "C" {
fn [< proto2_rust_thunk_Map_ $key_t _ $t _new >]() -> RawMap; fn [< proto2_rust_thunk_Map_ $key_t _ $t _new >]() -> RawMap;
fn [< proto2_rust_thunk_Map_ $key_t _ $t _free >](m: RawMap); fn [< proto2_rust_thunk_Map_ $key_t _ $t _free >](m: RawMap);
fn [< proto2_rust_thunk_Map_ $key_t _ $t _clear >](m: RawMap); fn [< proto2_rust_thunk_Map_ $key_t _ $t _clear >](m: RawMap);
fn [< proto2_rust_thunk_Map_ $key_t _ $t _size >](m: RawMap) -> usize; fn [< proto2_rust_thunk_Map_ $key_t _ $t _size >](m: RawMap) -> usize;
fn [< proto2_rust_thunk_Map_ $key_t _ $t _insert >](m: RawMap, key: $ffi_key_t, value: $ffi_t) -> bool; fn [< proto2_rust_thunk_Map_ $key_t _ $t _insert >](m: RawMap, key: $ffi_key_t, value: $ffi_value_t) -> bool;
fn [< proto2_rust_thunk_Map_ $key_t _ $t _get >](m: RawMap, key: $ffi_key_t, value: *mut $ffi_t) -> bool; fn [< proto2_rust_thunk_Map_ $key_t _ $t _get >](m: RawMap, key: $ffi_key_t, value: *mut $ffi_view_t) -> bool;
fn [< proto2_rust_thunk_Map_ $key_t _ $t _iter >](m: RawMap) -> UntypedMapIterator; fn [< proto2_rust_thunk_Map_ $key_t _ $t _iter >](m: RawMap) -> UntypedMapIterator;
fn [< proto2_rust_thunk_Map_ $key_t _ $t _iter_get >](iter: &mut UntypedMapIterator, key: *mut $ffi_key_t, value: *mut $ffi_t); fn [< proto2_rust_thunk_Map_ $key_t _ $t _iter_get >](iter: &mut UntypedMapIterator, key: *mut $ffi_key_t, value: *mut $ffi_view_t);
fn [< proto2_rust_thunk_Map_ $key_t _ $t _remove >](m: RawMap, key: $ffi_key_t, value: *mut $ffi_t) -> bool; fn [< proto2_rust_thunk_Map_ $key_t _ $t _remove >](m: RawMap, key: $ffi_key_t, value: *mut $ffi_view_t) -> bool;
} }
impl ProxiedInMapValue<$key_t> for $t { impl ProxiedInMapValue<$key_t> for $t {
@ -728,9 +747,9 @@ macro_rules! impl_ProxiedInMapValue_for_non_generated_value_types {
unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _size >](map.as_raw(Private)) } unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _size >](map.as_raw(Private)) }
} }
fn map_insert(mut map: Mut<'_, Map<$key_t, Self>>, key: View<'_, $key_t>, value: View<'_, Self>) -> bool { fn map_insert(mut map: Mut<'_, Map<$key_t, Self>>, key: View<'_, $key_t>, value: impl IntoProxied<Self>) -> bool {
let ffi_key = $to_ffi_key(key); let ffi_key = $to_ffi_key(key);
let ffi_value = $to_ffi_value(value); let ffi_value = $to_ffi_value(value.into_proxied(Private));
unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _insert >](map.as_raw(Private), ffi_key, ffi_value) } unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _insert >](map.as_raw(Private), ffi_key, ffi_value) }
} }
@ -797,8 +816,14 @@ fn ptrlen_to_str<'msg>(val: PtrAndLen) -> &'msg ProtoStr {
unsafe { ProtoStr::from_utf8_unchecked(val.as_ref()) } unsafe { ProtoStr::from_utf8_unchecked(val.as_ref()) }
} }
fn bytes_to_ptrlen(val: &[u8]) -> PtrAndLen { fn protostr_into_cppstdstring(val: ProtoString) -> CppStdString {
val.into() let m = ManuallyDrop::new(val);
m.inner.owned_ptr
}
fn protobytes_into_cppstdstring(val: ProtoBytes) -> CppStdString {
let m = ManuallyDrop::new(val);
m.inner.owned_ptr
} }
// Warning: this function is unsound on its own! `val.as_ref()` must be safe to // Warning: this function is unsound on its own! `val.as_ref()` must be safe to
@ -813,15 +838,15 @@ macro_rules! impl_ProxiedInMapValue_for_key_types {
$( $(
impl_ProxiedInMapValue_for_non_generated_value_types!( impl_ProxiedInMapValue_for_non_generated_value_types!(
$t, $ffi_t, $to_ffi_key, $from_ffi_key, for $t, $ffi_t, $to_ffi_key, $from_ffi_key, for
f32, f32, identity, identity; f32, f32, f32, identity, identity;
f64, f64, identity, identity; f64, f64, f64, identity, identity;
i32, i32, identity, identity; i32, i32, i32, identity, identity;
u32, u32, identity, identity; u32, u32, u32, identity, identity;
i64, i64, identity, identity; i64, i64, i64, identity, identity;
u64, u64, identity, identity; u64, u64, u64, identity, identity;
bool, bool, identity, identity; bool, bool, bool, identity, identity;
ProtoString, PtrAndLen, str_to_ptrlen, ptrlen_to_str; ProtoString, PtrAndLen, CppStdString, protostr_into_cppstdstring, ptrlen_to_str;
ProtoBytes, PtrAndLen, bytes_to_ptrlen, ptrlen_to_bytes; ProtoBytes, PtrAndLen, CppStdString, protobytes_into_cppstdstring, ptrlen_to_bytes;
); );
)* )*
} }

@ -2,6 +2,7 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <utility>
#include "google/protobuf/map.h" #include "google/protobuf/map.h"
#include "rust/cpp_kernel/strings.h" #include "rust/cpp_kernel/strings.h"
@ -13,27 +14,27 @@ void proto2_rust_thunk_UntypedMapIterator_increment(
iter->PlusPlus(); iter->PlusPlus();
} }
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int32_t, i32, int32_t, value, __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int32_t, i32, int32_t,
cpp_value); int32_t, value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint32_t, u32, uint32_t, __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint32_t, u32, uint32_t,
uint32_t, value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(float, f32, float, float,
value, cpp_value); value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(float, f32, float, value, __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(double, f64, double, double,
cpp_value); value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(double, f64, double, value, __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(bool, bool, bool, bool,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(bool, bool, bool, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint64_t, u64, uint64_t,
value, cpp_value); value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int64_t, i64, int64_t, value, __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint64_t, u64, uint64_t,
cpp_value); uint64_t, value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int64_t, i64, int64_t,
int64_t, value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE( __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(
std::string, ProtoBytes, google::protobuf::rust::PtrAndLen, std::string, ProtoBytes, google::protobuf::rust::PtrAndLen, std::string*,
std::string(value.ptr, value.len), std::move(*value),
google::protobuf::rust::PtrAndLen(cpp_value.data(), cpp_value.size())); google::protobuf::rust::PtrAndLen(cpp_value.data(), cpp_value.size()));
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE( __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(
std::string, ProtoString, google::protobuf::rust::PtrAndLen, std::string, ProtoString, google::protobuf::rust::PtrAndLen, std::string*,
std::string(value.ptr, value.len), std::move(*value),
google::protobuf::rust::PtrAndLen(cpp_value.data(), cpp_value.size())); google::protobuf::rust::PtrAndLen(cpp_value.data(), cpp_value.size()));
} // extern "C" } // extern "C"

@ -2,89 +2,90 @@
#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__ #define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__
// Defines concrete thunks to access typed map methods from Rust. // Defines concrete thunks to access typed map methods from Rust.
#define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \ #define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \
key_ty, rust_key_ty, ffi_key_ty, to_cpp_key, to_ffi_key, value_ty, \ key_ty, rust_key_ty, ffi_key_ty, to_cpp_key, to_ffi_key, value_ty, \
rust_value_ty, ffi_value_ty, to_cpp_value, to_ffi_value) \ rust_value_ty, ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value) \
google::protobuf::Map<key_ty, value_ty>* \ google::protobuf::Map<key_ty, value_ty>* \
proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_new() { \ proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_new() { \
return new google::protobuf::Map<key_ty, value_ty>(); \ return new google::protobuf::Map<key_ty, value_ty>(); \
} \ } \
void proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_free( \ void proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_free( \
google::protobuf::Map<key_ty, value_ty>* m) { \ google::protobuf::Map<key_ty, value_ty>* m) { \
delete m; \ delete m; \
} \ } \
void proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_clear( \ void proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_clear( \
google::protobuf::Map<key_ty, value_ty>* m) { \ google::protobuf::Map<key_ty, value_ty>* m) { \
m->clear(); \ m->clear(); \
} \ } \
size_t proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_size( \ size_t proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_size( \
const google::protobuf::Map<key_ty, value_ty>* m) { \ const google::protobuf::Map<key_ty, value_ty>* m) { \
return m->size(); \ return m->size(); \
} \ } \
bool proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_insert( \ bool proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_insert( \
google::protobuf::Map<key_ty, value_ty>* m, ffi_key_ty key, ffi_value_ty value) { \ google::protobuf::Map<key_ty, value_ty>* m, ffi_key_ty key, ffi_value_ty value) { \
auto iter_and_inserted = m->try_emplace(to_cpp_key, to_cpp_value); \ auto iter_and_inserted = m->try_emplace(to_cpp_key, to_cpp_value); \
if (!iter_and_inserted.second) { \ if (!iter_and_inserted.second) { \
iter_and_inserted.first->second = to_cpp_value; \ iter_and_inserted.first->second = to_cpp_value; \
} \ } \
return iter_and_inserted.second; \ return iter_and_inserted.second; \
} \ } \
bool proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_get( \ bool proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_get( \
const google::protobuf::Map<key_ty, value_ty>* m, ffi_key_ty key, \ const google::protobuf::Map<key_ty, value_ty>* m, ffi_key_ty key, \
ffi_value_ty* value) { \ ffi_view_ty* value) { \
auto cpp_key = to_cpp_key; \ auto cpp_key = to_cpp_key; \
auto it = m->find(cpp_key); \ auto it = m->find(cpp_key); \
if (it == m->end()) { \ if (it == m->end()) { \
return false; \ return false; \
} \ } \
auto& cpp_value = it->second; \ auto& cpp_value = it->second; \
*value = to_ffi_value; \ *value = to_ffi_value; \
return true; \ return true; \
} \ } \
google::protobuf::internal::UntypedMapIterator \ google::protobuf::internal::UntypedMapIterator \
proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_iter( \ proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_iter( \
const google::protobuf::Map<key_ty, value_ty>* m) { \ const google::protobuf::Map<key_ty, value_ty>* m) { \
return google::protobuf::internal::UntypedMapIterator::FromTyped(m->cbegin()); \ return google::protobuf::internal::UntypedMapIterator::FromTyped(m->cbegin()); \
} \ } \
void proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_iter_get( \ void proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_iter_get( \
const google::protobuf::internal::UntypedMapIterator* iter, ffi_key_ty* key, \ const google::protobuf::internal::UntypedMapIterator* iter, ffi_key_ty* key, \
ffi_value_ty* value) { \ ffi_view_ty* value) { \
auto typed_iter = \ auto typed_iter = \
iter->ToTyped<google::protobuf::Map<key_ty, value_ty>::const_iterator>(); \ iter->ToTyped<google::protobuf::Map<key_ty, value_ty>::const_iterator>(); \
const auto& cpp_key = typed_iter->first; \ const auto& cpp_key = typed_iter->first; \
const auto& cpp_value = typed_iter->second; \ const auto& cpp_value = typed_iter->second; \
*key = to_ffi_key; \ *key = to_ffi_key; \
*value = to_ffi_value; \ *value = to_ffi_value; \
} \ } \
bool proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_remove( \ bool proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_remove( \
google::protobuf::Map<key_ty, value_ty>* m, ffi_key_ty key, ffi_value_ty* value) { \ google::protobuf::Map<key_ty, value_ty>* m, ffi_key_ty key, ffi_view_ty* value) { \
auto cpp_key = to_cpp_key; \ auto cpp_key = to_cpp_key; \
auto num_removed = m->erase(cpp_key); \ auto num_removed = m->erase(cpp_key); \
return num_removed > 0; \ return num_removed > 0; \
} }
// Defines the map thunks for all supported key types for a given value type. // Defines the map thunks for all supported key types for a given value type.
#define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE( \ #define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE( \
value_ty, rust_value_ty, ffi_value_ty, to_cpp_value, to_ffi_value) \ value_ty, rust_value_ty, ffi_view_ty, ffi_value_ty, to_cpp_value, \
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS(int32_t, i32, int32_t, key, cpp_key, \ to_ffi_value) \
value_ty, rust_value_ty, ffi_value_ty, \ __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \
to_cpp_value, to_ffi_value); \ int32_t, i32, int32_t, key, cpp_key, value_ty, rust_value_ty, \
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS(uint32_t, u32, uint32_t, key, cpp_key, \ ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value); \
value_ty, rust_value_ty, ffi_value_ty, \ __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \
to_cpp_value, to_ffi_value); \ uint32_t, u32, uint32_t, key, cpp_key, value_ty, rust_value_ty, \
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS(bool, bool, bool, key, cpp_key, \ ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value); \
value_ty, rust_value_ty, ffi_value_ty, \ __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \
to_cpp_value, to_ffi_value); \ bool, bool, bool, key, cpp_key, value_ty, rust_value_ty, ffi_view_ty, \
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS(uint64_t, u64, uint64_t, key, cpp_key, \ ffi_value_ty, to_cpp_value, to_ffi_value); \
value_ty, rust_value_ty, ffi_value_ty, \ __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \
to_cpp_value, to_ffi_value); \ uint64_t, u64, uint64_t, key, cpp_key, value_ty, rust_value_ty, \
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS(int64_t, i64, int64_t, key, cpp_key, \ ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value); \
value_ty, rust_value_ty, ffi_value_ty, \ __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \
to_cpp_value, to_ffi_value); \ int64_t, i64, int64_t, key, cpp_key, value_ty, rust_value_ty, \
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \ ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value); \
std::string, ProtoString, google::protobuf::rust::PtrAndLen, \ __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \
std::string(key.ptr, key.len), \ std::string, ProtoString, google::protobuf::rust::PtrAndLen, \
google::protobuf::rust::PtrAndLen(cpp_key.data(), cpp_key.size()), value_ty, \ std::string(key.ptr, key.len), \
rust_value_ty, ffi_value_ty, to_cpp_value, to_ffi_value); google::protobuf::rust::PtrAndLen(cpp_key.data(), cpp_key.size()), value_ty, \
rust_value_ty, ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value);
#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__ #endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__

@ -2,6 +2,7 @@
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <utility>
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
#include "google/protobuf/message_lite.h" #include "google/protobuf/message_lite.h"
@ -56,45 +57,45 @@ expose_repeated_field_methods(uint64_t, u64);
expose_repeated_field_methods(int64_t, i64); expose_repeated_field_methods(int64_t, i64);
#undef expose_repeated_field_methods #undef expose_repeated_field_methods
#define expose_repeated_ptr_field_methods(ty) \ #define expose_repeated_ptr_field_methods(ty) \
google::protobuf::RepeatedPtrField<std::string>* \ google::protobuf::RepeatedPtrField<std::string>* \
proto2_rust_RepeatedField_##ty##_new() { \ proto2_rust_RepeatedField_##ty##_new() { \
return new google::protobuf::RepeatedPtrField<std::string>(); \ return new google::protobuf::RepeatedPtrField<std::string>(); \
} \ } \
void proto2_rust_RepeatedField_##ty##_free( \ void proto2_rust_RepeatedField_##ty##_free( \
google::protobuf::RepeatedPtrField<std::string>* r) { \ google::protobuf::RepeatedPtrField<std::string>* r) { \
delete r; \ delete r; \
} \ } \
void proto2_rust_RepeatedField_##ty##_add( \ void proto2_rust_RepeatedField_##ty##_add( \
google::protobuf::RepeatedPtrField<std::string>* r, google::protobuf::rust::PtrAndLen val) { \ google::protobuf::RepeatedPtrField<std::string>* r, std::string* val) { \
r->Add(std::string(val.ptr, val.len)); \ r->AddAllocated(val); \
} \ } \
size_t proto2_rust_RepeatedField_##ty##_size( \ size_t proto2_rust_RepeatedField_##ty##_size( \
google::protobuf::RepeatedPtrField<std::string>* r) { \ google::protobuf::RepeatedPtrField<std::string>* r) { \
return r->size(); \ return r->size(); \
} \ } \
google::protobuf::rust::PtrAndLen proto2_rust_RepeatedField_##ty##_get( \ google::protobuf::rust::PtrAndLen proto2_rust_RepeatedField_##ty##_get( \
google::protobuf::RepeatedPtrField<std::string>* r, size_t index) { \ google::protobuf::RepeatedPtrField<std::string>* r, size_t index) { \
const std::string& s = r->Get(index); \ const std::string& s = r->Get(index); \
return google::protobuf::rust::PtrAndLen(s.data(), s.size()); \ return google::protobuf::rust::PtrAndLen(s.data(), s.size()); \
} \ } \
void proto2_rust_RepeatedField_##ty##_set( \ void proto2_rust_RepeatedField_##ty##_set( \
google::protobuf::RepeatedPtrField<std::string>* r, size_t index, \ google::protobuf::RepeatedPtrField<std::string>* r, size_t index, \
google::protobuf::rust::PtrAndLen val) { \ std::string* val) { \
*r->Mutable(index) = std::string(val.ptr, val.len); \ *r->Mutable(index) = std::move(*val); \
} \ } \
void proto2_rust_RepeatedField_##ty##_copy_from( \ void proto2_rust_RepeatedField_##ty##_copy_from( \
const google::protobuf::RepeatedPtrField<std::string>* src, \ const google::protobuf::RepeatedPtrField<std::string>* src, \
google::protobuf::RepeatedPtrField<std::string>* dst) { \ google::protobuf::RepeatedPtrField<std::string>* dst) { \
dst->CopyFrom(*src); \ dst->CopyFrom(*src); \
} \ } \
void proto2_rust_RepeatedField_##ty##_clear( \ void proto2_rust_RepeatedField_##ty##_clear( \
google::protobuf::RepeatedPtrField<std::string>* r) { \ google::protobuf::RepeatedPtrField<std::string>* r) { \
r->Clear(); \ r->Clear(); \
} \ } \
void proto2_rust_RepeatedField_##ty##_reserve( \ void proto2_rust_RepeatedField_##ty##_reserve( \
google::protobuf::RepeatedPtrField<std::string>* r, size_t additional) { \ google::protobuf::RepeatedPtrField<std::string>* r, size_t additional) { \
r->Reserve(r->size() + additional); \ r->Reserve(r->size() + additional); \
} }
expose_repeated_ptr_field_methods(ProtoString); expose_repeated_ptr_field_methods(ProtoString);

@ -6,7 +6,7 @@
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
use crate::{ use crate::{
Mut, MutProxied, MutProxy, Proxied, View, ViewProxy, IntoProxied, Mut, MutProxied, MutProxy, Proxied, View, ViewProxy,
__internal::Private, __internal::Private,
__runtime::{InnerMap, InnerMapMut, RawMap, RawMapIter}, __runtime::{InnerMap, InnerMapMut, RawMap, RawMapIter},
}; };
@ -92,7 +92,11 @@ where
fn map_clear(map: Mut<'_, Map<K, Self>>); fn map_clear(map: Mut<'_, Map<K, Self>>);
fn map_len(map: View<'_, Map<K, Self>>) -> usize; fn map_len(map: View<'_, Map<K, Self>>) -> usize;
fn map_insert(map: Mut<'_, Map<K, Self>>, key: View<'_, K>, value: View<'_, Self>) -> bool; fn map_insert(
map: Mut<'_, Map<K, Self>>,
key: View<'_, K>,
value: impl IntoProxied<Self>,
) -> bool;
fn map_get<'a>(map: View<'a, Map<K, Self>>, key: View<'_, K>) -> Option<View<'a, Self>>; fn map_get<'a>(map: View<'a, Map<K, Self>>, key: View<'_, K>) -> Option<View<'a, Self>>;
fn map_remove(map: Mut<'_, Map<K, Self>>, key: View<'_, K>) -> bool; fn map_remove(map: Mut<'_, Map<K, Self>>, key: View<'_, K>) -> bool;
@ -283,16 +287,11 @@ where
/// Adds a key-value pair to the map. /// Adds a key-value pair to the map.
/// ///
/// Returns `true` if the entry was newly inserted. /// Returns `true` if the entry was newly inserted.
pub fn insert<'a, 'b>( pub fn insert<'a>(&mut self, key: impl Into<View<'a, K>>, value: impl IntoProxied<V>) -> bool
&mut self,
key: impl Into<View<'a, K>>,
value: impl Into<View<'b, V>>,
) -> bool
where where
K: 'a, K: 'a,
V: 'b,
{ {
V::map_insert(self.as_mut(), key.into(), value.into()) V::map_insert(self.as_mut(), key.into(), value)
} }
pub fn remove<'a>(&mut self, key: impl Into<View<'a, K>>) -> bool pub fn remove<'a>(&mut self, key: impl Into<View<'a, K>>) -> bool
@ -313,12 +312,11 @@ where
V::map_get(self.as_view(), key.into()) V::map_get(self.as_view(), key.into())
} }
pub fn copy_from<'a, 'b>( pub fn copy_from<'a>(
&mut self, &mut self,
src: impl IntoIterator<Item = (impl Into<View<'a, K>>, impl Into<View<'b, V>>)>, src: impl IntoIterator<Item = (impl Into<View<'a, K>>, impl IntoProxied<V>)>,
) where ) where
K: 'a, K: 'a,
V: 'b,
{ {
//TODO //TODO
self.clear(); self.clear();
@ -446,7 +444,7 @@ where
K: Proxied + ?Sized + 'msg + 'k, K: Proxied + ?Sized + 'msg + 'k,
V: ProxiedInMapValue<K> + ?Sized + 'msg + 'v, V: ProxiedInMapValue<K> + ?Sized + 'msg + 'v,
KView: Into<View<'k, K>>, KView: Into<View<'k, K>>,
VView: Into<View<'v, V>>, VView: IntoProxied<V>,
{ {
fn extend<T: IntoIterator<Item = (KView, VView)>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = (KView, VView)>>(&mut self, iter: T) {
for (k, v) in iter.into_iter() { for (k, v) in iter.into_iter() {

@ -4,7 +4,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at // license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
use crate::{Proxied, View, ViewProxy}; use crate::__internal::Private;
use crate::{IntoProxied, Proxied, View, ViewProxy};
macro_rules! impl_singular_primitives { macro_rules! impl_singular_primitives {
($($t:ty),*) => { ($($t:ty),*) => {
@ -25,6 +26,12 @@ macro_rules! impl_singular_primitives {
} }
} }
impl IntoProxied<$t> for $t {
fn into_proxied(self, _private: Private) -> $t {
self
}
}
// ProxiedInRepeated is implemented in {cpp,upb}.rs // ProxiedInRepeated is implemented in {cpp,upb}.rs
)* )*
} }

@ -22,44 +22,44 @@ use crate::{
/// Views the elements in a `repeated` field of `T`. /// Views the elements in a `repeated` field of `T`.
#[repr(transparent)] #[repr(transparent)]
pub struct RepeatedView<'msg, T: ?Sized> { pub struct RepeatedView<'msg, T> {
// This does not need to carry an arena in upb, so it can be just the raw repeated field // This does not need to carry an arena in upb, so it can be just the raw repeated field
raw: RawRepeatedField, raw: RawRepeatedField,
_phantom: PhantomData<&'msg T>, _phantom: PhantomData<&'msg T>,
} }
impl<'msg, T: ?Sized> Copy for RepeatedView<'msg, T> {} impl<'msg, T> Copy for RepeatedView<'msg, T> {}
impl<'msg, T: ?Sized> Clone for RepeatedView<'msg, T> { impl<'msg, T> Clone for RepeatedView<'msg, T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
unsafe impl<'msg, T: ?Sized> Sync for RepeatedView<'msg, T> {} unsafe impl<'msg, T> Sync for RepeatedView<'msg, T> {}
unsafe impl<'msg, T: ?Sized> Send for RepeatedView<'msg, T> {} unsafe impl<'msg, T> Send for RepeatedView<'msg, T> {}
impl<'msg, T: ?Sized> Debug for RepeatedView<'msg, T> { impl<'msg, T> Debug for RepeatedView<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RepeatedView").field("raw", &self.raw).finish() f.debug_struct("RepeatedView").field("raw", &self.raw).finish()
} }
} }
/// Mutates the elements in a `repeated` field of `T`. /// Mutates the elements in a `repeated` field of `T`.
pub struct RepeatedMut<'msg, T: ?Sized> { pub struct RepeatedMut<'msg, T> {
pub(crate) inner: InnerRepeatedMut<'msg>, pub(crate) inner: InnerRepeatedMut<'msg>,
_phantom: PhantomData<&'msg mut T>, _phantom: PhantomData<&'msg mut T>,
} }
unsafe impl<'msg, T: ?Sized> Sync for RepeatedMut<'msg, T> {} unsafe impl<'msg, T> Sync for RepeatedMut<'msg, T> {}
impl<'msg, T: ?Sized> Debug for RepeatedMut<'msg, T> { impl<'msg, T> Debug for RepeatedMut<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RepeatedMut").field("raw", &self.inner.raw).finish() f.debug_struct("RepeatedMut").field("raw", &self.inner.raw).finish()
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl<'msg, T: ?Sized> RepeatedView<'msg, T> { impl<'msg, T> RepeatedView<'msg, T> {
#[doc(hidden)] #[doc(hidden)]
#[inline] #[inline]
pub fn as_raw(&self, _private: Private) -> RawRepeatedField { pub fn as_raw(&self, _private: Private) -> RawRepeatedField {
@ -77,7 +77,7 @@ impl<'msg, T: ?Sized> RepeatedView<'msg, T> {
impl<'msg, T> RepeatedView<'msg, T> impl<'msg, T> RepeatedView<'msg, T>
where where
T: ProxiedInRepeated + ?Sized + 'msg, T: ProxiedInRepeated + 'msg,
{ {
/// Gets the length of the repeated field. /// Gets the length of the repeated field.
#[inline] #[inline]
@ -120,7 +120,7 @@ where
} }
#[doc(hidden)] #[doc(hidden)]
impl<'msg, T: ?Sized> RepeatedMut<'msg, T> { impl<'msg, T> RepeatedMut<'msg, T> {
/// # Safety /// # Safety
/// - `inner` must be valid to read and write from for `'msg` /// - `inner` must be valid to read and write from for `'msg`
/// - There must be no aliasing references or mutations on the same /// - There must be no aliasing references or mutations on the same
@ -140,7 +140,7 @@ impl<'msg, T: ?Sized> RepeatedMut<'msg, T> {
impl<'msg, T> RepeatedMut<'msg, T> impl<'msg, T> RepeatedMut<'msg, T>
where where
T: ProxiedInRepeated + ?Sized + 'msg, T: ProxiedInRepeated + 'msg,
{ {
/// Gets the length of the repeated field. /// Gets the length of the repeated field.
#[inline] #[inline]
@ -174,8 +174,7 @@ where
/// Appends `val` to the end of the repeated field. /// Appends `val` to the end of the repeated field.
#[inline] #[inline]
pub fn push(&mut self, val: View<T>) { pub fn push(&mut self, val: impl IntoProxied<T>) {
// TODO: b/320936046 - Use SettableValue instead of View for added ergonomics.
T::repeated_push(self.as_mut(), val); T::repeated_push(self.as_mut(), val);
} }
@ -184,13 +183,11 @@ where
/// # Panics /// # Panics
/// Panics if `index >= len` /// Panics if `index >= len`
#[inline] #[inline]
pub fn set(&mut self, index: usize, val: View<T>) { pub fn set(&mut self, index: usize, val: impl IntoProxied<T>) {
let len = self.len(); let len = self.len();
if index >= len { if index >= len {
panic!("index {index} >= repeated len {len}"); panic!("index {index} >= repeated len {len}");
} }
// TODO: b/320936046 - Use SettableValue instead of View for added ergonomics.
// SAFETY: `index` has been checked to be in-bounds.
unsafe { self.set_unchecked(index, val) } unsafe { self.set_unchecked(index, val) }
} }
@ -199,9 +196,7 @@ where
/// # Safety /// # Safety
/// Undefined behavior if `index >= len` /// Undefined behavior if `index >= len`
#[inline] #[inline]
pub unsafe fn set_unchecked(&mut self, index: usize, val: View<T>) { pub unsafe fn set_unchecked(&mut self, index: usize, val: impl IntoProxied<T>) {
// TODO: b/320936046 - Use SettableValue instead of View for added ergonomics.
// SAFETY: `index` is in-bounds as promised by the caller.
unsafe { T::repeated_set_unchecked(self.as_mut(), index, val) } unsafe { T::repeated_set_unchecked(self.as_mut(), index, val) }
} }
@ -225,7 +220,7 @@ where
impl<T> Repeated<T> impl<T> Repeated<T>
where where
T: ?Sized + ProxiedInRepeated, T: ProxiedInRepeated,
{ {
pub fn as_view(&self) -> View<Repeated<T>> { pub fn as_view(&self) -> View<Repeated<T>> {
RepeatedView { raw: self.inner.raw(), _phantom: PhantomData } RepeatedView { raw: self.inner.raw(), _phantom: PhantomData }
@ -239,7 +234,7 @@ where
impl<T> IntoProxied<Repeated<T>> for Repeated<T> impl<T> IntoProxied<Repeated<T>> for Repeated<T>
where where
T: ?Sized + ProxiedInRepeated, T: ProxiedInRepeated,
{ {
fn into_proxied(self, _private: Private) -> Repeated<T> { fn into_proxied(self, _private: Private) -> Repeated<T> {
self self
@ -248,7 +243,7 @@ where
impl<'msg, T> IntoProxied<Repeated<T>> for RepeatedView<'msg, T> impl<'msg, T> IntoProxied<Repeated<T>> for RepeatedView<'msg, T>
where where
T: 'msg + ?Sized + ProxiedInRepeated, T: 'msg + ProxiedInRepeated,
{ {
fn into_proxied(self, _private: Private) -> Repeated<T> { fn into_proxied(self, _private: Private) -> Repeated<T> {
let mut repeated: Repeated<T> = Repeated::new(); let mut repeated: Repeated<T> = Repeated::new();
@ -259,7 +254,7 @@ where
impl<'msg, T> IntoProxied<Repeated<T>> for RepeatedMut<'msg, T> impl<'msg, T> IntoProxied<Repeated<T>> for RepeatedMut<'msg, T>
where where
T: 'msg + ?Sized + ProxiedInRepeated, T: 'msg + ProxiedInRepeated,
{ {
fn into_proxied(self, _private: Private) -> Repeated<T> { fn into_proxied(self, _private: Private) -> Repeated<T> {
IntoProxied::into_proxied(self.as_view(), _private) IntoProxied::into_proxied(self.as_view(), _private)
@ -296,7 +291,7 @@ pub unsafe trait ProxiedInRepeated: Proxied {
fn repeated_len(repeated: View<Repeated<Self>>) -> usize; fn repeated_len(repeated: View<Repeated<Self>>) -> usize;
/// Appends a new element to the end of the repeated field. /// Appends a new element to the end of the repeated field.
fn repeated_push(repeated: Mut<Repeated<Self>>, val: View<Self>); fn repeated_push(repeated: Mut<Repeated<Self>>, val: impl IntoProxied<Self>);
/// Clears the repeated field of elements. /// Clears the repeated field of elements.
fn repeated_clear(repeated: Mut<Repeated<Self>>); fn repeated_clear(repeated: Mut<Repeated<Self>>);
@ -307,7 +302,11 @@ pub unsafe trait ProxiedInRepeated: Proxied {
/// # Safety /// # Safety
/// `index` must be less than `Self::repeated_len(repeated)` /// `index` must be less than `Self::repeated_len(repeated)`
unsafe fn repeated_set_unchecked(repeated: Mut<Repeated<Self>>, index: usize, val: View<Self>); unsafe fn repeated_set_unchecked(
repeated: Mut<Repeated<Self>>,
index: usize,
val: impl IntoProxied<Self>,
);
/// Copies the values in the `src` repeated field into `dest`. /// Copies the values in the `src` repeated field into `dest`.
fn repeated_copy_from(src: View<Repeated<Self>>, dest: Mut<Repeated<Self>>); fn repeated_copy_from(src: View<Repeated<Self>>, dest: Mut<Repeated<Self>>);
@ -318,12 +317,12 @@ pub unsafe trait ProxiedInRepeated: Proxied {
} }
/// An iterator over the values inside of a [`View<Repeated<T>>`](RepeatedView). /// An iterator over the values inside of a [`View<Repeated<T>>`](RepeatedView).
pub struct RepeatedIter<'msg, T: ?Sized> { pub struct RepeatedIter<'msg, T> {
view: RepeatedView<'msg, T>, view: RepeatedView<'msg, T>,
current_index: usize, current_index: usize,
} }
impl<'msg, T: ?Sized> Debug for RepeatedIter<'msg, T> { impl<'msg, T> Debug for RepeatedIter<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RepeatedIter") f.debug_struct("RepeatedIter")
.field("view", &self.view) .field("view", &self.view)
@ -336,19 +335,19 @@ impl<'msg, T: ?Sized> Debug for RepeatedIter<'msg, T> {
/// ///
/// Users will generally write [`View<Repeated<T>>`](RepeatedView) or /// Users will generally write [`View<Repeated<T>>`](RepeatedView) or
/// [`Mut<Repeated<T>>`](RepeatedMut) to access the repeated elements /// [`Mut<Repeated<T>>`](RepeatedMut) to access the repeated elements
pub struct Repeated<T: ?Sized + ProxiedInRepeated> { pub struct Repeated<T: ProxiedInRepeated> {
pub(crate) inner: InnerRepeated, pub(crate) inner: InnerRepeated,
_phantom: PhantomData<T>, _phantom: PhantomData<T>,
} }
// SAFETY: `Repeated` is Sync because it does not implement interior mutability. // SAFETY: `Repeated` is Sync because it does not implement interior mutability.
unsafe impl<T: ?Sized + ProxiedInRepeated> Sync for Repeated<T> {} unsafe impl<T: ProxiedInRepeated> Sync for Repeated<T> {}
// SAFETY: `Repeated` is Send because it's not bound to a specific thread e.g. // SAFETY: `Repeated` is Send because it's not bound to a specific thread e.g.
// it does not use thread-local data or similar. // it does not use thread-local data or similar.
unsafe impl<T: ?Sized + ProxiedInRepeated> Send for Repeated<T> {} unsafe impl<T: ProxiedInRepeated> Send for Repeated<T> {}
impl<T: ?Sized + ProxiedInRepeated> Repeated<T> { impl<T: ProxiedInRepeated> Repeated<T> {
pub fn new() -> Self { pub fn new() -> Self {
T::repeated_new(Private) T::repeated_new(Private)
} }
@ -362,13 +361,13 @@ impl<T: ?Sized + ProxiedInRepeated> Repeated<T> {
} }
} }
impl<T: ?Sized + ProxiedInRepeated> Default for Repeated<T> { impl<T: ProxiedInRepeated> Default for Repeated<T> {
fn default() -> Self { fn default() -> Self {
Repeated::new() Repeated::new()
} }
} }
impl<T: ?Sized + ProxiedInRepeated> Drop for Repeated<T> { impl<T: ProxiedInRepeated> Drop for Repeated<T> {
fn drop(&mut self) { fn drop(&mut self) {
// SAFETY: only called once // SAFETY: only called once
unsafe { T::repeated_free(Private, self) } unsafe { T::repeated_free(Private, self) }
@ -377,21 +376,21 @@ impl<T: ?Sized + ProxiedInRepeated> Drop for Repeated<T> {
impl<T> Proxied for Repeated<T> impl<T> Proxied for Repeated<T>
where where
T: ProxiedInRepeated + ?Sized, T: ProxiedInRepeated,
{ {
type View<'msg> = RepeatedView<'msg, T> where Repeated<T>: 'msg; type View<'msg> = RepeatedView<'msg, T> where Repeated<T>: 'msg;
} }
impl<T> MutProxied for Repeated<T> impl<T> MutProxied for Repeated<T>
where where
T: ProxiedInRepeated + ?Sized, T: ProxiedInRepeated,
{ {
type Mut<'msg> = RepeatedMut<'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> impl<'msg, T> ViewProxy<'msg> for RepeatedView<'msg, T>
where where
T: ProxiedInRepeated + ?Sized + 'msg, T: ProxiedInRepeated + 'msg,
{ {
type Proxied = Repeated<T>; type Proxied = Repeated<T>;
@ -411,7 +410,7 @@ where
impl<'msg, T> ViewProxy<'msg> for RepeatedMut<'msg, T> impl<'msg, T> ViewProxy<'msg> for RepeatedMut<'msg, T>
where where
T: ProxiedInRepeated + ?Sized + 'msg, T: ProxiedInRepeated + 'msg,
{ {
type Proxied = Repeated<T>; type Proxied = Repeated<T>;
@ -431,7 +430,7 @@ where
impl<'msg, T> MutProxy<'msg> for RepeatedMut<'msg, T> impl<'msg, T> MutProxy<'msg> for RepeatedMut<'msg, T>
where where
T: ProxiedInRepeated + ?Sized + 'msg, T: ProxiedInRepeated + 'msg,
{ {
#[inline] #[inline]
fn as_mut(&mut self) -> Mut<'_, Self::Proxied> { fn as_mut(&mut self) -> Mut<'_, Self::Proxied> {
@ -449,7 +448,7 @@ where
impl<'msg, T> iter::Iterator for RepeatedIter<'msg, T> impl<'msg, T> iter::Iterator for RepeatedIter<'msg, T>
where where
T: ProxiedInRepeated + ?Sized + 'msg, T: ProxiedInRepeated + 'msg,
{ {
type Item = View<'msg, T>; type Item = View<'msg, T>;
@ -468,18 +467,18 @@ where
} }
} }
impl<'msg, T: ?Sized + ProxiedInRepeated> ExactSizeIterator for RepeatedIter<'msg, T> { impl<'msg, T: ProxiedInRepeated> ExactSizeIterator for RepeatedIter<'msg, T> {
fn len(&self) -> usize { fn len(&self) -> usize {
self.view.len() - self.current_index self.view.len() - self.current_index
} }
} }
// TODO: impl DoubleEndedIterator // TODO: impl DoubleEndedIterator
impl<'msg, T: ?Sized + ProxiedInRepeated> FusedIterator for RepeatedIter<'msg, T> {} impl<'msg, T: ProxiedInRepeated> FusedIterator for RepeatedIter<'msg, T> {}
impl<'msg, T> iter::IntoIterator for RepeatedView<'msg, T> impl<'msg, T> iter::IntoIterator for RepeatedView<'msg, T>
where where
T: ProxiedInRepeated + ?Sized + 'msg, T: ProxiedInRepeated + 'msg,
{ {
type Item = View<'msg, T>; type Item = View<'msg, T>;
type IntoIter = RepeatedIter<'msg, T>; type IntoIter = RepeatedIter<'msg, T>;
@ -491,7 +490,7 @@ where
impl<'msg, T> iter::IntoIterator for &'_ RepeatedView<'msg, T> impl<'msg, T> iter::IntoIterator for &'_ RepeatedView<'msg, T>
where where
T: ProxiedInRepeated + ?Sized + 'msg, T: ProxiedInRepeated + 'msg,
{ {
type Item = View<'msg, T>; type Item = View<'msg, T>;
type IntoIter = RepeatedIter<'msg, T>; type IntoIter = RepeatedIter<'msg, T>;
@ -503,7 +502,7 @@ where
impl<'borrow, T> iter::IntoIterator for &'borrow RepeatedMut<'_, T> impl<'borrow, T> iter::IntoIterator for &'borrow RepeatedMut<'_, T>
where where
T: ProxiedInRepeated + ?Sized + 'borrow, T: ProxiedInRepeated + 'borrow,
{ {
type Item = View<'borrow, T>; type Item = View<'borrow, T>;
type IntoIter = RepeatedIter<'borrow, T>; type IntoIter = RepeatedIter<'borrow, T>;
@ -515,14 +514,14 @@ where
impl<'msg, 'view, T, ViewT> Extend<ViewT> for RepeatedMut<'msg, T> impl<'msg, 'view, T, ViewT> Extend<ViewT> for RepeatedMut<'msg, T>
where where
T: ProxiedInRepeated + ?Sized + 'view, T: ProxiedInRepeated + 'view,
ViewT: Into<View<'view, T>>, ViewT: IntoProxied<T>,
{ {
fn extend<I: IntoIterator<Item = ViewT>>(&mut self, iter: I) { fn extend<I: IntoIterator<Item = ViewT>>(&mut self, iter: I) {
let iter = iter.into_iter(); let iter = iter.into_iter();
T::repeated_reserve(self.as_mut(), iter.size_hint().0); T::repeated_reserve(self.as_mut(), iter.size_hint().0);
for item in iter { for item in iter {
self.push(item.into()); self.push(item);
} }
} }
} }

@ -164,6 +164,12 @@ impl ProtoString {
} }
} }
impl From<ProtoString> for ProtoBytes {
fn from(v: ProtoString) -> Self {
ProtoBytes { inner: v.inner }
}
}
impl From<&str> for ProtoString { impl From<&str> for ProtoString {
fn from(v: &str) -> Self { fn from(v: &str) -> Self {
Self::from(v.as_bytes()) Self::from(v.as_bytes())

@ -142,7 +142,7 @@ fn test_bytes_and_string_copied() {
// Ensure val is dropped after inserting into the map. // Ensure val is dropped after inserting into the map.
let mut key = String::from("hello"); let mut key = String::from("hello");
let mut val = String::from("world"); let mut val = String::from("world");
msg.map_string_string_mut().insert(key.as_str(), val.as_str()); msg.map_string_string_mut().insert(key.as_str(), &val);
msg.map_int32_bytes_mut().insert(1, val.as_bytes()); msg.map_int32_bytes_mut().insert(1, val.as_bytes());
// Validate that map keys are copied by mutating the originals. // Validate that map keys are copied by mutating the originals.
key.replace_range(.., "ayo"); key.replace_range(.., "ayo");
@ -233,7 +233,7 @@ macro_rules! generate_map_with_msg_values_tests {
assert_that!( assert_that!(
msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new().as_view()), msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new()),
eq(true)); eq(true));
assert_that!( assert_that!(
msg.[< map_ $k_field _all_types_mut >]().remove($k_nonzero), msg.[< map_ $k_field _all_types_mut >]().remove($k_nonzero),
@ -264,7 +264,7 @@ macro_rules! generate_map_with_msg_values_tests {
// single element iter // single element iter
assert_that!( assert_that!(
msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new().as_view()), msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new()),
eq(true)); eq(true));
// assert_that!( // assert_that!(
// msg.[< map_ $k_field _all_types >]().iter().collect::<Vec<_>>(), // msg.[< map_ $k_field _all_types >]().iter().collect::<Vec<_>>(),
@ -285,7 +285,7 @@ macro_rules! generate_map_with_msg_values_tests {
assert_that!( assert_that!(
msg msg
.[< map_ $k_field _all_types_mut >]() .[< map_ $k_field _all_types_mut >]()
.insert($k_other, TestAllTypes::new().as_view()), .insert($k_other, TestAllTypes::new()),
eq(true)); eq(true));
assert_that!( assert_that!(

@ -193,7 +193,7 @@ fn test_repeated_message() {
assert_that!(msg.repeated_nested_message().len(), eq(0)); assert_that!(msg.repeated_nested_message().len(), eq(0));
let mut nested = NestedMessage::new(); let mut nested = NestedMessage::new();
nested.set_bb(1); nested.set_bb(1);
msg.repeated_nested_message_mut().push(nested.as_view()); msg.repeated_nested_message_mut().push(nested);
assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(1)); assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(1));
let mut msg2 = TestAllTypes::new(); let mut msg2 = TestAllTypes::new();
@ -203,8 +203,7 @@ fn test_repeated_message() {
let mut nested2 = NestedMessage::new(); let mut nested2 = NestedMessage::new();
nested2.set_bb(2); nested2.set_bb(2);
// TODO: b/320936046 - Test SettableValue once available msg.repeated_nested_message_mut().set(0, nested2);
msg.repeated_nested_message_mut().set(0, nested2.as_view());
assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(2)); assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(2));
assert_that!( assert_that!(
@ -227,14 +226,12 @@ fn test_repeated_strings() {
assert_that!(msg.repeated_string(), empty()); assert_that!(msg.repeated_string(), empty());
{ {
let s = String::from("set from Mut"); let s = String::from("set from Mut");
// TODO: b/320936046 - Test SettableValue once available msg.repeated_string_mut().push(s);
msg.repeated_string_mut().push(s.as_str().into());
} }
msg.repeated_string_mut().push("second str".into()); msg.repeated_string_mut().push("second str");
{ {
let s2 = String::from("set second str"); let s2 = String::from("set second str");
// TODO: b/320936046 - Test SettableValue once available msg.repeated_string_mut().set(1, s2);
msg.repeated_string_mut().set(1, s2.as_str().into());
} }
assert_that!(msg.repeated_string().len(), eq(2)); assert_that!(msg.repeated_string().len(), eq(2));
assert_that!(msg.repeated_string().get(0).unwrap(), eq("set from Mut")); assert_that!(msg.repeated_string().get(0).unwrap(), eq("set from Mut"));
@ -264,14 +261,12 @@ fn test_repeated_bytes() {
assert_that!(msg.repeated_bytes(), empty()); assert_that!(msg.repeated_bytes(), empty());
{ {
let s = Vec::from(b"set from Mut"); let s = Vec::from(b"set from Mut");
// TODO: b/320936046 - Test SettableValue once available msg.repeated_bytes_mut().push(s);
msg.repeated_bytes_mut().push(&s[..]);
} }
msg.repeated_bytes_mut().push(b"second bytes"); msg.repeated_bytes_mut().push(b"second bytes");
{ {
let s2 = Vec::from(b"set second bytes"); let s2 = Vec::from(b"set second bytes");
// TODO: b/320936046 - Test SettableValue once available msg.repeated_bytes_mut().set(1, s2);
msg.repeated_bytes_mut().set(1, &s2[..]);
} }
assert_that!(msg.repeated_bytes().len(), eq(2)); assert_that!(msg.repeated_bytes().len(), eq(2));
assert_that!(msg.repeated_bytes().get(0).unwrap(), eq(b"set from Mut")); assert_that!(msg.repeated_bytes().get(0).unwrap(), eq(b"set from Mut"));

@ -32,7 +32,7 @@ fn string_view_works() {
fn repeated_string_view_works() { fn repeated_string_view_works() {
let mut msg = edition2023_rust_proto::EditionsMessage::new(); let mut msg = edition2023_rust_proto::EditionsMessage::new();
assert_that!(msg.repeated_str_view().len(), eq(0)); assert_that!(msg.repeated_str_view().len(), eq(0));
msg.repeated_str_view_mut().push("first".into()); msg.repeated_str_view_mut().push("first");
assert_that!(msg.repeated_str_view().len(), eq(1)); assert_that!(msg.repeated_str_view().len(), eq(1));
assert_that!(msg.repeated_str_view().get(0), some(eq("first"))); assert_that!(msg.repeated_str_view().get(0), some(eq("first")));
} }

@ -12,7 +12,7 @@ use unittest_proto3_rust_proto::TestAllTypes;
fn test_stringpiece_repeated() { fn test_stringpiece_repeated() {
let mut msg = TestAllTypes::new(); let mut msg = TestAllTypes::new();
assert_that!(msg.repeated_string_piece().len(), eq(0)); assert_that!(msg.repeated_string_piece().len(), eq(0));
msg.repeated_string_piece_mut().push("hello".into()); msg.repeated_string_piece_mut().push("hello");
assert_that!(msg.repeated_string_piece().len(), eq(1)); assert_that!(msg.repeated_string_piece().len(), eq(1));
assert_that!(msg.repeated_string_piece().get(0), some(eq("hello"))); assert_that!(msg.repeated_string_piece().get(0), some(eq("hello")));
} }
@ -29,7 +29,7 @@ fn test_cord() {
fn test_cord_repeated() { fn test_cord_repeated() {
let mut msg = TestAllTypes::new(); let mut msg = TestAllTypes::new();
assert_that!(msg.repeated_cord().len(), eq(0)); assert_that!(msg.repeated_cord().len(), eq(0));
msg.repeated_cord_mut().push("hello".into()); msg.repeated_cord_mut().push("hello");
assert_that!(msg.repeated_cord().len(), eq(1)); assert_that!(msg.repeated_cord().len(), eq(1));
assert_that!(msg.repeated_cord().get(0), some(eq("hello"))); assert_that!(msg.repeated_cord().get(0), some(eq("hello")));
} }

@ -226,12 +226,15 @@ macro_rules! impl_repeated_base {
unsafe { upb_Array_Size(f.as_raw(Private)) } unsafe { upb_Array_Size(f.as_raw(Private)) }
} }
#[inline] #[inline]
fn repeated_push(mut f: Mut<Repeated<$t>>, v: View<$t>) { fn repeated_push(mut f: Mut<Repeated<$t>>, v: impl IntoProxied<$t>) {
let arena = f.raw_arena(Private); let arena = f.raw_arena(Private);
unsafe { unsafe {
assert!(upb_Array_Append( assert!(upb_Array_Append(
f.as_raw(Private), f.as_raw(Private),
<$t as UpbTypeConversions>::to_message_value_copy_if_required(arena, v), <$t as UpbTypeConversions>::into_message_value_fuse_if_required(
arena,
v.into_proxied(Private)
),
arena, arena,
)); ));
} }
@ -249,13 +252,20 @@ macro_rules! impl_repeated_base {
} }
} }
#[inline] #[inline]
unsafe fn repeated_set_unchecked(mut f: Mut<Repeated<$t>>, i: usize, v: View<$t>) { unsafe fn repeated_set_unchecked(
mut f: Mut<Repeated<$t>>,
i: usize,
v: impl IntoProxied<$t>,
) {
let arena = f.raw_arena(Private); let arena = f.raw_arena(Private);
unsafe { unsafe {
upb_Array_Set( upb_Array_Set(
f.as_raw(Private), f.as_raw(Private),
i, i,
<$t as UpbTypeConversions>::to_message_value_copy_if_required(arena, v.into()), <$t as UpbTypeConversions>::into_message_value_fuse_if_required(
arena,
v.into_proxied(Private),
),
) )
} }
} }
@ -340,7 +350,7 @@ macro_rules! impl_repeated_bytes {
} }
} }
impl<'msg, T: ?Sized> RepeatedMut<'msg, T> { impl<'msg, T> RepeatedMut<'msg, T> {
// Returns a `RawArena` which is live for at least `'msg` // Returns a `RawArena` which is live for at least `'msg`
#[doc(hidden)] #[doc(hidden)]
pub fn raw_arena(&mut self, _private: Private) -> RawArena { pub fn raw_arena(&mut self, _private: Private) -> RawArena {
@ -538,13 +548,14 @@ impl<'msg> InnerMapMut<'msg> {
pub trait UpbTypeConversions: Proxied { pub trait UpbTypeConversions: Proxied {
fn upb_type() -> upb::CType; fn upb_type() -> upb::CType;
fn to_message_value(val: View<'_, Self>) -> upb_MessageValue; fn to_message_value(val: View<'_, Self>) -> upb_MessageValue;
/// # Safety /// # Safety
/// - `raw_arena` must point to a valid upb arena. /// - `raw_arena` must point to a valid upb arena.
unsafe fn to_message_value_copy_if_required( unsafe fn into_message_value_fuse_if_required(
raw_arena: RawArena, raw_arena: RawArena,
val: View<'_, Self>, val: Self,
) -> upb_MessageValue; ) -> upb_MessageValue;
/// # Safety /// # Safety
@ -568,7 +579,7 @@ macro_rules! impl_upb_type_conversions_for_scalars {
} }
#[inline(always)] #[inline(always)]
unsafe fn to_message_value_copy_if_required(_: RawArena, val: View<'_, $t>) -> upb_MessageValue { unsafe fn into_message_value_fuse_if_required(_: RawArena, val: $t) -> upb_MessageValue {
Self::to_message_value(val) Self::to_message_value(val)
} }
@ -600,14 +611,17 @@ impl UpbTypeConversions for ProtoBytes {
upb_MessageValue { str_val: val.into() } upb_MessageValue { str_val: val.into() }
} }
unsafe fn to_message_value_copy_if_required( unsafe fn into_message_value_fuse_if_required(
raw_arena: RawArena, raw_parent_arena: RawArena,
val: View<'_, ProtoBytes>, val: ProtoBytes,
) -> upb_MessageValue { ) -> upb_MessageValue {
// SAFETY: The arena memory is not freed due to `ManuallyDrop`. // SAFETY: The arena memory is not freed due to `ManuallyDrop`.
let arena = ManuallyDrop::new(unsafe { Arena::from_raw(raw_arena) }); let parent_arena = ManuallyDrop::new(unsafe { Arena::from_raw(raw_parent_arena) });
let copied = copy_bytes_in_arena(&arena, val); let (data, arena) = val.inner.0.into_parts();
let msg_val = Self::to_message_value(copied);
parent_arena.fuse(&arena);
let msg_val = Self::to_message_value(unsafe { data.as_ref() });
msg_val msg_val
} }
@ -625,15 +639,15 @@ impl UpbTypeConversions for ProtoString {
upb_MessageValue { str_val: val.as_bytes().into() } upb_MessageValue { str_val: val.as_bytes().into() }
} }
unsafe fn to_message_value_copy_if_required( unsafe fn into_message_value_fuse_if_required(
raw_arena: RawArena, raw_arena: RawArena,
val: View<'_, ProtoString>, val: ProtoString,
) -> upb_MessageValue { ) -> upb_MessageValue {
// SAFETY: `raw_arena` is valid as promised by the caller // SAFETY: `raw_arena` is valid as promised by the caller
unsafe { unsafe {
<ProtoBytes as UpbTypeConversions>::to_message_value_copy_if_required( <ProtoBytes as UpbTypeConversions>::into_message_value_fuse_if_required(
raw_arena, raw_arena,
val.as_bytes(), val.into(),
) )
} }
} }
@ -701,13 +715,13 @@ macro_rules! impl_ProxiedInMapValue_for_non_generated_value_types {
} }
} }
fn map_insert(mut map: Mut<'_, Map<$key_t, Self>>, key: View<'_, $key_t>, value: View<'_, Self>) -> bool { fn map_insert(mut map: Mut<'_, Map<$key_t, Self>>, key: View<'_, $key_t>, value: impl IntoProxied<Self>) -> bool {
let arena = map.raw_arena(Private); let arena = map.raw_arena(Private);
unsafe { unsafe {
upb_Map_InsertAndReturnIfInserted( upb_Map_InsertAndReturnIfInserted(
map.as_raw(Private), map.as_raw(Private),
<$key_t as UpbTypeConversions>::to_message_value(key), <$key_t as UpbTypeConversions>::to_message_value(key),
<$t as UpbTypeConversions>::to_message_value_copy_if_required(arena, value), <$t as UpbTypeConversions>::into_message_value_fuse_if_required(arena, value.into_proxied(Private)),
arena arena
) )
} }

@ -105,8 +105,8 @@ void EnumProxiedInMapValue(Context& ctx, const EnumDescriptor& desc) {
unsafe { $map_size_thunk$(map.as_raw($pbi$::Private)) } unsafe { $map_size_thunk$(map.as_raw($pbi$::Private)) }
} }
fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: $pb$::View<'_, Self>) -> bool { fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: impl $pb$::IntoProxied<Self>) -> bool {
unsafe { $map_insert_thunk$(map.as_raw($pbi$::Private), $to_ffi_key_expr$, value) } unsafe { $map_insert_thunk$(map.as_raw($pbi$::Private), $to_ffi_key_expr$, value.into_proxied($pbi$::Private)) }
} }
fn map_get<'a>(map: $pb$::View<'a, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> Option<$pb$::View<'a, Self>> { fn map_get<'a>(map: $pb$::View<'a, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> Option<$pb$::View<'a, Self>> {
@ -193,13 +193,13 @@ void EnumProxiedInMapValue(Context& ctx, const EnumDescriptor& desc) {
} }
} }
fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: $pb$::View<'_, Self>) -> bool { fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: impl $pb$::IntoProxied<Self>) -> bool {
let arena = map.inner($pbi$::Private).raw_arena($pbi$::Private); let arena = map.inner($pbi$::Private).raw_arena($pbi$::Private);
unsafe { unsafe {
$pbr$::upb_Map_InsertAndReturnIfInserted( $pbr$::upb_Map_InsertAndReturnIfInserted(
map.as_raw($pbi$::Private), map.as_raw($pbi$::Private),
<$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key), <$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key),
$pbr$::upb_MessageValue { int32_val: value.0 }, $pbr$::upb_MessageValue { int32_val: value.into_proxied($pbi$::Private).0 },
arena arena
) )
} }
@ -389,6 +389,18 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) {
} }
} }
impl $pb$::IntoProxied<$name$> for $name$ {
fn into_proxied(self, _: $pbi$::Private) -> Self {
self
}
}
impl $pb$::IntoProxied<i32> for $name$ {
fn into_proxied(self, _: $pbi$::Private) -> i32 {
self.0
}
}
impl $pb$::Proxied for $name$ { impl $pb$::Proxied for $name$ {
type View<'a> = $name$; type View<'a> = $name$;
} }
@ -410,8 +422,8 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) {
$pbr$::cast_enum_repeated_view($pbi$::Private, r).len() $pbr$::cast_enum_repeated_view($pbi$::Private, r).len()
} }
fn repeated_push(r: $pb$::Mut<$pb$::Repeated<Self>>, val: $name$) { fn repeated_push(r: $pb$::Mut<$pb$::Repeated<Self>>, val: impl $pb$::IntoProxied<$name$>) {
$pbr$::cast_enum_repeated_mut($pbi$::Private, r).push(val.into()) $pbr$::cast_enum_repeated_mut($pbi$::Private, r).push(val.into_proxied($pbi$::Private))
} }
fn repeated_clear(r: $pb$::Mut<$pb$::Repeated<Self>>) { fn repeated_clear(r: $pb$::Mut<$pb$::Repeated<Self>>) {
@ -434,12 +446,12 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) {
unsafe fn repeated_set_unchecked( unsafe fn repeated_set_unchecked(
r: $pb$::Mut<$pb$::Repeated<Self>>, r: $pb$::Mut<$pb$::Repeated<Self>>,
index: usize, index: usize,
val: $name$, val: impl $pb$::IntoProxied<$name$>,
) { ) {
// SAFETY: In-bounds as promised by the caller. // SAFETY: In-bounds as promised by the caller.
unsafe { unsafe {
$pbr$::cast_enum_repeated_mut($pbi$::Private, r) $pbr$::cast_enum_repeated_mut($pbi$::Private, r)
.set_unchecked(index, val.into()) .set_unchecked(index, val.into_proxied($pbi$::Private))
} }
} }
@ -484,7 +496,7 @@ void GenerateEnumThunksCc(Context& ctx, const EnumDescriptor& desc) {
R"cc( R"cc(
extern $abi$ { extern $abi$ {
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE( __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(
$cpp_t$, $rs_t$, $cpp_t$, value, cpp_value) $cpp_t$, $rs_t$, $cpp_t$, $cpp_t$, value, cpp_value)
} }
)cc"); )cc");
} }

@ -374,7 +374,7 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) {
unsafe fn repeated_set_unchecked( unsafe fn repeated_set_unchecked(
mut f: $pb$::Mut<$pb$::Repeated<Self>>, mut f: $pb$::Mut<$pb$::Repeated<Self>>,
i: usize, i: usize,
v: $pb$::View<Self>, v: impl $pb$::IntoProxied<Self>,
) { ) {
// SAFETY: // SAFETY:
// - `f.as_raw()` is a valid `RepeatedPtrField*`. // - `f.as_raw()` is a valid `RepeatedPtrField*`.
@ -383,7 +383,7 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) {
unsafe { unsafe {
$copy_from_thunk$( $copy_from_thunk$(
$repeated_get_mut_thunk$(f.as_raw($pbi$::Private), i), $repeated_get_mut_thunk$(f.as_raw($pbi$::Private), i),
v.raw_msg(), v.into_proxied($pbi$::Private).raw_msg(),
); );
} }
} }
@ -404,13 +404,13 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) {
unsafe { $repeated_clear_thunk$(f.as_raw($pbi$::Private)) }; unsafe { $repeated_clear_thunk$(f.as_raw($pbi$::Private)) };
} }
fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated<Self>>, v: $pb$::View<Self>) { fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated<Self>>, v: impl $pb$::IntoProxied<Self>) {
// SAFETY: // SAFETY:
// - `f.as_raw()` is a valid `RepeatedPtrField*`. // - `f.as_raw()` is a valid `RepeatedPtrField*`.
// - `v.raw_msg()` is a valid `const Message&`. // - `v.raw_msg()` is a valid `const Message&`.
unsafe { unsafe {
let new_elem = $repeated_add_thunk$(f.as_raw($pbi$::Private)); let new_elem = $repeated_add_thunk$(f.as_raw($pbi$::Private));
$copy_from_thunk$(new_elem, v.raw_msg()); $copy_from_thunk$(new_elem, v.into_proxied($pbi$::Private).raw_msg());
} }
} }
@ -452,26 +452,18 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) {
unsafe fn repeated_set_unchecked( unsafe fn repeated_set_unchecked(
mut f: $pb$::Mut<$pb$::Repeated<Self>>, mut f: $pb$::Mut<$pb$::Repeated<Self>>,
i: usize, i: usize,
v: $pb$::View<Self>, v: impl $pb$::IntoProxied<Self>,
) { ) {
// SAFETY:
// - `f.as_raw()` is a valid `upb_Array*`.
// - `i < len(f)` is promised by the caller.
let dest_msg = unsafe {
$pbr$::upb_Array_GetMutable(f.as_raw($pbi$::Private), i).msg
}.expect("upb_Array* element should not be NULL");
// SAFETY:
// - `dest_msg` is a valid `upb_Message*`.
// - `v.raw_msg()` and `dest_msg` both have message minitable `$minitable$`.
unsafe { unsafe {
$pbr$::upb_Message_DeepCopy( $pbr$::upb_Array_Set(
dest_msg, f.as_raw($pbi$::Private),
v.raw_msg(), i,
$std$::ptr::addr_of!($minitable$), <Self as $pbr$::UpbTypeConversions>::into_message_value_fuse_if_required(
f.raw_arena($pbi$::Private), f.raw_arena($pbi$::Private),
) v.into_proxied($pbi$::Private),
}; ),
)
}
} }
unsafe fn repeated_get_unchecked( unsafe fn repeated_get_unchecked(
@ -493,26 +485,15 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) {
$pbr$::upb_Array_Resize(f.as_raw($pbi$::Private), 0, f.raw_arena($pbi$::Private)) $pbr$::upb_Array_Resize(f.as_raw($pbi$::Private), 0, f.raw_arena($pbi$::Private))
}; };
} }
fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated<Self>>, v: $pb$::View<Self>) { fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated<Self>>, v: impl $pb$::IntoProxied<Self>) {
// SAFETY:
// - `v.raw_msg()` is a valid `const upb_Message*` with minitable `$minitable$`.
let msg_ptr = unsafe {
$pbr$::upb_Message_DeepClone(
v.raw_msg(),
std::ptr::addr_of!($minitable$),
f.raw_arena($pbi$::Private),
)
}.expect("upb_Message_DeepClone failed.");
// Append new default message to array.
// SAFETY: // SAFETY:
// - `f.as_raw()` is a valid `upb_Array*`. // - `f.as_raw()` is a valid `upb_Array*`.
// - `msg_ptr` is a valid `upb_Message*`. // - `msg_ptr` is a valid `upb_Message*`.
unsafe { unsafe {
$pbr$::upb_Array_Append( $pbr$::upb_Array_Append(
f.as_raw($pbi$::Private), f.as_raw($pbi$::Private),
$pbr$::upb_MessageValue{msg_val: Some(msg_ptr)}, <Self as $pbr$::UpbTypeConversions>::into_message_value_fuse_if_required(f.raw_arena($pbi$::Private), v.into_proxied($pbi$::Private)),
f.raw_arena($pbi$::Private), f.raw_arena($pbi$::Private)
); );
}; };
} }
@ -605,8 +586,8 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
unsafe { $map_size_thunk$(map.as_raw($pbi$::Private)) } unsafe { $map_size_thunk$(map.as_raw($pbi$::Private)) }
} }
fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: $pb$::View<'_, Self>) -> bool { fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: impl $pb$::IntoProxied<Self>) -> bool {
unsafe { $map_insert_thunk$(map.as_raw($pbi$::Private), $key_expr$, value.raw_msg()) } unsafe { $map_insert_thunk$(map.as_raw($pbi$::Private), $key_expr$, value.into_proxied($pbi$::Private).raw_msg()) }
} }
fn map_get<'a>(map: $pb$::View<'a, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> Option<$pb$::View<'a, Self>> { fn map_get<'a>(map: $pb$::View<'a, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> Option<$pb$::View<'a, Self>> {
@ -675,17 +656,15 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
$pbr$::upb_MessageValue { msg_val: Some(val.raw_msg()) } $pbr$::upb_MessageValue { msg_val: Some(val.raw_msg()) }
} }
unsafe fn to_message_value_copy_if_required( unsafe fn into_message_value_fuse_if_required(
arena: $pbr$::RawArena, raw_parent_arena: $pbr$::RawArena,
val: $pb$::View<'_, Self>) -> $pbr$::upb_MessageValue { mut val: Self) -> $pbr$::upb_MessageValue {
// Self::to_message_value(val)
// SAFETY: The arena memory is not freed due to `ManuallyDrop`. // SAFETY: The arena memory is not freed due to `ManuallyDrop`.
let cloned_msg = $pbr$::upb_Message_DeepClone( let parent_arena = core::mem::ManuallyDrop::new(unsafe { $pbr$::Arena::from_raw(raw_parent_arena) });
val.raw_msg(), $std$::ptr::addr_of!($minitable$), arena)
.expect("upb_Message_DeepClone failed."); parent_arena.fuse(val.as_mutator_message_ref($pbi$::Private).arena($pbi$::Private));
Self::to_message_value( $pbr$::upb_MessageValue { msg_val: Some(val.raw_msg()) }
$Msg$View::new($pbi$::Private, cloned_msg)) }
}
unsafe fn from_message_value<'msg>(msg: $pbr$::upb_MessageValue) unsafe fn from_message_value<'msg>(msg: $pbr$::upb_MessageValue)
-> $pb$::View<'msg, Self> { -> $pb$::View<'msg, Self> {
@ -731,13 +710,13 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
} }
} }
fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: $pb$::View<'_, Self>) -> bool { fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: impl $pb$::IntoProxied<Self>) -> bool {
let arena = map.inner($pbi$::Private).raw_arena($pbi$::Private); let arena = map.inner($pbi$::Private).raw_arena($pbi$::Private);
unsafe { unsafe {
$pbr$::upb_Map_InsertAndReturnIfInserted( $pbr$::upb_Map_InsertAndReturnIfInserted(
map.as_raw($pbi$::Private), map.as_raw($pbi$::Private),
<$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key), <$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key),
<Self as $pbr$::UpbTypeConversions>::to_message_value_copy_if_required(arena, value), <Self as $pbr$::UpbTypeConversions>::into_message_value_fuse_if_required(arena, value.into_proxied($pbi$::Private)),
arena arena
) )
} }

Loading…
Cancel
Save