64 google::protobuf::Message* proto,
67 std::string uncompressed;
69 VLOG(1) <<
"ReadFileToProto(): input is gzipped";
82 constexpr double kMaxBinaryProtoParseShrinkFactor = 2;
83 std::string binary_format_error;
84 if (proto->ParsePartialFromString(data) &&
85 (allow_partial || proto->IsInitialized())) {
91 proto->DiscardUnknownFields();
92 if (proto->ByteSizeLong() <
93 data.size() / kMaxBinaryProtoParseShrinkFactor) {
95 "The input may be a binary protobuf payload, but it"
96 " probably is from a different proto class";
98 VLOG(1) <<
"StringToProto(): input seems to be a binary proto";
99 return absl::OkStatus();
103 struct :
public google::protobuf::io::ErrorCollector {
104 void RecordError(
int line, google::protobuf::io::ColumnNumber column,
105 absl::string_view error_message)
override {
106 if (!message.empty()) message +=
", ";
107 absl::StrAppendFormat(&message,
"%d:%d: %s",
109 line + 1, column, error_message);
113 google::protobuf::TextFormat::Parser text_parser;
114 text_parser.RecordErrorsTo(&text_format_error);
115 text_parser.AllowPartialMessage(allow_partial);
116 if (text_parser.ParseFromString(data, proto)) {
117 VLOG(1) <<
"StringToProto(): input is a text proto";
118 return absl::OkStatus();
120 std::string json_error;
121 absl::Status json_status =
122 JsonStringToMessage(data, proto, JsonParseOptions());
123 if (json_status.ok()) {
128 constexpr int kMaxJsonToBinaryShrinkFactor = 30;
129 if (proto->ByteSizeLong() < data.size() / kMaxJsonToBinaryShrinkFactor) {
130 json_status = absl::InvalidArgumentError(
131 "The input looks like valid JSON, but probably not"
132 " of the right proto class");
134 VLOG(1) <<
"StringToProto(): input is a proto JSON";
135 return absl::OkStatus();
138 return absl::InvalidArgumentError(absl::StrFormat(
139 "binary format error: '%s', text format error: '%s', json error: '%s'",
140 binary_format_error, text_format_error.message, json_status.message()));
144 const google::protobuf::Message& proto,
146 bool append_extension_to_file_name) {
147 std::string file_type_suffix;
148 std::string output_string;
149 google::protobuf::io::StringOutputStream stream(&output_string);
150 auto make_error = [filename](absl::string_view error_message) {
151 return absl::InternalError(absl::StrFormat(
152 "WriteProtoToFile('%s') failed: %s", filename, error_message));
154 switch (proto_write_format) {
156 if (!proto.SerializeToZeroCopyStream(&stream)) {
157 return make_error(
"SerializeToZeroCopyStream()");
159 file_type_suffix =
".bin";
162 if (!google::protobuf::TextFormat::PrintToString(proto, &output_string)) {
163 return make_error(
"TextFormat::PrintToString()");
167 google::protobuf::util::JsonPrintOptions options;
168 options.add_whitespace =
true;
169 options.always_print_fields_with_no_presence =
true;
170 options.preserve_proto_field_names =
true;
171 if (!google::protobuf::util::MessageToJsonString(proto, &output_string,
174 LOG(WARNING) <<
"Printing to stream failed.";
175 return make_error(
"google::protobuf::util::MessageToJsonString()");
177 file_type_suffix =
".json";
181 google::protobuf::util::JsonPrintOptions options;
182 options.add_whitespace =
true;
183 if (!google::protobuf::util::MessageToJsonString(proto, &output_string,
186 LOG(WARNING) <<
"Printing to stream failed.";
187 return make_error(
"google::protobuf::util::MessageToJsonString()");
189 file_type_suffix =
".json";
193 std::string gzip_string;
195 output_string.swap(gzip_string);
196 file_type_suffix +=
".gz";
198 std::string output_filename(filename);
199 if (append_extension_to_file_name) output_filename += file_type_suffix;
200 VLOG(1) <<
"Writing " << output_string.size() <<
" bytes to '"
201 << output_filename <<
"'";
absl::Status StringToProto(absl::string_view data, google::protobuf::Message *proto, bool allow_partial)
Exactly like ReadFileToProto(), but directly from the contents.
absl::Status WriteProtoToFile(absl::string_view filename, const google::protobuf::Message &proto, ProtoWriteFormat proto_write_format, bool gzipped, bool append_extension_to_file_name)