diff --git a/rust/codegen_traits.rs b/rust/codegen_traits.rs index 1f7e2c9bbf..88864be9da 100644 --- a/rust/codegen_traits.rs +++ b/rust/codegen_traits.rs @@ -37,7 +37,7 @@ pub trait Message: SealedInternal pub trait MessageView<'msg>: SealedInternal + ViewProxy<'msg, Proxied = Self::Message> // Read traits: - + Debug + Serialize + + Debug + Serialize + Default // Thread safety: + Send + Sync // Copy/Clone: diff --git a/rust/test/shared/serialization_test.rs b/rust/test/shared/serialization_test.rs index f30754d48b..789e2fbef6 100644 --- a/rust/test/shared/serialization_test.rs +++ b/rust/test/shared/serialization_test.rs @@ -7,6 +7,7 @@ use googletest::prelude::*; use protobuf::prelude::*; +use protobuf::View; use edition_unittest_rust_proto::TestAllTypes as TestAllTypesEditions; use paste::paste; @@ -31,6 +32,12 @@ macro_rules! generate_parameterized_serialization_test { assert_that!(serialized.len(), eq(0)); } + #[gtest] + fn [< serialize_default_view $name_ext>]() { + let default = View::<[< $type >]>::default(); + assert_that!(default.serialize().unwrap().len(), eq(0)); + } + #[gtest] fn [< serialize_deserialize_message_ $name_ext>]() { let mut msg = [< $type >]::new(); diff --git a/src/google/protobuf/compiler/rust/message.cc b/src/google/protobuf/compiler/rust/message.cc index 235f8ffc3d..7f0dec216d 100644 --- a/src/google/protobuf/compiler/rust/message.cc +++ b/src/google/protobuf/compiler/rust/message.cc @@ -195,6 +195,7 @@ void CppMessageExterns(Context& ctx, const Descriptor& msg) { ABSL_CHECK(ctx.is_cpp()); ctx.Emit( {{"new_thunk", ThunkName(ctx, msg, "new")}, + {"default_instance_thunk", ThunkName(ctx, msg, "default_instance")}, {"repeated_new_thunk", ThunkName(ctx, msg, "repeated_new")}, {"repeated_free_thunk", ThunkName(ctx, msg, "repeated_free")}, {"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")}, @@ -207,6 +208,7 @@ void CppMessageExterns(Context& ctx, const Descriptor& msg) { {"map_size_info_thunk", ThunkName(ctx, msg, "size_info")}}, R"rs( fn $new_thunk$() -> $pbr$::RawMessage; + fn $default_instance_thunk$() -> $pbr$::RawMessage; fn $repeated_new_thunk$() -> $pbr$::RawRepeatedField; fn $repeated_free_thunk$(raw: $pbr$::RawRepeatedField); fn $repeated_len_thunk$(raw: $pbr$::RawRepeatedField) -> usize; @@ -733,6 +735,16 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) { } } +void GenerateDefaultInstanceImpl(Context& ctx, const Descriptor& msg) { + if (ctx.is_upb()) { + ctx.Emit("$pbr$::ScratchSpace::zeroed_block()"); + } else { + ctx.Emit( + {{"default_instance_thunk", ThunkName(ctx, msg, "default_instance")}}, + "unsafe { $default_instance_thunk$() }"); + } +} + } // namespace void GenerateRs(Context& ctx, const Descriptor& msg) { @@ -749,6 +761,8 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { {"Msg::drop", [&] { MessageDrop(ctx, msg); }}, {"Msg::debug", [&] { MessageDebug(ctx, msg); }}, {"MsgMut::merge_from", [&] { MessageMutMergeFrom(ctx, msg); }}, + {"default_instance_impl", + [&] { GenerateDefaultInstanceImpl(ctx, msg); }}, {"accessor_fns", [&] { for (int i = 0; i < msg.field_count(); ++i) { @@ -948,6 +962,12 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { } } + impl $std$::default::Default for $Msg$View<'_> { + fn default() -> $Msg$View<'static> { + $Msg$View::new($pbi$::Private, $default_instance_impl$) + } + } + #[allow(dead_code)] impl<'msg> $Msg$View<'msg> { #[doc(hidden)] @@ -1367,6 +1387,7 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) { {"Msg", RsSafeName(msg.name())}, {"QualifiedMsg", cpp::QualifiedClassName(&msg)}, {"new_thunk", ThunkName(ctx, msg, "new")}, + {"default_instance_thunk", ThunkName(ctx, msg, "default_instance")}, {"repeated_new_thunk", ThunkName(ctx, msg, "repeated_new")}, {"repeated_free_thunk", ThunkName(ctx, msg, "repeated_free")}, {"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")}, @@ -1403,6 +1424,10 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) { extern $abi$ { void* $new_thunk$() { return new $QualifiedMsg$(); } + const google::protobuf::MessageLite* $default_instance_thunk$() { + return &$QualifiedMsg$::default_instance(); + } + void* $repeated_new_thunk$() { return new google::protobuf::RepeatedPtrField<$QualifiedMsg$>(); }