diff --git a/td/generate/generate_json.cpp b/td/generate/generate_json.cpp index 5b75a88e..d8d64eeb 100644 --- a/td/generate/generate_json.cpp +++ b/td/generate/generate_json.cpp @@ -10,5 +10,6 @@ #include "td/tl/tl_generate.h" int main() { - td::gen_json_converter(td::tl::read_tl_config_from_file("scheme/td_api.tlo"), "td/telegram/td_api_json"); + td::gen_json_converter(td::tl::read_tl_config_from_file("scheme/td_api.tlo"), "td/telegram/td_api_json", + td::tl::TL_writer::Server); } diff --git a/td/generate/tl_json_converter.cpp b/td/generate/tl_json_converter.cpp index 42cd6877..5910ade4 100644 --- a/td/generate/tl_json_converter.cpp +++ b/td/generate/tl_json_converter.cpp @@ -19,6 +19,8 @@ namespace td { +using Mode = tl::TL_writer::Mode; + template void gen_to_json_constructor(StringBuilder &sb, const T *constructor, bool is_header) { sb << "void to_json(JsonValueScope &jv, " @@ -55,8 +57,11 @@ void gen_to_json_constructor(StringBuilder &sb, const T *constructor, bool is_he sb << "}\n"; } -void gen_to_json(StringBuilder &sb, const tl::simple::Schema &schema, bool is_header) { +void gen_to_json(StringBuilder &sb, const tl::simple::Schema &schema, bool is_header, Mode mode) { for (auto *custom_type : schema.custom_types) { + if (!((custom_type->is_query_ && mode != Mode::Server) || (custom_type->is_result_ && mode != Mode::Client))) { + continue; + } if (custom_type->constructors.size() > 1) { auto type_name = tl::simple::gen_cpp_name(custom_type->name); sb << "void to_json(JsonValueScope &jv, const td_api::" << type_name << " &object)"; @@ -74,6 +79,9 @@ void gen_to_json(StringBuilder &sb, const tl::simple::Schema &schema, bool is_he gen_to_json_constructor(sb, constructor, is_header); } } + if (mode == Mode::Server) { + return; + } for (auto *function : schema.functions) { gen_to_json_constructor(sb, function, is_header); } @@ -104,12 +112,18 @@ void gen_from_json_constructor(StringBuilder &sb, const T *constructor, bool is_ } } -void gen_from_json(StringBuilder &sb, const tl::simple::Schema &schema, bool is_header) { +void gen_from_json(StringBuilder &sb, const tl::simple::Schema &schema, bool is_header, Mode mode) { for (auto *custom_type : schema.custom_types) { + if (!((custom_type->is_query_ && mode != Mode::Client) || (custom_type->is_result_ && mode != Mode::Server))) { + continue; + } for (auto *constructor : custom_type->constructors) { gen_from_json_constructor(sb, constructor, is_header); } } + if (mode == Mode::Client) { + return; + } for (auto *function : schema.functions) { gen_from_json_constructor(sb, function, is_header); } @@ -143,9 +157,12 @@ void gen_tl_constructor_from_string(StringBuilder &sb, Slice name, const Vec &ve sb << "}\n"; } -void gen_tl_constructor_from_string(StringBuilder &sb, const tl::simple::Schema &schema, bool is_header) { +void gen_tl_constructor_from_string(StringBuilder &sb, const tl::simple::Schema &schema, bool is_header, Mode mode) { Vec vec_for_nullary; for (auto *custom_type : schema.custom_types) { + if (!((custom_type->is_query_ && mode != Mode::Client) || (custom_type->is_result_ && mode != Mode::Server))) { + continue; + } Vec vec; for (auto *constructor : custom_type->constructors) { vec.push_back(std::make_pair(constructor->id, constructor->name)); @@ -158,6 +175,9 @@ void gen_tl_constructor_from_string(StringBuilder &sb, const tl::simple::Schema } gen_tl_constructor_from_string(sb, "Object", vec_for_nullary, is_header); + if (mode == Mode::Client) { + return; + } Vec vec_for_function; for (auto *function : schema.functions) { vec_for_function.push_back(std::make_pair(function->id, function->name)); @@ -165,7 +185,8 @@ void gen_tl_constructor_from_string(StringBuilder &sb, const tl::simple::Schema gen_tl_constructor_from_string(sb, "Function", vec_for_function, is_header); } -void gen_json_converter_file(const tl::simple::Schema &schema, const std::string &file_name_base, bool is_header) { +void gen_json_converter_file(const tl::simple::Schema &schema, const std::string &file_name_base, bool is_header, + Mode mode) { auto file_name = is_header ? file_name_base + ".h" : file_name_base + ".cpp"; file_name = "auto/" + file_name; auto old_file_content = [&] { @@ -202,9 +223,9 @@ void gen_json_converter_file(const tl::simple::Schema &schema, const std::string } sb << "namespace td {\n"; sb << "namespace td_api{\n"; - gen_tl_constructor_from_string(sb, schema, is_header); - gen_from_json(sb, schema, is_header); - gen_to_json(sb, schema, is_header); + gen_tl_constructor_from_string(sb, schema, is_header, mode); + gen_from_json(sb, schema, is_header, mode); + gen_to_json(sb, schema, is_header, mode); sb << "} // namespace td_api\n"; sb << "} // namespace td\n"; @@ -226,10 +247,10 @@ void gen_json_converter_file(const tl::simple::Schema &schema, const std::string } } -void gen_json_converter(const tl::tl_config &config, const std::string &file_name) { +void gen_json_converter(const tl::tl_config &config, const std::string &file_name, Mode mode) { tl::simple::Schema schema(config); - gen_json_converter_file(schema, file_name, true); - gen_json_converter_file(schema, file_name, false); + gen_json_converter_file(schema, file_name, true, mode); + gen_json_converter_file(schema, file_name, false, mode); } } // namespace td diff --git a/td/generate/tl_json_converter.h b/td/generate/tl_json_converter.h index d37de7ff..ded58af4 100644 --- a/td/generate/tl_json_converter.h +++ b/td/generate/tl_json_converter.h @@ -7,11 +7,12 @@ #pragma once #include "td/tl/tl_config.h" +#include "td/tl/tl_writer.h" #include namespace td { -void gen_json_converter(const tl::tl_config &config, const std::string &file_name); +void gen_json_converter(const tl::tl_config &config, const std::string &file_name, tl::TL_writer::Mode mode); } // namespace td diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index f7cf2aa3..ec22f572 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -589,13 +589,13 @@ class CliClient final : public Actor { auto as_json_str = json_encode(ToJson(result)); // LOG(INFO) << "Receive result [" << generation << "][id=" << id << "] " << as_json_str; - auto copy_as_json_str = as_json_str; - auto as_json_value = json_decode(copy_as_json_str).move_as_ok(); - td_api::object_ptr object; - from_json(object, as_json_value).ensure(); - CHECK(object != nullptr); - auto as_json_str2 = json_encode(ToJson(object)); - LOG_CHECK(as_json_str == as_json_str2) << "\n" << tag("a", as_json_str) << "\n" << tag("b", as_json_str2); + //auto copy_as_json_str = as_json_str; + //auto as_json_value = json_decode(copy_as_json_str).move_as_ok(); + //td_api::object_ptr object; + //from_json(object, as_json_value).ensure(); + //CHECK(object != nullptr); + //auto as_json_str2 = json_encode(ToJson(object)); + //LOG_CHECK(as_json_str == as_json_str2) << "\n" << tag("a", as_json_str) << "\n" << tag("b", as_json_str2); // LOG(INFO) << "Receive result [" << generation << "][id=" << id << "] " << as_json_str; if (generation != generation_) { diff --git a/td/tl/tl_json.h b/td/tl/tl_json.h index 6eecde75..a740f18b 100644 --- a/td/tl/tl_json.h +++ b/td/tl/tl_json.h @@ -39,11 +39,22 @@ inline void to_json(JsonValueScope &jv, const JsonVectorInt64 &vec) { } } +template +auto lazy_to_json(JsonValueScope &jv, const T &t) -> decltype(td_api::to_json(jv, t)) { + return td_api::to_json(jv, t); +} + +template +void lazy_to_json(std::reference_wrapper, const T &t) { + UNREACHABLE(); +} + inline void to_json(JsonValueScope &jv, const td_api::Object &object) { - td_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); + td_api::downcast_call(const_cast(object), [&jv](const auto &object) { lazy_to_json(jv, object); }); } inline void to_json(JsonValueScope &jv, const td_api::Function &object) { - td_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); + td_api::downcast_call(const_cast(object), + [&jv](const auto &object) { lazy_to_json(jv, object); }); } template diff --git a/tdtl/td/tl/tl_simple.h b/tdtl/td/tl/tl_simple.h index 2b51fda9..ea53a062 100644 --- a/tdtl/td/tl/tl_simple.h +++ b/tdtl/td/tl/tl_simple.h @@ -16,6 +16,8 @@ #include #include +#include + namespace td { namespace tl { namespace simple { @@ -63,6 +65,9 @@ struct Constructor { struct CustomType { std::string name; std::vector constructors; + + mutable bool is_result_{false}; + mutable bool is_query_{false}; }; struct Function { @@ -91,6 +96,23 @@ class Schema { auto *from_function = config.get_function_by_num(function_num); functions.push_back(get_function(from_function)); } + for (auto &function : functions_) { + mark_result(function->type); + for (auto &arg : function->args) { + mark_query(arg.type); + } + } + + //for (auto custom_type : custom_types) { + //std::cerr << custom_type->name; + //if (custom_type->is_result_) { + //std::cerr << " result"; + //} + //if (custom_type->is_query_) { + //std::cerr << " query"; + //} + //std::cerr << std::endl; + //} } std::vector custom_types; @@ -107,6 +129,32 @@ class Schema { std::map constructor_by_id; std::map function_by_id; + void mark_result(const Type *type) { + do_mark(type, true); + } + void mark_query(const Type *type) { + do_mark(type, false); + } + void do_mark(const Type *type, bool is_result) { + if (type->type == Type::Vector) { + return do_mark(type->vector_value_type, is_result); + } + if (type->type != Type::Custom) { + return; + } + auto *custom = type->custom; + auto &was = is_result ? custom->is_result_ : custom->is_query_; + if (was) { + return; + } + was = true; + for (auto constructor : custom->constructors) { + for (auto &arg : constructor->args) { + do_mark(arg.type, is_result); + } + } + } + const Type *get_type(const tl_type *from_type) { auto &type = type_by_id[from_type->id]; if (!type) {