Skip to content

Commit

Permalink
Implement flat setters for map and repeated fields.
Browse files Browse the repository at this point in the history
This doesn't yet use the new IntoProxied trait, but is functionaly equivalent with MutProxy::set() and always copies.

PiperOrigin-RevId: 627693770
  • Loading branch information
buchgr authored and Copybara-Service committed Apr 30, 2024
1 parent 6d33efe commit 7426ad3
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 33 deletions.
17 changes: 17 additions & 0 deletions rust/test/shared/accessors_map_test.rs
Expand Up @@ -157,6 +157,23 @@ fn test_bytes_and_string_copied() {
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 $(,)?)),*
Expand Down
14 changes: 8 additions & 6 deletions rust/test/shared/accessors_repeated_test.rs
Expand Up @@ -55,16 +55,17 @@ macro_rules! generate_repeated_numeric_test {
#[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<_>>())
);
}
Expand Down Expand Up @@ -177,15 +178,16 @@ fn test_repeated_enum_accessors() {
#[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]
Expand Down
14 changes: 14 additions & 0 deletions src/google/protobuf/compiler/rust/accessors/map.cc
Expand Up @@ -42,6 +42,7 @@ void Map::InMsgImpl(Context& ctx, const FieldDescriptor& field,
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)},
Expand Down Expand Up @@ -99,10 +100,23 @@ void Map::InMsgImpl(Context& ctx, const FieldDescriptor& field,
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");
}

Expand Down
73 changes: 46 additions & 27 deletions src/google/protobuf/compiler/rust/accessors/repeated_field.cc
Expand Up @@ -23,16 +23,19 @@ namespace rust {
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$(
Expand All @@ -47,8 +50,8 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field,
)
}
)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(
Expand All @@ -58,16 +61,16 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field,
}
}
)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(
Expand All @@ -85,8 +88,8 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field,
}
}
)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(
Expand All @@ -99,11 +102,25 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field,
}
}
)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");
}

Expand Down Expand Up @@ -180,6 +197,8 @@ void RepeatedField::InThunkCc(Context& ctx,
{"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(
Expand Down

0 comments on commit 7426ad3

Please sign in to comment.