Skip to content

Commit f810cc5

Browse files
Enable MessageLite::DebugString to use Message::DebugString where possible.
This will mean that calling DebugString on a MessageLite* which is actually a full Message will get the debug info instead of the minimal output. PiperOrigin-RevId: 649103508
1 parent 6750ed8 commit f810cc5

File tree

11 files changed

+67
-24
lines changed

11 files changed

+67
-24
lines changed

rust/cpp.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -293,17 +293,12 @@ impl From<RustStringRawParts> for String {
293293

294294
extern "C" {
295295
fn proto2_rust_utf8_debug_string(msg: RawMessage) -> RustStringRawParts;
296-
fn proto2_rust_utf8_debug_string_lite(msg: RawMessage) -> RustStringRawParts;
297296
}
298297

299298
pub fn debug_string(_private: Private, msg: RawMessage, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300299
// SAFETY:
301300
// - `msg` is a valid protobuf message.
302-
#[cfg(not(lite_runtime))]
303301
let dbg_str: String = unsafe { proto2_rust_utf8_debug_string(msg) }.into();
304-
#[cfg(lite_runtime)]
305-
let dbg_str: String = unsafe { proto2_rust_utf8_debug_string_lite(msg) }.into();
306-
307302
write!(f, "{dbg_str}")
308303
}
309304

rust/cpp_kernel/debug.cc

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,12 @@
22

33
#include <string>
44

5-
#include "google/protobuf/message.h"
65
#include "google/protobuf/message_lite.h"
76
#include "rust/cpp_kernel/strings.h"
87

98
extern "C" {
109

1110
google::protobuf::rust::RustStringRawParts proto2_rust_utf8_debug_string(
12-
const google::protobuf::Message* msg) {
13-
std::string text = google::protobuf::Utf8Format(*msg);
14-
return google::protobuf::rust::RustStringRawParts(text);
15-
}
16-
17-
google::protobuf::rust::RustStringRawParts proto2_rust_utf8_debug_string_lite(
1811
const google::protobuf::MessageLite* msg) {
1912
std::string text = google::protobuf::Utf8Format(*msg);
2013
return google::protobuf::rust::RustStringRawParts(text);

rust/cpp_kernel/debug.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_DEBUG_H__
22
#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_DEBUG_H__
33

4-
#include "google/protobuf/message.h"
54
#include "google/protobuf/message_lite.h"
65
#include "rust/cpp_kernel/strings.h"
76

87
extern "C" {
98

109
google::protobuf::rust::RustStringRawParts proto2_rust_utf8_debug_string(
11-
const google::protobuf::Message* msg);
12-
13-
google::protobuf::rust::RustStringRawParts proto2_rust_utf8_debug_string_lite(
1410
const google::protobuf::MessageLite* msg);
1511

1612
} // extern "C"

rust/test/cpp/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,27 @@ rust_cc_proto_library(
2929
deps = [":debug_proto"],
3030
)
3131

32+
proto_library(
33+
name = "optimize_for_lite_proto",
34+
testonly = True,
35+
srcs = ["optimize_for_lite.proto"],
36+
)
37+
38+
rust_cc_proto_library(
39+
name = "optimize_for_lite_cpp_rust_proto",
40+
testonly = True,
41+
visibility = [
42+
"//rust/test/shared:__subpackages__",
43+
],
44+
deps = [":optimize_for_lite_proto"],
45+
)
46+
3247
rust_test(
3348
name = "debug_test",
3449
srcs = ["debug_test.rs"],
3550
deps = [
3651
":debug_cpp_rust_proto",
52+
":optimize_for_lite_cpp_rust_proto",
3753
"//rust:protobuf_cpp",
3854
"@crate_index//:googletest",
3955
],

rust/test/cpp/debug_test.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use debug_rust_proto::DebugMsg;
22
use googletest::prelude::*;
3+
use optimize_for_lite_rust_proto::OptimizeForLiteTestMessage;
34

45
#[cfg(not(lite_runtime))]
56
#[test]
@@ -22,3 +23,14 @@ fn test_debug_lite() {
2223
assert_that!(format!("{msg:?}"), contains_substring("MessageLite"));
2324
assert_that!(format!("{msg:?}"), not(contains_substring("password")));
2425
}
26+
27+
/// A message with the option set to optimize for lite will behave as a lite
28+
/// message regardless of the `lite_runtime` feature. Run this test not guarded
29+
/// by the cfg(lite_runtime) and ensure it functions as lite.
30+
#[test]
31+
fn test_optimize_for_lite_option() {
32+
let mut msg = OptimizeForLiteTestMessage::new();
33+
msg.set_value("password");
34+
assert_that!(format!("{msg:?}"), contains_substring("MessageLite"));
35+
assert_that!(format!("{msg:?}"), not(contains_substring("password")));
36+
}

rust/test/cpp/optimize_for_lite.proto

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
edition = "2023";
2+
3+
package optimize_for_lite_test;
4+
5+
option java_multiple_files = true;
6+
option optimize_for = LITE_RUNTIME;
7+
8+
message OptimizeForLiteTestMessage {
9+
string value = 1;
10+
}

src/google/protobuf/compiler/rust/generator.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ bool RustGenerator::Generate(const FileDescriptor* file,
218218
#include "$proto_h$"
219219
$proto_deps_h$
220220
#include "google/protobuf/map.h"
221+
#include "google/protobuf/repeated_field.h"
221222
#include "google/protobuf/repeated_ptr_field.h"
222223
#include "google/protobuf/rust/cpp_kernel/map.h"
223224
#include "google/protobuf/rust/cpp_kernel/serialized_data.h"

src/google/protobuf/message.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,15 @@ size_t Message::SpaceUsedLongImpl(const MessageLite& msg_lite) {
224224
return msg.GetReflection()->SpaceUsedLong(msg);
225225
}
226226

227+
static std::string DebugStringImpl(const MessageLite& msg) {
228+
return DownCastMessage<Message>(msg).DebugString();
229+
}
230+
227231
PROTOBUF_CONSTINIT const MessageLite::DescriptorMethods
228232
Message::kDescriptorMethods = {
229-
GetTypeNameImpl,
230-
InitializationErrorStringImpl,
231-
GetTcParseTableImpl,
232-
SpaceUsedLongImpl,
233+
GetTypeNameImpl, InitializationErrorStringImpl,
234+
GetTcParseTableImpl, SpaceUsedLongImpl,
235+
DebugStringImpl,
233236
};
234237

235238
namespace internal {

src/google/protobuf/message_lite.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ std::string MessageLite::InitializationErrorString() const {
128128
}
129129

130130
std::string MessageLite::DebugString() const {
131+
auto* data = GetClassData();
132+
ABSL_DCHECK(data != nullptr);
133+
if (!data->is_lite) {
134+
return data->full().descriptor_methods->debug_string(*this);
135+
}
136+
131137
return absl::StrCat("MessageLite at 0x", absl::Hex(this));
132138
}
133139

src/google/protobuf/message_lite.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ class PROTOBUF_EXPORT MessageLite {
618618
std::string (*initialization_error_string)(const MessageLite&);
619619
const internal::TcParseTableBase* (*get_tc_table)(const MessageLite&);
620620
size_t (*space_used_long)(const MessageLite&);
621+
std::string (*debug_string)(const MessageLite&);
621622
};
622623

623624
// Note: The order of arguments in the functions is chosen so that it has

src/google/protobuf/message_unittest.inc

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
#include <sys/types.h>
1919

2020
#include <cmath>
21-
#include <functional>
21+
#include <cstddef>
22+
#include <cstdint>
2223
#include <limits>
23-
#include <vector>
24+
#include <string>
2425

2526
#ifndef _MSC_VER
2627
#include <unistd.h>
@@ -825,14 +826,23 @@ TEST(MESSAGE_TEST_NAME, DownCastMessageInvalidPointerType) {
825826
TEST(MESSAGE_TEST_NAME, DownCastMessageInvalidReferenceType) {
826827
UNITTEST::TestAllTypes test_all_types;
827828

828-
MessageLite& test_all_types_pointer = test_all_types;
829+
MessageLite& test_all_types_ref = test_all_types;
829830

830831
ASSERT_DEBUG_DEATH(
831-
DownCastMessage<UNITTEST::TestRequired>(test_all_types_pointer),
832+
DownCastMessage<UNITTEST::TestRequired>(test_all_types_ref),
832833
"Cannot downcast " + test_all_types.GetTypeName() + " to " +
833834
UNITTEST::TestRequired::default_instance().GetTypeName());
834835
}
835836

837+
TEST(MESSAGE_TEST_NAME, MessageDebugStringMatchesBehindPointerAndLitePointer) {
838+
UNITTEST::TestAllTypes test_all_types;
839+
test_all_types.set_optional_string("foo");
840+
Message* msg_full_pointer = &test_all_types;
841+
MessageLite* msg_lite_pointer = &test_all_types;
842+
ASSERT_EQ(test_all_types.DebugString(), msg_full_pointer->DebugString());
843+
ASSERT_EQ(test_all_types.DebugString(), msg_lite_pointer->DebugString());
844+
}
845+
836846
#if GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet.
837847

838848
TEST(MESSAGE_TEST_NAME, SerializeFailsIfNotInitialized) {

0 commit comments

Comments
 (0)