tl json: support tl::TL_writer::Mode

GitOrigin-RevId: db6769e80f43f5fa2eedac5414cd2a44f8dcaf3c
This commit is contained in:
Arseny Smirnov 2019-07-01 10:43:31 +02:00
parent d22a6751db
commit 620e4221f3
6 changed files with 103 additions and 21 deletions

View File

@ -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);
}

View File

@ -19,6 +19,8 @@
namespace td {
using Mode = tl::TL_writer::Mode;
template <class T>
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

View File

@ -7,11 +7,12 @@
#pragma once
#include "td/tl/tl_config.h"
#include "td/tl/tl_writer.h"
#include <string>
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

View File

@ -589,13 +589,13 @@ class CliClient final : public Actor {
auto as_json_str = json_encode<std::string>(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<td_api::Object> object;
from_json(object, as_json_value).ensure();
CHECK(object != nullptr);
auto as_json_str2 = json_encode<std::string>(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<td_api::Object> object;
//from_json(object, as_json_value).ensure();
//CHECK(object != nullptr);
//auto as_json_str2 = json_encode<std::string>(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_) {

View File

@ -39,11 +39,22 @@ inline void to_json(JsonValueScope &jv, const JsonVectorInt64 &vec) {
}
}
template <class T>
auto lazy_to_json(JsonValueScope &jv, const T &t) -> decltype(td_api::to_json(jv, t)) {
return td_api::to_json(jv, t);
}
template <class T>
void lazy_to_json(std::reference_wrapper<JsonValueScope>, const T &t) {
UNREACHABLE();
}
inline void to_json(JsonValueScope &jv, const td_api::Object &object) {
td_api::downcast_call(const_cast<td_api::Object &>(object), [&jv](const auto &object) { to_json(jv, object); });
td_api::downcast_call(const_cast<td_api::Object &>(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<td_api::Function &>(object), [&jv](const auto &object) { to_json(jv, object); });
td_api::downcast_call(const_cast<td_api::Function &>(object),
[&jv](const auto &object) { lazy_to_json(jv, object); });
}
template <class T>

View File

@ -16,6 +16,8 @@
#include <string>
#include <vector>
#include <iostream>
namespace td {
namespace tl {
namespace simple {
@ -63,6 +65,9 @@ struct Constructor {
struct CustomType {
std::string name;
std::vector<const Constructor *> 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<const CustomType *> custom_types;
@ -107,6 +129,32 @@ class Schema {
std::map<std::int32_t, Constructor *> constructor_by_id;
std::map<std::int32_t, Function *> 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) {