Add merge_from to Msg and MsgMut codegen. Cpp Kernel uses new thunk to typed MergeFrom() and Upb Kernel uses new upb_Message_MergeFrom() function

PiperOrigin-RevId: 646961954
pull/17246/head
Derek Benson 11 months ago committed by Copybara-Service
parent 3836fd3474
commit 237332ef92
  1. 26
      rust/test/shared/BUILD
  2. 54
      rust/test/shared/merge_from_test.rs
  3. 54
      src/google/protobuf/compiler/rust/message.cc

@ -362,6 +362,32 @@ rust_test(
],
)
rust_test(
name = "merge_from_cpp_test",
srcs = ["merge_from_test.rs"],
aliases = {
"//rust:protobuf_cpp": "protobuf",
},
deps = [
"//rust:protobuf_cpp",
"//rust/test:unittest_cpp_rust_proto",
"@crate_index//:googletest",
],
)
rust_test(
name = "merge_from_upb_test",
srcs = ["merge_from_test.rs"],
aliases = {
"//rust:protobuf_upb": "protobuf",
},
deps = [
"//rust:protobuf_upb",
"//rust/test:unittest_upb_rust_proto",
"@crate_index//:googletest",
],
)
rust_test(
name = "proto_macro_cpp_test",
srcs = ["proto_macro_test.rs"],

@ -0,0 +1,54 @@
use googletest::prelude::*;
use protobuf::proto;
use unittest_rust_proto::{NestedTestAllTypes, TestAllTypes};
#[test]
fn merge_from_empty() {
let mut dst = TestAllTypes::new();
let src = TestAllTypes::new();
dst.merge_from(src.as_view());
assert_that!(dst.as_view().has_optional_int32(), eq(false));
}
#[test]
fn merge_from_non_empty() {
let mut dst = TestAllTypes::new();
let src = proto!(TestAllTypes { optional_int32: 42 });
dst.as_mut().merge_from(src.as_view());
assert_eq!(dst.as_view().optional_int32(), 42);
}
#[test]
fn merge_repeated_empty() {
let mut dst = TestAllTypes::new();
let mut src = TestAllTypes::new();
src.repeated_int32_mut().extend(0..5);
dst.merge_from(src.as_view());
assert_that!(
&dst.repeated_int32().iter().collect::<Vec<_>>(),
eq(&src.repeated_int32().iter().collect::<Vec<_>>())
);
}
#[test]
fn merge_repeated_non_empty() {
let mut dst = TestAllTypes::new();
let mut src = TestAllTypes::new();
dst.repeated_int32_mut().extend(0..5);
src.repeated_int32_mut().extend(5..10);
dst.merge_from(src.as_view());
assert_that!(
&dst.repeated_int32().iter().collect::<Vec<_>>(),
eq(&(0..10).collect::<Vec<_>>())
);
}
#[test]
fn merge_from_sub_message() {
let mut dst = NestedTestAllTypes::new();
let src = proto!(NestedTestAllTypes {
child: NestedTestAllTypes { payload: TestAllTypes { optional_int32: 42 } }
});
dst.merge_from(src.as_view());
assert_that!(dst.as_view().child().payload().optional_int32(), eq(42));
}

@ -178,6 +178,7 @@ void MessageExterns(Context& ctx, const Descriptor& msg) {
{"serialize_thunk", ThunkName(ctx, msg, "serialize")},
{"parse_thunk", ThunkName(ctx, msg, "parse")},
{"copy_from_thunk", ThunkName(ctx, msg, "copy_from")},
{"merge_from_thunk", ThunkName(ctx, msg, "merge_from")},
{"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")},
{"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")},
{"repeated_get_mut_thunk",
@ -195,6 +196,7 @@ void MessageExterns(Context& ctx, const Descriptor& msg) {
fn $serialize_thunk$(raw_msg: $pbr$::RawMessage, out: &mut $pbr$::SerializedData) -> bool;
fn $parse_thunk$(raw_msg: $pbr$::RawMessage, data: $pbr$::SerializedData) -> bool;
fn $copy_from_thunk$(dst: $pbr$::RawMessage, src: $pbr$::RawMessage);
fn $merge_from_thunk$(dst: $pbr$::RawMessage, src: $pbr$::RawMessage);
fn $repeated_len_thunk$(raw: $pbr$::RawRepeatedField) -> usize;
fn $repeated_add_thunk$(raw: $pbr$::RawRepeatedField) -> $pbr$::RawMessage;
fn $repeated_get_thunk$(raw: $pbr$::RawRepeatedField, index: usize) -> $pbr$::RawMessage;
@ -304,6 +306,46 @@ void MessageGetMinitable(Context& ctx, const Descriptor& msg) {
}
}
void MessageMergeFrom(Context& ctx, const Descriptor& msg) {
switch (ctx.opts().kernel) {
case Kernel::kCpp:
ctx.Emit(
{
{"merge_from_thunk", ThunkName(ctx, msg, "merge_from")},
},
R"rs(
pub fn merge_from<'src>(&mut self, src: impl $pb$::ViewProxy<'src, Proxied = $Msg$>) {
// SAFETY: self and src are both valid `$Msg$`s.
unsafe {
$merge_from_thunk$(self.raw_msg(), src.as_view().raw_msg());
}
}
)rs");
return;
case Kernel::kUpb:
ctx.Emit(
{
{"minitable", UpbMinitableName(msg)},
},
R"rs(
pub fn merge_from<'src>(&mut self, src: impl $pb$::ViewProxy<'src, Proxied = $Msg$>) {
// SAFETY: self and src are both valid `$Msg$`s.
unsafe {
assert!(
$pbr$::upb_Message_MergeFrom(self.raw_msg(),
src.as_view().raw_msg(),
$std$::ptr::addr_of!($minitable$),
// Use a nullptr for the ExtensionRegistry.
$std$::ptr::null(),
self.arena().raw())
);
}
}
)rs");
return;
}
}
void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) {
switch (ctx.opts().kernel) {
case Kernel::kCpp:
@ -863,6 +905,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
}},
{"into_proxied_impl", [&] { IntoProxiedForMessage(ctx, msg); }},
{"get_upb_minitable", [&] { MessageGetMinitable(ctx, msg); }},
{"msg_merge_from", [&] { MessageMergeFrom(ctx, msg); }},
{"repeated_impl", [&] { MessageProxiedInRepeated(ctx, msg); }},
{"map_value_impl", [&] { MessageProxiedInMapValue(ctx, msg); }},
{"unwrap_upb",
@ -1023,6 +1066,8 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
$pb$::ViewProxy::as_view(self).to_owned()
}
$msg_merge_from$
$get_upb_minitable$
$raw_arena_getter_for_msgmut$
@ -1092,6 +1137,10 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
$Msg$Mut::new($pbi$::Private, &mut self.inner)
}
pub fn merge_from<'src>(&mut self, src: impl $pb$::ViewProxy<'src, Proxied = $Msg$>) {
self.as_mut().merge_from(src);
}
$get_upb_minitable$
$accessor_fns$
@ -1181,6 +1230,7 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
{"serialize_thunk", ThunkName(ctx, msg, "serialize")},
{"parse_thunk", ThunkName(ctx, msg, "parse")},
{"copy_from_thunk", ThunkName(ctx, msg, "copy_from")},
{"merge_from_thunk", ThunkName(ctx, msg, "merge_from")},
{"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")},
{"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")},
{"repeated_get_mut_thunk", ThunkName(ctx, msg, "repeated_get_mut")},
@ -1229,6 +1279,10 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
dst->CopyFrom(*src);
}
void $merge_from_thunk$($QualifiedMsg$* dst, const $QualifiedMsg$* src) {
dst->MergeFrom(*src);
}
size_t $repeated_len_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) {
return field->size();
}

Loading…
Cancel
Save