diff --git a/rust/cpp.rs b/rust/cpp.rs index 2a199dcc61..1a623ee947 100644 --- a/rust/cpp.rs +++ b/rust/cpp.rs @@ -140,6 +140,10 @@ pub struct SerializedData { } impl SerializedData { + pub fn new() -> Self { + Self { data: NonNull::dangling(), len: 0 } + } + /// Constructs owned serialized data from raw components. /// /// # Safety diff --git a/rust/cpp_kernel/BUILD b/rust/cpp_kernel/BUILD index 5de02e55d8..2438bfb79d 100644 --- a/rust/cpp_kernel/BUILD +++ b/rust/cpp_kernel/BUILD @@ -14,7 +14,7 @@ cc_library( ":rust_alloc_for_cpp_api", # buildcleaner: keep "//src/google/protobuf", "//src/google/protobuf:protobuf_lite", - "@com_google_absl//absl/strings:string_view", + "@com_google_absl//absl/log:absl_log", ], ) diff --git a/rust/cpp_kernel/cpp_api.h b/rust/cpp_kernel/cpp_api.h index e165e8b838..44f299feb5 100644 --- a/rust/cpp_kernel/cpp_api.h +++ b/rust/cpp_kernel/cpp_api.h @@ -14,7 +14,9 @@ #include #include +#include "absl/log/absl_log.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" namespace google { namespace protobuf { @@ -41,16 +43,17 @@ extern "C" struct SerializedData { // This function is defined in `rust_alloc_for_cpp_api.rs`. extern "C" void* __pb_rust_alloc(size_t size, size_t align); -inline SerializedData SerializeMsg(const google::protobuf::MessageLite* msg) { +inline bool SerializeMsg(const google::protobuf::MessageLite* msg, SerializedData* out) { size_t len = msg->ByteSizeLong(); void* bytes = __pb_rust_alloc(len, alignof(char)); if (bytes == nullptr) { ABSL_LOG(FATAL) << "Rust allocator failed to allocate memory."; } if (!msg->SerializeToArray(bytes, static_cast(len))) { - ABSL_LOG(FATAL) << "Couldn't serialize the message."; + return false; } - return SerializedData(static_cast(bytes), len); + *out = SerializedData(static_cast(bytes), len); + return true; } // Represents an ABI-stable version of &[u8]/string_view (borrowed slice of diff --git a/rust/test/cpp/interop/BUILD b/rust/test/cpp/interop/BUILD index 6faac7a5a3..b4915b8d32 100644 --- a/rust/test/cpp/interop/BUILD +++ b/rust/test/cpp/interop/BUILD @@ -8,6 +8,7 @@ cc_library( deps = [ "//rust/cpp_kernel:cpp_api", "//src/google/protobuf:unittest_cc_proto", + "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/strings", ], ) diff --git a/rust/test/cpp/interop/test_utils.cc b/rust/test/cpp/interop/test_utils.cc index 823c916129..a3010df7f8 100644 --- a/rust/test/cpp/interop/test_utils.cc +++ b/rust/test/cpp/interop/test_utils.cc @@ -8,19 +8,25 @@ #include #include +#include "absl/log/absl_check.h" #include "absl/strings/string_view.h" #include "rust/cpp_kernel/cpp_api.h" #include "google/protobuf/unittest.pb.h" +using google::protobuf::rust_internal::SerializedData; +using google::protobuf::rust_internal::SerializeMsg; + extern "C" void MutateTestAllTypes(protobuf_unittest::TestAllTypes* msg) { msg->set_optional_int64(42); msg->set_optional_bytes("something mysterious"); msg->set_optional_bool(false); } -extern "C" google::protobuf::rust_internal::SerializedData SerializeTestAllTypes( +extern "C" SerializedData SerializeTestAllTypes( const protobuf_unittest::TestAllTypes* msg) { - return google::protobuf::rust_internal::SerializeMsg(msg); + SerializedData data(nullptr, 0); + ABSL_CHECK(SerializeMsg(msg, &data)); + return data; } extern "C" void DeleteTestAllTypes(protobuf_unittest::TestAllTypes* msg) { diff --git a/src/google/protobuf/compiler/rust/message.cc b/src/google/protobuf/compiler/rust/message.cc index d7443d03f0..4b138b931c 100644 --- a/src/google/protobuf/compiler/rust/message.cc +++ b/src/google/protobuf/compiler/rust/message.cc @@ -61,8 +61,15 @@ void MessageSerialize(Context& ctx, const Descriptor& msg) { switch (ctx.opts().kernel) { case Kernel::kCpp: ctx.Emit({{"serialize_thunk", ThunkName(ctx, msg, "serialize")}}, R"rs( - //~ TODO: This should be fallible. - Ok(unsafe { $serialize_thunk$(self.raw_msg()) }) + let mut serialized_data = $pbr$::SerializedData::new(); + let success = unsafe { + $serialize_thunk$(self.raw_msg(), &mut serialized_data) + }; + if success { + Ok(serialized_data) + } else { + Err($pb$::SerializeError) + } )rs"); return; @@ -185,7 +192,7 @@ void MessageExterns(Context& ctx, const Descriptor& msg) { R"rs( fn $new_thunk$() -> $pbr$::RawMessage; fn $delete_thunk$(raw_msg: $pbr$::RawMessage); - fn $serialize_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::SerializedData; + 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 $repeated_len_thunk$(raw: $pbr$::RawRepeatedField) -> usize; @@ -1210,8 +1217,8 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) { extern $abi$ { void* $new_thunk$() { return new $QualifiedMsg$(); } void $delete_thunk$(void* ptr) { delete static_cast<$QualifiedMsg$*>(ptr); } - google::protobuf::rust_internal::SerializedData $serialize_thunk$($QualifiedMsg$* msg) { - return google::protobuf::rust_internal::SerializeMsg(msg); + bool $serialize_thunk$($QualifiedMsg$* msg, google::protobuf::rust_internal::SerializedData* out) { + return google::protobuf::rust_internal::SerializeMsg(msg, out); } bool $parse_thunk$($QualifiedMsg$* msg, google::protobuf::rust_internal::SerializedData data) {