blob: 36a8c701fe8cfbe3addd5566e97b62753d9cdf60 [file] [log] [blame] [edit]
#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_DETERMINISTIC_BMC_OFFLINE_CONFIG_PARSER_PROTO_READER_H_
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_DETERMINISTIC_BMC_OFFLINE_CONFIG_PARSER_PROTO_READER_H_
#include <cstdint>
#include <filesystem> // NOLINT
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <system_error> // NOLINT
#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/message.h"
#include "google/protobuf/text_format.h"
namespace deterministic_bmc {
enum ProtoFormat : uint8_t {
kTextProto,
kBinaryProto,
};
inline std::ostream& operator<<(std::ostream& os, ProtoFormat format) {
switch (format) {
case ProtoFormat::kTextProto:
return os << "TextProto";
case ProtoFormat::kBinaryProto:
return os << "BinaryProto";
default:
return os << "Invalid ProtoFormat";
}
}
template <typename T>
class ProtoReader {
public:
// Reads a proto from a file.
//
// path: The path to the file.
// format: The format of the proto.
//
// Returns a proto if successful, or an error if unsuccessful.
static absl::StatusOr<T> ReadProtoFromFile(absl::string_view path,
ProtoFormat format);
};
template <typename T>
absl::StatusOr<T> ProtoReader<T>::ReadProtoFromFile(absl::string_view path,
ProtoFormat format) {
std::error_code ec;
if (!std::filesystem::exists(path, ec)) {
LOG(WARNING)
<< "Proto file " << path
<< " does not exist or filesystem::exists() failed with error: "
<< (ec ? "N/A" : ec.message());
return absl::NotFoundError(
absl::StrCat("ProtoReader: File not found: ", path));
}
std::ifstream input(std::string(path), format == ProtoFormat::kBinaryProto
? std::ios::in | std::ios::binary
: std::ios::in);
if (!input.is_open()) {
LOG(WARNING) << "Error opening file: " << path;
return absl::InternalError(
absl::StrCat("ProtoReader: Failed to open file: ", path));
}
// Read the entire file into a stringstream
std::stringstream buffer;
buffer << input.rdbuf();
input.close();
T config;
// Parse the proto from the string
const std::string format_str =
(format == ProtoFormat::kBinaryProto) ? "binary" : "text";
if (format == ProtoFormat::kBinaryProto
? !config.ParseFromString(buffer.str())
: !::google::protobuf::TextFormat::ParseFromString(buffer.str(), &config)) {
LOG(WARNING) << "Error parsing " << format_str
<< " proto from file: " << path;
return absl::InternalError(absl::StrCat("ProtoReader: Failed to parse ",
format_str,
" proto from file: ", path));
}
return config;
}
} // namespace deterministic_bmc
#endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_DETERMINISTIC_BMC_OFFLINE_CONFIG_PARSER_PROTO_READER_H_