1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -514,6 +514,33 @@ TProtoStringType MessageLite::SerializePartialAsString() const {
return output;
}
+#if PROTOBUF_USE_EXCEPTIONS && defined(__cpp_lib_string_view)
+void MessageLite::ParseFromStringOrThrow(std::string_view s) {
+ const bool isOk = ParseFromArray(s.data(), s.size());
+ if (!isOk) {
+ throw FatalException("message_lite.cc", __LINE__, "Failed to parse protobuf message " + GetTypeName());
+ }
+}
+#endif
+
+#if PROTOBUF_USE_EXCEPTIONS
+TProtoStringType NProtoBuf::MessageLite::SerializeAsStringOrThrow() const {
+ TProtoStringType s;
+ if (!IsInitialized()) {
+ //NOTE: SerializeToString (called inside SerializeAsString too) does not perform this check in release build
+ // so SerializeToString in release build return false only if result size is greater than 2gb
+ // but in debug build not properly inited message (without required filds) will lead to an exception
+ // different control flow in debug and build release look like a bug
+ throw FatalException("message_lite.cc", __LINE__, "Some required fileds are not set in message " + GetTypeName());
+ }
+ const bool isOk = SerializeToString(&s);
+ if (!isOk) {
+ throw FatalException("message_lite.cc", __LINE__, "Failed to serialize protobuf message " + GetTypeName());
+ }
+ return s;
+}
+#endif
+
namespace internal {
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -469,6 +469,14 @@ class PROTOBUF_EXPORT MessageLite {
return false;
}
+ #if PROTOBUF_USE_EXCEPTIONS && defined(__cpp_lib_string_view)
+ PROTOBUF_ATTRIBUTE_REINITIALIZES void ParseFromStringOrThrow(std::string_view s) noexcept(false);
+ #endif
+
+ #if PROTOBUF_USE_EXCEPTIONS
+ TProtoStringType SerializeAsStringOrThrow() const noexcept(false);
+ #endif
+
private:
friend class FastReflectionMessageMutator;
friend class FastReflectionStringSetter;
--- a/src/google/protobuf/stubs/common.cc (a305e8c438c21585e001abb5ada0122f6e1fc694)
+++ a/src/google/protobuf/stubs/common.cc (109a04575819756fff3dc3e089008c9b1e971f85)
@@ -159,6 +159,14 @@ arc_ui32 ghtonl(arc_ui32 x) {
return result;
}
+#if PROTOBUF_USE_EXCEPTIONS
+FatalException::~FatalException() throw() {}
+
+const char* FatalException::what() const throw() {
+ return message_.c_str();
+}
+#endif
+
} // namespace protobuf
} // namespace google
--- a/src/google/protobuf/stubs/common.h (a305e8c438c21585e001abb5ada0122f6e1fc694)
+++ a/src/google/protobuf/stubs/common.h (109a04575819756fff3dc3e089008c9b1e971f85)
@@ -45,6 +45,16 @@
#include "google/protobuf/stubs/platform_macros.h"
#include "google/protobuf/stubs/port.h"
+#ifndef PROTOBUF_USE_EXCEPTIONS
+#if defined(_MSC_VER) && defined(_CPPUNWIND)
+ #define PROTOBUF_USE_EXCEPTIONS 1
+#elif defined(__EXCEPTIONS)
+ #define PROTOBUF_USE_EXCEPTIONS 1
+#else
+ #define PROTOBUF_USE_EXCEPTIONS 0
+#endif
+#endif
+
#define Y_PROTOBUF_SUPPRESS_NODISCARD [[maybe_unused]] bool Y_GENERATE_UNIQUE_ID(pb_checker)=
#if defined(__APPLE__)
@@ -101,6 +111,26 @@ ProtocVersionString(int version); // NOLINT(runtime/string)
} // namespace internal
+#if PROTOBUF_USE_EXCEPTIONS
+class FatalException : public std::exception {
+ public:
+ FatalException(const char* filename, int line, const TProtoStringType& message)
+ : filename_(filename), line_(line), message_(message) {}
+ virtual ~FatalException() throw();
+
+ const char* what() const throw() override;
+
+ const char* filename() const { return filename_; }
+ int line() const { return line_; }
+ const TProtoStringType& message() const { return message_; }
+
+ private:
+ const char* filename_;
+ const int line_;
+ const TProtoStringType message_;
+};
+#endif
+
// Place this macro in your main() function (or somewhere before you attempt
// to use the protobuf library) to verify that the version you link against
// matches the headers you compiled against. If a version mismatch is
|