// cs/net/proto/db/field_path_builder.gpt.hh
#ifndef CS_NET_PROTO_DB_FIELD_PATH_BUILDER_GPT_HH
#define CS_NET_PROTO_DB_FIELD_PATH_BUILDER_GPT_HH
#include <cstdio>
#include <cstdlib>
#include <string>
#include <type_traits>
namespace cs::net::proto::db {
// Default: no specialization; abort at runtime.
// Specializations from gencode + explicit instantiations in
// proto .cc export symbols.
template <typename T, typename FieldType>
std::string GetFieldPath(FieldType T::*member_ptr) {
std::fprintf(stderr,
"GetFieldPath: no specialization for type; "
"include gencode "
"header. Aborting.\n");
std::abort();
}
template <typename T>
struct FieldProxy {
std::string path;
FieldProxy() : path("") {}
explicit FieldProxy(const std::string& p) : path(p) {}
template <typename FieldType>
FieldProxy<FieldType> operator>>(FieldType T::*ptr) {
std::string field_path = GetFieldPath(ptr);
std::string new_path;
if (path.empty()) {
new_path = field_path;
} else {
new_path = path + "." + field_path;
}
return FieldProxy<FieldType>{new_path};
}
const std::string& get_path() const { return path; }
};
template <typename T>
struct FieldPathBuilder {
std::string path;
FieldPathBuilder() : path("") {}
explicit FieldPathBuilder(const std::string& p)
: path(p) {}
template <typename FieldType>
FieldProxy<FieldType> operator>>(FieldType T::*ptr) {
std::string field_path = GetFieldPath(ptr);
std::string new_path;
if (path.empty()) {
new_path = field_path;
} else {
new_path = path + "." + field_path;
}
return FieldProxy<FieldType>{new_path};
}
const std::string& get_path() const { return path; }
};
// Note: FieldPathBuilder is typically used via
// codegen-generated instances like: `log >> request >>
// path` where `log` is a FieldPathBuilder<Log> instance
// generated by codegen.
template <typename T>
std::string GetFieldPathOrConvert(T&& arg) {
if constexpr (std::is_member_pointer_v<std::decay_t<T>>) {
return GetFieldPath(arg);
} else {
// FieldProxy or FieldPathBuilder (has get_path())
return std::string(arg.get_path());
}
}
} // namespace cs::net::proto::db
#endif // CS_NET_PROTO_DB_FIELD_PATH_BUILDER_GPT_HH