Skip to content

Commit

Permalink
Use boost::pfr::get_name(). Simplify emitter.
Browse files Browse the repository at this point in the history
  • Loading branch information
egorpugin committed Oct 18, 2023
1 parent eb194c4 commit 3302100
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 24 deletions.
41 changes: 35 additions & 6 deletions include/tgbot/bot.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,42 @@
#pragma once

#include <boost/pfr.hpp>
#include <nlohmann/json.hpp>

#include <cstdint>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <variant>
#include <vector>

#define TBGOT_TO_JSON_REQUEST_MACRO(f, ret) \
auto f(const f##Request &r) const { \
nlohmann::json j; \
boost::pfr::for_each_field(r, [&]<auto I>(auto &&field, std::integral_constant<size_t, I>) { \
to_json(j, boost::pfr::get_name<I, f##Request>(), field); \
}); \
j = send_request(#f, j.dump()); \
return from_json<ret>(j); \
}

#define TBGOT_TO_REQUEST_ARGUMENT_REQUEST_MACRO(f, ret) \
auto f(const f##Request &r) const { \
std::array<http_request_argument, boost::pfr::tuple_size<f##Request>> args; \
auto i = args.begin(); \
boost::pfr::for_each_field(r, [&]<auto I>(auto &&field, std::integral_constant<size_t, I>) { \
to_request_argument(i, boost::pfr::get_name<I, f##Request>(), field); \
}); \
auto j = send_request(#f, http_request_arguments{args.begin(), i}); \
return from_json<ret>(j); \
}

namespace tgbot {

using namespace std::literals;

using Boolean = bool;
using Integer = std::int64_t;
using Float = double;
Expand Down Expand Up @@ -71,7 +96,7 @@ struct api {
// Bot's HttpClient must implement
//std::string make_request(const std::string &url, const http_request_arguments &args) const;
//std::string make_request(const std::string &url, const std::string &json) const;
nlohmann::json send_request(const char *method, auto &&args) const {
nlohmann::json send_request(std::string_view method, auto &&args) const {
auto url = bot.base_url();
url += bot.token();
url += "/";
Expand Down Expand Up @@ -124,7 +149,7 @@ struct api {
return a;
}
}
static void to_request_argument(auto &&arg, const char *n, auto &&r) {
static void to_request_argument(auto &&arg, std::string_view n, auto &&r) {
if (auto v = to_request_argument(n, r); v)
*arg++ = std::move(*v);
}
Expand Down Expand Up @@ -152,12 +177,14 @@ struct api {
return j;
} else {
nlohmann::json j;
refl<T>::for_each([&v, &j](auto n, auto f) {to_json(j, n, v.*f); });
boost::pfr::for_each_field(v, [&]<auto I>(auto &&field, std::integral_constant<size_t, I>) {
to_json(j, boost::pfr::get_name<I, T>(), field);
});
return j;
}
}
template <typename T>
static void to_json(nlohmann::json &j, const char *k, const T &r) {
static void to_json(nlohmann::json &j, std::string_view k, const T &r) {
if (auto v = to_json(r); !v.is_null())
j[k] = v;
}
Expand All @@ -183,12 +210,14 @@ struct api {
return from_json(j, type<T>{});
} else {
T v;
refl<T>::for_each([&v, &j](auto n, auto f) {from_json(j, n, v.*f); });
boost::pfr::for_each_field(v, [&]<auto I>(auto &&field, std::integral_constant<size_t, I>) {
from_json(j, boost::pfr::get_name<I, T>(), field);
});
return v;
}
}
template <typename T>
static void from_json(const nlohmann::json &j, const char *k, T &v) {
static void from_json(const nlohmann::json &j, std::string_view k, T &v) {
if (j.contains(k))
v = from_json<T>(j[k]);
}
Expand Down
4 changes: 4 additions & 0 deletions sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ void build(Solution &s)
if (tgbot.getCompilerType() == CompilerType::MSVC)
tgbot.Public.CompileOptions.push_back("/Zc:__cplusplus");
tgbot.Public += "org.sw.demo.nlohmann.json"_dep;
tgbot.Public += "org.sw.demo.boostorg.pfr-develop"_dep;
{
auto c = tgbot.addCommand();
c << cmd::prog(apitool)
Expand All @@ -33,6 +34,9 @@ void build(Solution &s)
<< cmd::out("types.inl.h")
<< cmd::out("methods.inl.h")
;
// to make dependency? (in VS IDE only?)
//tgbot.Public += "types.inl.h";
//tgbot.Public += "methods.inl.h";
}
}

Expand Down
34 changes: 16 additions & 18 deletions tools/emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,13 @@ void Method::emit(const Emitter &e, primitives::CppEmitter &h) const {
cpp.addLine("std::array<http_request_argument, " + std::to_string(fields.size()) + "> args;");
cpp.addLine("auto i = args.begin();");
for (auto &f: fields)
cpp.addLine("to_request_argument(i, \"" + f.name + "\", " + f.name + ");");
cpp.addLine("auto j = send_request(\"" + name + "\", http_request_arguments{args.begin(), i});");
cpp.addLine("to_request_argument(i, \"" + f.name + "\"sv, " + f.name + ");");
cpp.addLine("auto j = send_request(\"" + name + "\"sv, http_request_arguments{args.begin(), i});");
} else {
cpp.addLine("nlohmann::json j;");
for (auto &f: fields)
cpp.addLine("to_json(j, \"" + f.name + "\", " + f.name + ");");
cpp.addLine("j = send_request(\"" + name + "\", j.dump());");
cpp.addLine("to_json(j, \"" + f.name + "\"sv, " + f.name + ");");
cpp.addLine("j = send_request(\"" + name + "\"sv, j.dump());");
}
cpp.addLine();
cpp.addText("return from_json<");
Expand All @@ -241,16 +241,10 @@ void Method::emit(const Emitter &e, primitives::CppEmitter &h) const {
// with request struct
if (!fields.empty()) {
cpp.addLine();
cpp.addText("auto " + name + "(const " + cpp_name() + " &r) const");
cpp.beginBlock();
cpp.addLine("return " + name + "(");
cpp.increaseIndent();
for (const auto &f: fields)
cpp.addLine("r." + f.name + ",");
cpp.trimEnd(1);
cpp.decreaseIndent();
cpp.addLine(");");
cpp.endBlock();
cpp.addText((!has_input_file ? "TBGOT_TO_JSON_REQUEST_MACRO"s : "TBGOT_TO_REQUEST_ARGUMENT_REQUEST_MACRO"s) +
"(" + name + ", ");
return_type.emitFieldType(cpp, true, true);
cpp.addText(")");
cpp.emptyLines();
}
}
Expand Down Expand Up @@ -312,6 +306,7 @@ void Emitter::emitTypesHeader() {
m.emitRequestType(ctx);
}
ctx.emptyLines();
//write_file("types.inl.h", ctx.getText());
write_file("types.inl.h", ctx.getText() + emitReflection());
}

Expand Down Expand Up @@ -408,21 +403,24 @@ String Emitter::emitReflection() const {
ctx.addLine();
// refl
for (auto &[n, t]: types) {
if (!t.is_received_variant(types)) {
continue;
}
ctx.addLine("template <> struct refl<" + t.name + "> {");
ctx.increaseIndent();
ctx.addLine("using T = " + t.name + ";");
ctx.addLine();
//ctx.addLine("using T = " + t.name + ";");
//ctx.addLine();
ctx.addLine(
"static constexpr auto is_received_variant = "s + (t.is_received_variant(types) ? "true" : "false") +
";");
//ctx.addLine("static constexpr auto size() { return " + std::to_string(t.fields.size()) + "; }");
ctx.addLine();
/*ctx.addLine();
ctx.addLine("template <typename F>");
ctx.addLine("static void for_each(F &&f) {");
ctx.increaseIndent();
for (auto &f: t.fields)
ctx.addLine("f(\"" + f.name + "\", &T::" + f.name + ");");
ctx.endBlock();
ctx.endBlock();*/
ctx.endBlock(true);
ctx.emptyLines();
}
Expand Down

0 comments on commit 3302100

Please sign in to comment.