| #ifndef PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_PARSE_TEXT_PROTO_H_ |
| #define PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_PARSE_TEXT_PROTO_H_ |
| |
| #include <fcntl.h> |
| #include <unistd.h> |
| |
| #include <cerrno> |
| #include <cstring> |
| #include <optional> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/log/log.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/str_cat.h" |
| #include "absl/strings/string_view.h" |
| #include "google/protobuf/io/tokenizer.h" |
| #include "google/protobuf/io/zero_copy_stream_impl.h" |
| #include "google/protobuf/text_format.h" |
| |
| namespace safepower_agent { |
| namespace internal { |
| class ErrorCollector : public google::protobuf::io::ErrorCollector { |
| public: |
| ErrorCollector() = default; |
| ErrorCollector(const ErrorCollector&) = delete; |
| ErrorCollector& operator=(const ErrorCollector&) = delete; |
| |
| void RecordError(int line, google::protobuf::io::ColumnNumber column, |
| absl::string_view message) override; |
| void RecordWarning(int line, google::protobuf::io::ColumnNumber column, |
| absl::string_view message) override; |
| std::string message() && { return std::move(message_); } |
| |
| protected: |
| virtual std::string ExtractLine(int line) const = 0; |
| |
| private: |
| std::string message_; |
| }; |
| |
| class ErrorCollectorString : public ErrorCollector { |
| public: |
| explicit ErrorCollectorString(absl::string_view text_proto) |
| : text_proto_(text_proto) {} |
| std::string ExtractLine(int line) const override; |
| |
| private: |
| absl::string_view text_proto_; |
| }; |
| |
| class ErrorCollectorFile : public ErrorCollector { |
| public: |
| explicit ErrorCollectorFile(const std::string& path) : path_(path) {} |
| std::string ExtractLine(int line) const override; |
| |
| private: |
| const std::string& path_; |
| }; |
| |
| } // namespace internal |
| |
| template <typename Proto> |
| absl::StatusOr<Proto> ParseTextProto(absl::string_view text_proto) { |
| google::protobuf::TextFormat::Parser parser; |
| internal::ErrorCollectorString error_collector(text_proto); |
| parser.RecordErrorsTo(&error_collector); |
| Proto proto; |
| if (!parser.ParseFromString(text_proto, &proto)) { |
| return absl::InvalidArgumentError(std::move(error_collector).message()); |
| } |
| return proto; |
| } |
| |
| template <typename Proto> |
| absl::StatusOr<Proto> ParseTextProtoFromFile(const std::string& path) { |
| google::protobuf::TextFormat::Parser parser; |
| internal::ErrorCollectorFile error_collector(path); |
| parser.RecordErrorsTo(&error_collector); |
| Proto proto; |
| int fd = open(path.c_str(), O_RDONLY); |
| if (fd < 0) { |
| return absl::InvalidArgumentError( |
| absl::StrCat("Failed to open file: ", path, " :", strerror(errno))); |
| } |
| google::protobuf::io::FileInputStream stream(fd); |
| stream.SetCloseOnDelete(true); |
| if (!parser.Parse(&stream, &proto)) { |
| return absl::InvalidArgumentError(std::move(error_collector).message()); |
| } |
| return proto; |
| } |
| |
| } // namespace safepower_agent |
| |
| #endif // PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_PARSE_TEXT_PROTO_H_ |