Implement flat setters for map and repeated fields.
This doesn't yet use the new IntoProxied trait, but is functionaly equivalent with MutProxy::set() and always copies.
PiperOrigin-RevId: 629358666
diff --git a/rust/test/shared/accessors_map_test.rs b/rust/test/shared/accessors_map_test.rs
index 0fc153f..50341b0 100644
--- a/rust/test/shared/accessors_map_test.rs
+++ b/rust/test/shared/accessors_map_test.rs
@@ -157,6 +157,23 @@
assert_that!(msg.map_int32_bytes_mut().get(1).unwrap(), eq(b"world"));
}
+#[test]
+fn test_map_setter() {
+ let mut msg = TestMap::new();
+ msg.map_string_string_mut().insert("hello", "world");
+ msg.map_string_string_mut().insert("fizz", "buzz");
+
+ let mut msg2 = TestMap::new();
+ msg2.set_map_string_string(msg.map_string_string());
+ assert_that!(
+ msg2.map_string_string().iter().collect::<Vec<_>>(),
+ unordered_elements_are![
+ eq(("hello".into(), "world".into())),
+ eq(("fizz".into(), "buzz".into()))
+ ]
+ );
+}
+
macro_rules! generate_map_with_msg_values_tests {
(
$(($k_field:ident, $k_nonzero:expr, $k_other:expr $(,)?)),*
diff --git a/rust/test/shared/accessors_repeated_test.rs b/rust/test/shared/accessors_repeated_test.rs
index 9aee490..99ae453 100644
--- a/rust/test/shared/accessors_repeated_test.rs
+++ b/rust/test/shared/accessors_repeated_test.rs
@@ -55,16 +55,17 @@
#[test]
fn [< test_repeated_ $field _set >]() {
let mut msg = TestAllTypes::new();
- let mut mutator = msg.[<repeated_ $field _mut>]();
let mut msg2 = TestAllTypes::new();
let mut mutator2 = msg2.[<repeated_ $field _mut>]();
for i in 0..5 {
mutator2.push(i as $t);
}
- protobuf::MutProxy::set(&mut mutator, mutator2.as_view());
+ msg.[<set_repeated_ $field >](mutator2.as_view());
+
+ let view = msg.[<repeated_ $field>]();
assert_that!(
- mutator.iter().collect::<Vec<_>>(),
+ view.iter().collect::<Vec<_>>(),
eq(mutator2.iter().collect::<Vec<_>>())
);
}
@@ -177,15 +178,16 @@
#[test]
fn test_repeated_bool_set() {
let mut msg = TestAllTypes::new();
- let mut mutator = msg.repeated_bool_mut();
let mut msg2 = TestAllTypes::new();
let mut mutator2 = msg2.repeated_bool_mut();
for _ in 0..5 {
mutator2.push(true);
}
- protobuf::MutProxy::set(&mut mutator, mutator2.as_view());
- assert_that!(mutator.iter().collect::<Vec<_>>(), eq(mutator2.iter().collect::<Vec<_>>()));
+ msg.set_repeated_bool(mutator2.as_view());
+
+ let view = msg.repeated_bool();
+ assert_that!(view.iter().collect::<Vec<_>>(), eq(mutator2.iter().collect::<Vec<_>>()));
}
#[test]
diff --git a/src/google/protobuf/compiler/rust/accessors/map.cc b/src/google/protobuf/compiler/rust/accessors/map.cc
index 75aa500..397d210 100644
--- a/src/google/protobuf/compiler/rust/accessors/map.cc
+++ b/src/google/protobuf/compiler/rust/accessors/map.cc
@@ -42,6 +42,7 @@
std::string field_name = FieldNameWithCollisionAvoidance(field);
ctx.Emit({{"field", RsSafeName(field_name)},
+ {"raw_field_name", field_name}, // Never r# prefixed
{"Key", RsTypePath(ctx, key_type)},
{"Value", RsTypePath(ctx, value_type)},
{"view_lifetime", ViewLifetime(accessor_case)},
@@ -99,10 +100,23 @@
unsafe { $pb$::MapMut::from_inner($pbi$::Private, inner) }
})rs");
}
+ }},
+ {"setter",
+ [&] {
+ if (accessor_case == AccessorCase::VIEW) {
+ return;
+ }
+ ctx.Emit({}, R"rs(
+ pub fn set_$raw_field_name$(&mut self, src: $pb$::MapView<'_, $Key$, $Value$>) {
+ // TODO: Implement IntoProxied and avoid copying.
+ self.$field$_mut().copy_from(src);
+ }
+ )rs");
}}},
R"rs(
$getter$
$getter_mut$
+ $setter$
)rs");
}
diff --git a/src/google/protobuf/compiler/rust/accessors/repeated_field.cc b/src/google/protobuf/compiler/rust/accessors/repeated_field.cc
index e1e14e6..11a8585 100644
--- a/src/google/protobuf/compiler/rust/accessors/repeated_field.cc
+++ b/src/google/protobuf/compiler/rust/accessors/repeated_field.cc
@@ -23,16 +23,19 @@
void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field,
AccessorCase accessor_case) const {
std::string field_name = FieldNameWithCollisionAvoidance(field);
- ctx.Emit({{"field", RsSafeName(field_name)},
- {"RsType", RsTypePath(ctx, field)},
- {"view_lifetime", ViewLifetime(accessor_case)},
- {"view_self", ViewReceiver(accessor_case)},
- {"getter_thunk", ThunkName(ctx, field, "get")},
- {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")},
- {"getter",
- [&] {
- if (ctx.is_upb()) {
- ctx.Emit({}, R"rs(
+ ctx.Emit(
+ {
+ {"field", RsSafeName(field_name)},
+ {"raw_field_name", field_name}, // Never r# prefixed
+ {"RsType", RsTypePath(ctx, field)},
+ {"view_lifetime", ViewLifetime(accessor_case)},
+ {"view_self", ViewReceiver(accessor_case)},
+ {"getter_thunk", ThunkName(ctx, field, "get")},
+ {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")},
+ {"getter",
+ [&] {
+ if (ctx.is_upb()) {
+ ctx.Emit({}, R"rs(
pub fn $field$($view_self$) -> $pb$::RepeatedView<$view_lifetime$, $RsType$> {
unsafe {
$getter_thunk$(
@@ -47,8 +50,8 @@
)
}
)rs");
- } else {
- ctx.Emit({}, R"rs(
+ } else {
+ ctx.Emit({}, R"rs(
pub fn $field$($view_self$) -> $pb$::RepeatedView<$view_lifetime$, $RsType$> {
unsafe {
$pb$::RepeatedView::from_raw(
@@ -58,16 +61,16 @@
}
}
)rs");
- }
- }},
- {"clearer_thunk", ThunkName(ctx, field, "clear")},
- {"getter_mut",
- [&] {
- if (accessor_case == AccessorCase::VIEW) {
- return;
- }
- if (ctx.is_upb()) {
- ctx.Emit({}, R"rs(
+ }
+ }},
+ {"clearer_thunk", ThunkName(ctx, field, "clear")},
+ {"getter_mut",
+ [&] {
+ if (accessor_case == AccessorCase::VIEW) {
+ return;
+ }
+ if (ctx.is_upb()) {
+ ctx.Emit({}, R"rs(
pub fn $field$_mut(&mut self) -> $pb$::RepeatedMut<'_, $RsType$> {
unsafe {
$pb$::RepeatedMut::from_inner(
@@ -85,8 +88,8 @@
}
}
)rs");
- } else {
- ctx.Emit({}, R"rs(
+ } else {
+ ctx.Emit({}, R"rs(
pub fn $field$_mut(&mut self) -> $pb$::RepeatedMut<'_, $RsType$> {
unsafe {
$pb$::RepeatedMut::from_inner(
@@ -99,11 +102,25 @@
}
}
)rs");
- }
- }}},
- R"rs(
+ }
+ }},
+ {"setter",
+ [&] {
+ if (accessor_case == AccessorCase::VIEW) {
+ return;
+ }
+ ctx.Emit({}, R"rs(
+ pub fn set_$raw_field_name$(&mut self, src: $pb$::RepeatedView<'_, $RsType$>) {
+ // TODO: Implement IntoProxied and avoid copying.
+ self.$field$_mut().copy_from(src);
+ }
+ )rs");
+ }},
+ },
+ R"rs(
$getter$
$getter_mut$
+ $setter$
)rs");
}
@@ -180,6 +197,8 @@
{"clearer_thunk", ThunkName(ctx, field, "clear")},
{"getter_thunk", ThunkName(ctx, field, "get")},
{"getter_mut_thunk", ThunkName(ctx, field, "get_mut")},
+ {"repeated_copy_from_thunk",
+ ThunkName(ctx, field, "repeated_copy_from")},
{"impls",
[&] {
ctx.Emit(