Use TL code generator from lib_tl.

This commit is contained in:
John Preston 2019-09-26 17:26:36 +03:00
parent 7bb23519f9
commit bc2a0fb505
7 changed files with 154 additions and 1733 deletions

3
.gitmodules vendored
View File

@ -43,3 +43,6 @@
[submodule "Telegram/lib_lottie"]
path = Telegram/lib_lottie
url = https://github.com/desktop-app/lib_lottie.git
[submodule "Telegram/lib_tl"]
path = Telegram/lib_tl
url = https://github.com/desktop-app/lib_tl.git

View File

@ -1,6 +1,14 @@
// Core types (no need to gen)
//vector#1cb5c415 {t:Type} # [ t ] = Vector t;
int ? = Int;
long ? = Long;
double ? = Double;
string ? = String;
vector {t:Type} # [ t ] = Vector t;
int128 4*[ int ] = Int128;
int256 8*[ int ] = Int256;
///////////////////////////////
/// Authorization key creation

File diff suppressed because it is too large Load Diff

View File

@ -7,16 +7,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include <gsl/gsl>
#include <QtCore/QVector>
#include <QtCore/QString>
#include <QtCore/QByteArray>
#include "base/basic_types.h"
#include "base/match_method.h"
#include "base/flags.h"
#include "base/bytes.h"
#include "base/algorithm.h"
#include "base/assertion.h"
#include "tl/tl_basic_types.h"
#include <QtCore/QVector>
#include <QtCore/QString>
#include <QtCore/QByteArray>
#include <gsl/gsl>
using mtpPrime = int32;
using mtpRequestId = int32;
@ -58,108 +60,17 @@ constexpr int GetDcIdShift(ShiftedDcId shiftedDcId) {
} // namespace MTP
namespace MTP {
namespace internal {
class TypeData {
public:
TypeData() = default;
TypeData(const TypeData &other) = delete;
TypeData(TypeData &&other) = delete;
TypeData &operator=(const TypeData &other) = delete;
TypeData &operator=(TypeData &&other) = delete;
virtual ~TypeData() {
}
private:
void incrementCounter() const {
_counter.ref();
}
bool decrementCounter() const {
return _counter.deref();
}
friend class TypeDataOwner;
mutable QAtomicInt _counter = { 1 };
};
class TypeDataOwner {
public:
TypeDataOwner(TypeDataOwner &&other) : _data(base::take(other._data)) {
}
TypeDataOwner(const TypeDataOwner &other) : _data(other._data) {
incrementCounter();
}
TypeDataOwner &operator=(TypeDataOwner &&other) {
if (other._data != _data) {
decrementCounter();
_data = base::take(other._data);
}
return *this;
}
TypeDataOwner &operator=(const TypeDataOwner &other) {
if (other._data != _data) {
setData(other._data);
incrementCounter();
}
return *this;
}
~TypeDataOwner() {
decrementCounter();
}
protected:
TypeDataOwner() = default;
TypeDataOwner(const TypeData *data) : _data(data) {
}
void setData(const TypeData *data) {
decrementCounter();
_data = data;
}
// Unsafe cast, type should be checked by the caller.
template <typename DataType>
const DataType &queryData() const {
Expects(_data != nullptr);
return static_cast<const DataType &>(*_data);
}
private:
void incrementCounter() {
if (_data) {
_data->incrementCounter();
}
}
void decrementCounter() {
if (_data && !_data->decrementCounter()) {
delete base::take(_data);
}
}
const TypeData * _data = nullptr;
};
struct ZeroFlagsHelper {
};
} // namespace internal
} // namespace MTP
enum {
// core types
mtpc_int = 0xa8509bda,
mtpc_long = 0x22076cba,
mtpc_int128 = 0x4bb5362b,
mtpc_int256 = 0x929c32f,
mtpc_double = 0x2210c154,
mtpc_string = 0xb5286e24,
mtpc_vector = 0x1cb5c415,
mtpc_int = tl::id_int,
mtpc_long = tl::id_long,
mtpc_int128 = tl::id_int128,
mtpc_int256 = tl::id_int256,
mtpc_double = tl::id_double,
mtpc_string = tl::id_string,
mtpc_vector = tl::id_vector,
mtpc_bytes = tl::id_bytes,
mtpc_flags = tl::id_flags,
// layers
mtpc_invokeWithLayer1 = 0x53835315,
@ -187,8 +98,6 @@ enum {
// mtpc_msg_copy = 0xe06046b2,
mtpc_gzip_packed = 0x3072cfa1
};
static const mtpTypeId mtpc_bytes = mtpc_string;
static const mtpTypeId mtpc_flags = mtpc_int;
static const mtpTypeId mtpc_core_message = -1; // undefined type, but is used
static const mtpTypeId mtpLayers[] = {
mtpTypeId(mtpc_invokeWithLayer1),
@ -212,43 +121,6 @@ static const mtpTypeId mtpLayers[] = {
};
static const uint32 mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]);
template <typename bareT>
class MTPBoxed : public bareT {
public:
using bareT::bareT;
MTPBoxed() = default;
MTPBoxed(const MTPBoxed<bareT> &v) = default;
MTPBoxed<bareT> &operator=(const MTPBoxed<bareT> &v) = default;
MTPBoxed(const bareT &v) : bareT(v) {
}
MTPBoxed<bareT> &operator=(const bareT &v) {
*((bareT*)this) = v;
return *this;
}
uint32 innerLength() const {
return sizeof(mtpTypeId) + bareT::innerLength();
}
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) {
if (from + 1 > end) {
return false;
}
cons = (mtpTypeId)*(from++);
return bareT::read(from, end, cons);
}
void write(mtpBuffer &to) const {
to.push_back(bareT::type());
bareT::write(to);
}
using Unboxed = bareT;
};
template <typename T>
class MTPBoxed<MTPBoxed<T> > {
typename T::CantMakeBoxedBoxedType v;
};
namespace MTP {
namespace details {
@ -257,17 +129,6 @@ struct SecureRequestCreateTag {
} // namespace details
template <typename T>
struct is_boxed : std::false_type {
};
template <typename T>
struct is_boxed<MTPBoxed<T>> : std::true_type {
};
template <typename T>
constexpr bool is_boxed_v = is_boxed<T>::value;
class SecureRequestData;
class SecureRequest {
public:
@ -290,7 +151,7 @@ public:
template <
typename Request,
typename = std::enable_if_t<is_boxed_v<Request>>>
typename = std::enable_if_t<tl::is_boxed_v<Request>>>
static SecureRequest Serialize(const Request &request);
// For template MTP requests and MTPBoxed instanciation.
@ -341,511 +202,122 @@ SecureRequest SecureRequest::Serialize(const Request &request) {
return serialized;
}
template <typename Type>
struct RepeatHelper {
using type = Type;
};
template <typename Type>
using Repeat = typename RepeatHelper<Type>::type;
struct InnerHelper {
static void Check(...);
template <typename Type, typename Result = decltype(std::declval<Type>().v)>
static Result Check(const Type&);
template <typename Type>
using type = std::decay_t<decltype(Check(std::declval<Type>()))>;
};
template <typename Type>
class conditional {
public:
conditional() = default;
conditional(const Type *value) : _value(value) {
}
operator const Type*() const {
return _value;
}
const Type *operator->() const {
Expects(_value != nullptr);
return _value;
}
const Type &operator*() const {
Expects(_value != nullptr);
return *_value;
}
template <
typename Inner = InnerHelper::type<Type>,
typename = std::enable_if_t<!std::is_same_v<Inner, void>>>
Inner value_or(Repeat<Inner> fallback) const {
return _value ? _value->v : fallback;
}
template <
typename Inner = InnerHelper::type<Type>,
typename = std::enable_if_t<!std::is_same_v<Inner, void>>>
Inner value_or_empty() const {
return _value ? _value->v : Inner();
}
private:
const Type *_value = nullptr;
};
} // namespace MTP
class MTPint {
public:
int32 v = 0;
using MTPint = tl::int_type;
MTPint() = default;
uint32 innerLength() const {
return sizeof(int32);
}
mtpTypeId type() const {
return mtpc_int;
}
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_int) {
if (from + 1 > end || cons != mtpc_int) {
return false;
}
v = (int32)*(from++);
return true;
}
void write(mtpBuffer &to) const {
to.push_back((mtpPrime)v);
}
private:
explicit MTPint(int32 val) : v(val) {
}
friend MTPint MTP_int(int32 v);
};
inline MTPint MTP_int(int32 v) {
return MTPint(v);
return tl::make_int(v);
}
using MTPInt = MTPBoxed<MTPint>;
template <typename Flags>
class MTPflags {
public:
Flags v = 0;
static_assert(
sizeof(Flags) == sizeof(int32),
"MTPflags are allowed only wrapping int32 flag types!");
MTPflags() = default;
MTPflags(MTP::internal::ZeroFlagsHelper helper) {
}
uint32 innerLength() const {
return sizeof(Flags);
}
mtpTypeId type() const {
return mtpc_flags;
}
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_flags) {
if (from + 1 > end || cons != mtpc_flags) {
return false;
}
v = Flags::from_raw(static_cast<typename Flags::Type>(*(from++)));
return true;
}
void write(mtpBuffer &to) const {
to.push_back(static_cast<mtpPrime>(v.value()));
}
private:
explicit MTPflags(Flags val) : v(val) {
}
template <typename T>
friend MTPflags<base::flags<T>> MTP_flags(base::flags<T> v);
template <typename T, typename>
friend MTPflags<base::flags<T>> MTP_flags(T v);
};
using MTPflags = tl::flags_type<Flags>;
template <typename T>
inline MTPflags<base::flags<T>> MTP_flags(base::flags<T> v) {
return MTPflags<base::flags<T>>(v);
return tl::make_flags(v);
}
template <typename T, typename = std::enable_if_t<!std::is_same<T, int>::value>>
inline MTPflags<base::flags<T>> MTP_flags(T v) {
return MTPflags<base::flags<T>>(v);
return tl::make_flags(v);
}
inline MTP::internal::ZeroFlagsHelper MTP_flags(void(MTP::internal::ZeroFlagsHelper::*)()) {
return MTP::internal::ZeroFlagsHelper();
inline tl::details::zero_flags_helper MTP_flags(void(tl::details::zero_flags_helper::*)()) {
return tl::details::zero_flags_helper();
}
template <typename Flags>
using MTPFlags = MTPBoxed<MTPflags<Flags>>;
using MTPlong = tl::long_type;
inline bool operator==(const MTPint &a, const MTPint &b) {
return a.v == b.v;
}
inline bool operator!=(const MTPint &a, const MTPint &b) {
return a.v != b.v;
}
class MTPlong {
public:
uint64 v = 0;
MTPlong() = default;
uint32 innerLength() const {
return sizeof(uint64);
}
mtpTypeId type() const {
return mtpc_long;
}
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_long) {
if (from + 2 > end || cons != mtpc_long) {
return false;
}
v = (uint64)(((uint32*)from)[0]) | ((uint64)(((uint32*)from)[1]) << 32);
from += 2;
return true;
}
void write(mtpBuffer &to) const {
to.push_back((mtpPrime)(v & 0xFFFFFFFFL));
to.push_back((mtpPrime)(v >> 32));
}
private:
explicit MTPlong(uint64 val) : v(val) {
}
friend MTPlong MTP_long(uint64 v);
};
inline MTPlong MTP_long(uint64 v) {
return MTPlong(v);
}
using MTPLong = MTPBoxed<MTPlong>;
inline bool operator==(const MTPlong &a, const MTPlong &b) {
return a.v == b.v;
}
inline bool operator!=(const MTPlong &a, const MTPlong &b) {
return a.v != b.v;
return tl::make_long(v);
}
class MTPint128 {
public:
uint64 l = 0;
uint64 h = 0;
using MTPint128 = tl::int128_type;
MTPint128() = default;
uint32 innerLength() const {
return sizeof(uint64) + sizeof(uint64);
}
mtpTypeId type() const {
return mtpc_int128;
}
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_int128) {
if (from + 4 > end || cons != mtpc_int128) {
return false;
}
l = (uint64)(((uint32*)from)[0]) | ((uint64)(((uint32*)from)[1]) << 32);
h = (uint64)(((uint32*)from)[2]) | ((uint64)(((uint32*)from)[3]) << 32);
from += 4;
return true;
}
void write(mtpBuffer &to) const {
to.push_back((mtpPrime)(l & 0xFFFFFFFFL));
to.push_back((mtpPrime)(l >> 32));
to.push_back((mtpPrime)(h & 0xFFFFFFFFL));
to.push_back((mtpPrime)(h >> 32));
}
private:
explicit MTPint128(uint64 low, uint64 high) : l(low), h(high) {
}
friend MTPint128 MTP_int128(uint64 l, uint64 h);
};
inline MTPint128 MTP_int128(uint64 l, uint64 h) {
return MTPint128(l, h);
}
using MTPInt128 = MTPBoxed<MTPint128>;
inline bool operator==(const MTPint128 &a, const MTPint128 &b) {
return a.l == b.l && a.h == b.h;
}
inline bool operator!=(const MTPint128 &a, const MTPint128 &b) {
return a.l != b.l || a.h != b.h;
return tl::make_int128(l, h);
}
class MTPint256 {
public:
MTPint128 l;
MTPint128 h;
using MTPint256 = tl::int256_type;
MTPint256() = default;
uint32 innerLength() const {
return l.innerLength() + h.innerLength();
}
mtpTypeId type() const {
return mtpc_int256;
}
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_int256) {
if (cons != mtpc_int256) {
return false;
}
return l.read(from, end)
&& h.read(from, end);
}
void write(mtpBuffer &to) const {
l.write(to);
h.write(to);
}
private:
explicit MTPint256(MTPint128 low, MTPint128 high) : l(low), h(high) {
}
friend MTPint256 MTP_int256(const MTPint128 &l, const MTPint128 &h);
};
inline MTPint256 MTP_int256(const MTPint128 &l, const MTPint128 &h) {
return MTPint256(l, h);
}
using MTPInt256 = MTPBoxed<MTPint256>;
inline bool operator==(const MTPint256 &a, const MTPint256 &b) {
return a.l == b.l && a.h == b.h;
}
inline bool operator!=(const MTPint256 &a, const MTPint256 &b) {
return a.l != b.l || a.h != b.h;
return tl::make_int256(l, h);
}
class MTPdouble {
public:
float64 v = 0.;
using MTPdouble = tl::double_type;
MTPdouble() = default;
uint32 innerLength() const {
return sizeof(float64);
}
mtpTypeId type() const {
return mtpc_double;
}
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_double) {
if (from + 2 > end || cons != mtpc_double) {
return false;
}
auto nv = (uint64)(((uint32*)from)[0]) | ((uint64)(((uint32*)from)[1]) << 32);
std::memcpy(&v, &nv, sizeof(v));
from += 2;
return true;
}
void write(mtpBuffer &to) const {
uint64 iv;
std::memcpy(&iv, &v, sizeof(v));
to.push_back((mtpPrime)(iv & 0xFFFFFFFFL));
to.push_back((mtpPrime)(iv >> 32));
}
private:
explicit MTPdouble(float64 val) : v(val) {
}
friend MTPdouble MTP_double(float64 v);
};
inline MTPdouble MTP_double(float64 v) {
return MTPdouble(v);
}
using MTPDouble = MTPBoxed<MTPdouble>;
inline bool operator==(const MTPdouble &a, const MTPdouble &b) {
return a.v == b.v;
}
inline bool operator!=(const MTPdouble &a, const MTPdouble &b) {
return a.v != b.v;
return tl::make_double(v);
}
class MTPstring;
using MTPbytes = MTPstring;
class MTPstring {
public:
MTPstring() = default;
uint32 innerLength() const;
mtpTypeId type() const {
return mtpc_string;
}
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_string);
void write(mtpBuffer &to) const;
QByteArray v;
private:
explicit MTPstring(QByteArray &&data) : v(std::move(data)) {
}
friend MTPstring MTP_string(const std::string &v);
friend MTPstring MTP_string(const QString &v);
friend MTPstring MTP_string(const char *v);
friend MTPstring MTP_string();
friend MTPbytes MTP_bytes(const QByteArray &v);
friend MTPbytes MTP_bytes(QByteArray &&v);
friend MTPbytes MTP_bytes();
};
using MTPString = MTPBoxed<MTPstring>;
using MTPBytes = MTPBoxed<MTPbytes>;
using MTPstring = tl::string_type;
using MTPbytes = tl::bytes_type;
inline MTPstring MTP_string(const std::string &v) {
return MTPstring(QByteArray(v.data(), v.size()));
return tl::make_string(v);
}
inline MTPstring MTP_string(const QString &v) {
return MTPstring(v.toUtf8());
return tl::make_string(v);
}
inline MTPstring MTP_string(const char *v) {
return MTPstring(QByteArray(v, strlen(v)));
return tl::make_string(v);
}
inline MTPstring MTP_string() {
return MTPstring(QByteArray());
return tl::make_string();
}
MTPstring MTP_string(const QByteArray &v) = delete;
inline MTPbytes MTP_bytes(const QByteArray &v) {
return MTPbytes(QByteArray(v));
return tl::make_bytes(v);
}
inline MTPbytes MTP_bytes(QByteArray &&v) {
return MTPbytes(std::move(v));
return tl::make_bytes(std::move(v));
}
inline MTPbytes MTP_bytes() {
return MTPbytes(QByteArray());
return tl::make_bytes();
}
inline MTPbytes MTP_bytes(bytes::const_span buffer) {
return MTP_bytes(QByteArray(
reinterpret_cast<const char*>(buffer.data()),
buffer.size()));
return tl::make_bytes(buffer);
}
inline MTPbytes MTP_bytes(const bytes::vector &buffer) {
return MTP_bytes(bytes::make_span(buffer));
}
inline bool operator==(const MTPstring &a, const MTPstring &b) {
return a.v == b.v;
}
inline bool operator!=(const MTPstring &a, const MTPstring &b) {
return a.v != b.v;
return tl::make_bytes(buffer);
}
inline QString qs(const MTPstring &v) {
return QString::fromUtf8(v.v);
return tl::utf16(v);
}
inline QString qs(const QByteArray &v) {
return QString::fromUtf8(v);
return tl::utf16(v);
}
inline QByteArray qba(const MTPstring &v) {
return v.v;
return tl::utf8(v);
}
template <typename T>
class MTPvector {
public:
MTPvector() = default;
using MTPvector = tl::vector_type<T>;
uint32 innerLength() const {
auto result = uint32(sizeof(uint32));
for (const auto &item : v) {
result += item.innerLength();
}
return result;
}
mtpTypeId type() const {
return mtpc_vector;
}
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_vector) {
if (from + 1 > end || cons != mtpc_vector) {
return false;
}
auto count = static_cast<uint32>(*(from++));
auto vector = QVector<T>(count, T());
for (auto &item : vector) {
if (!item.read(from, end)) {
return false;
}
}
v = std::move(vector);
return true;
}
void write(mtpBuffer &to) const {
to.push_back(v.size());
for (const auto &item : v) {
item.write(to);
}
}
QVector<T> v;
private:
explicit MTPvector(QVector<T> &&data) : v(std::move(data)) {
}
template <typename U>
friend MTPvector<U> MTP_vector(uint32 count);
template <typename U>
friend MTPvector<U> MTP_vector(uint32 count, const U &value);
template <typename U>
friend MTPvector<U> MTP_vector(const QVector<U> &v);
template <typename U>
friend MTPvector<U> MTP_vector(QVector<U> &&v);
template <typename U>
friend MTPvector<U> MTP_vector();
};
template <typename T>
inline MTPvector<T> MTP_vector(uint32 count) {
return MTPvector<T>(QVector<T>(count));
return tl::make_vector<T>(count);
}
template <typename T>
inline MTPvector<T> MTP_vector(uint32 count, const T &value) {
return MTPvector<T>(QVector<T>(count, value));
return tl::make_vector<T>(count, value);
}
template <typename T>
inline MTPvector<T> MTP_vector(const QVector<T> &v) {
return MTPvector<T>(QVector<T>(v));
return tl::make_vector<T>(v);
}
template <typename T>
inline MTPvector<T> MTP_vector(QVector<T> &&v) {
return MTPvector<T>(std::move(v));
return tl::make_vector<T>(std::move(v));
}
template <typename T>
inline MTPvector<T> MTP_vector() {
return MTPvector<T>();
}
template <typename T>
using MTPVector = MTPBoxed<MTPvector<T>>;
template <typename T>
inline bool operator==(const MTPvector<T> &a, const MTPvector<T> &b) {
return a.c_vector().v == b.c_vector().v;
}
template <typename T>
inline bool operator!=(const MTPvector<T> &a, const MTPvector<T> &b) {
return a.c_vector().v != b.c_vector().v;
return tl::make_vector<T>();
}
// Human-readable text serialization

View File

@ -156,6 +156,7 @@ auto GenerateCodes() {
Ui::show(Box<InformBox>("All sound overrides were reset."));
}
});
return codes;
}

View File

@ -31,9 +31,11 @@
}]],
'dependencies': [
'<(submodules_loc)/lib_base/lib_base.gyp:lib_base',
'<(submodules_loc)/lib_tl/lib_tl.gyp:lib_tl',
],
'export_dependent_settings': [
'<(submodules_loc)/lib_base/lib_base.gyp:lib_base',
'<(submodules_loc)/lib_tl/lib_tl.gyp:lib_tl',
],
'include_dirs': [
'<(src_loc)',
@ -49,6 +51,7 @@
'action_name': 'codegen_scheme',
'inputs': [
'<(src_loc)/codegen/scheme/codegen_scheme.py',
'<(submodules_loc)/lib_tl/tl/generate_tl.py',
'<(res_loc)/tl/mtproto.tl',
'<(res_loc)/tl/api.tl',
],
@ -58,7 +61,7 @@
],
'action': [
'python', '<(src_loc)/codegen/scheme/codegen_scheme.py',
'-o', '<(SHARED_INTERMEDIATE_DIR)',
'-o', '<(SHARED_INTERMEDIATE_DIR)/scheme',
'<(res_loc)/tl/mtproto.tl',
'<(res_loc)/tl/api.tl',
],

1
Telegram/lib_tl Submodule

@ -0,0 +1 @@
Subproject commit ab4e30d38914142d6abbb64389a00cd6f8ef55d2