From bc2a0fb505447c0eefe3d74efd9ccc21876781f0 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 26 Sep 2019 17:26:36 +0300 Subject: [PATCH] Use TL code generator from lib_tl. --- .gitmodules | 3 + Telegram/Resources/tl/mtproto.tl | 10 +- .../codegen/scheme/codegen_scheme.py | 1237 ++--------------- Telegram/SourceFiles/mtproto/core_types.h | 630 +-------- .../SourceFiles/settings/settings_codes.cpp | 1 + Telegram/gyp/lib_scheme.gyp | 5 +- Telegram/lib_tl | 1 + 7 files changed, 154 insertions(+), 1733 deletions(-) create mode 160000 Telegram/lib_tl diff --git a/.gitmodules b/.gitmodules index 2e49012beb..2876230de0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/Telegram/Resources/tl/mtproto.tl b/Telegram/Resources/tl/mtproto.tl index 1b26ca9a2d..83a7702926 100644 --- a/Telegram/Resources/tl/mtproto.tl +++ b/Telegram/Resources/tl/mtproto.tl @@ -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 diff --git a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py index 4159cdbafa..08e5469794 100644 --- a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py +++ b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py @@ -7,1155 +7,88 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL ''' import glob, re, binascii, os, sys -input_files = [] -output_path = '' -next_output_path = False -for arg in sys.argv[1:]: - if next_output_path: - next_output_path = False - output_path = arg - elif arg == '-o': - next_output_path = True - elif re.match(r'^-o(.+)', arg): - output_path = arg[2:] - else: - input_files.append(arg) - -if len(input_files) == 0: - print('Input file required.') - sys.exit(1) -if output_path == '': - print('Output path required.') - sys.exit(1) - -output_header = output_path + '/scheme.h' -output_source = output_path + '/scheme.cpp' - -# define some checked flag conversions -# the key flag type should be a subset of the value flag type -# with exact the same names, then the key flag can be implicitly -# casted to the value flag type -parentFlags = {}; -parentFlagsList = []; -def addChildParentFlags(child, parent): - parentFlagsList.append(child); - parentFlags[child] = parent; -addChildParentFlags('MTPDmessageService', 'MTPDmessage'); -addChildParentFlags('MTPDupdateShortMessage', 'MTPDmessage'); -addChildParentFlags('MTPDupdateShortChatMessage', 'MTPDmessage'); -addChildParentFlags('MTPDupdateShortSentMessage', 'MTPDmessage'); -addChildParentFlags('MTPDreplyKeyboardHide', 'MTPDreplyKeyboardMarkup'); -addChildParentFlags('MTPDreplyKeyboardForceReply', 'MTPDreplyKeyboardMarkup'); -addChildParentFlags('MTPDinputPeerNotifySettings', 'MTPDpeerNotifySettings'); -addChildParentFlags('MTPDpeerNotifySettings', 'MTPDinputPeerNotifySettings'); -addChildParentFlags('MTPDchannelForbidden', 'MTPDchannel'); -addChildParentFlags('MTPDdialogFolder', 'MTPDdialog'); - -# this is a map (key flags -> map (flag name -> flag bit)) -# each key flag of parentFlags should be a subset of the value flag here -parentFlagsCheck = {}; - -countedTypeIdExceptions = {}; -countedTypeIdExceptions['channel#c88974ac'] = True -countedTypeIdExceptions['ipPortSecret#37982646'] = True -countedTypeIdExceptions['accessPointRule#4679b65f'] = True -countedTypeIdExceptions['help.configSimple#5a592a6c'] = True - -renamedTypes = {}; -renamedTypes['passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow'] = 'passwordKdfAlgoModPow'; - -lines = []; -layer = ''; -layerIndex = 0; -funcs = 0 -types = 0; -consts = 0 -funcsNow = 0 -enums = []; -funcsDict = {}; -funcsList = []; -typesDict = {}; -TypesDict = {}; -typesList = []; -boxed = {}; -funcsText = ''; -typesText = ''; -dataTexts = ''; -creatorProxyText = ''; -factories = ''; -flagOperators = ''; -methods = ''; -inlineMethods = ''; -visitorMethods = ''; -textSerializeInit = ''; -textSerializeMethods = ''; -forwards = ''; -forwTypedefs = ''; - -for input_file in input_files: - lines.append('---types---') - with open(input_file) as f: - for line in f: - layerline = re.match(r'// LAYER (\d+)', line) - if (layerline): - layerIndex = int(layerline.group(1)); - layer = 'inline constexpr mtpPrime CurrentLayer = mtpPrime(' + str(layerIndex) + ');'; - else: - lines.append(line); - -for line in lines: - nocomment = re.match(r'^(.*?)//', line) - if (nocomment): - line = nocomment.group(1); - if (re.match(r'\-\-\-functions\-\-\-', line)): - funcsNow = 1; - continue; - if (re.match(r'\-\-\-types\-\-\-', line)): - funcsNow = 0; - continue; - if (re.match(r'^\s*$', line)): - continue; - - nametype = re.match(r'([a-zA-Z\.0-9_]+)(#[0-9a-f]+)?([^=]*)=\s*([a-zA-Z\.<>0-9_]+);', line); - if (not nametype): - if (not re.match(r'vector#1cb5c415 \{t:Type\} # \[ t \] = Vector t;', line)): - print('Bad line found: ' + line); - sys.exit(1); - continue; - - originalname = nametype.group(1); - name = originalname; - if (name in renamedTypes): - name = renamedTypes[name]; - nameInd = name.find('.'); - if (nameInd >= 0): - Name = name[0:nameInd] + '_' + name[nameInd + 1:nameInd + 2].upper() + name[nameInd + 2:]; - name = name.replace('.', '_'); - else: - Name = name[0:1].upper() + name[1:]; - typeid = nametype.group(2); - if (typeid and len(typeid) > 0): - typeid = typeid[1:]; # Skip '#' - while (typeid and len(typeid) > 0 and typeid[0] == '0'): - typeid = typeid[1:]; - - cleanline = nametype.group(1) + nametype.group(3) + '= ' + nametype.group(4); - cleanline = re.sub(r' [a-zA-Z0-9_]+\:flags\.[0-9]+\?true', '', cleanline); - cleanline = cleanline.replace('<', ' ').replace('>', ' ').replace(' ', ' '); - cleanline = re.sub(r'^ ', '', cleanline); - cleanline = re.sub(r' $', '', cleanline); - cleanline = cleanline.replace(':bytes ', ':string '); - cleanline = cleanline.replace('?bytes ', '?string '); - cleanline = cleanline.replace('{', ''); - cleanline = cleanline.replace('}', ''); - countTypeId = binascii.crc32(binascii.a2b_qp(cleanline)); - if (countTypeId < 0): - countTypeId += 2 ** 32; - countTypeId = re.sub(r'^0x|L$', '', hex(countTypeId)); - if (typeid and len(typeid) > 0): - typeid = typeid; - if (typeid != countTypeId): - key = originalname + '#' + typeid; - if (not key in countedTypeIdExceptions): - print('Warning: counted ' + countTypeId + ' mismatch with provided ' + typeid + ' (' + key + ', ' + cleanline + ')'); - continue; - else: - typeid = countTypeId; - - typeid = '0x' + typeid; - - params = nametype.group(3); - restype = nametype.group(4); - if (restype.find('<') >= 0): - templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', restype); - if (templ): - vectemplate = templ.group(2); - if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+\.[A-Z]', vectemplate)): - restype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - elif (vectemplate == 'int' or vectemplate == 'long' or vectemplate == 'string' or vectemplate == 'bytes'): - restype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - else: - foundmeta = ''; - for metatype in typesDict: - for typedata in typesDict[metatype]: - if (typedata[0] == vectemplate): - foundmeta = metatype; - break; - if (len(foundmeta) > 0): - break; - if (len(foundmeta) > 0): - ptype = templ.group(1) + 'MTP' + foundmeta.replace('.', '_') + '>'; - else: - print('Bad vector param: ' + vectemplate); - sys.exit(1); - else: - print('Bad template type: ' + restype); - sys.exit(1); - resType = restype.replace('.', '_'); - if (restype.find('.') >= 0): - parts = re.match(r'([a-z]+)\.([A-Z][A-Za-z0-9<>\._]+)', restype) - if (parts): - restype = parts.group(1) + '_' + parts.group(2)[0:1].lower() + parts.group(2)[1:]; - else: - print('Bad result type name with dot: ' + restype); - sys.exit(1); - else: - if (re.match(r'^[A-Z]', restype)): - restype = restype[:1].lower() + restype[1:]; - else: - print('Bad result type name: ' + restype); - sys.exit(1); - - boxed[resType] = restype; - boxed[Name] = name; - - enums.append('\tmtpc_' + name + ' = ' + typeid); - - paramsList = params.strip().split(' '); - prms = {}; - conditions = {}; - trivialConditions = {}; # true type - prmsList = []; - conditionsList = []; - isTemplate = hasFlags = hasTemplate = ''; - for param in paramsList: - if (re.match(r'^\s*$', param)): - continue; - templ = re.match(r'^{([A-Za-z]+):Type}$', param); - if (templ): - hasTemplate = templ.group(1); - continue; - pnametype = re.match(r'([a-zA-Z_][a-zA-Z0-9_]*):([A-Za-z0-9<>\._]+|![a-zA-Z]+|\#|[a-z_][a-z0-9_]*\.[0-9]+\?[A-Za-z0-9<>\._]+)$', param); - if (not pnametype): - print('Bad param found: "' + param + '" in line: ' + line); - sys.exit(1); - pname = pnametype.group(1); - ptypewide = pnametype.group(2); - if (re.match(r'^!([a-zA-Z]+)$', ptypewide)): - if ('!' + hasTemplate == ptypewide): - isTemplate = pname; - ptype = 'TQueryType'; - else: - print('Bad template param name: "' + param + '" in line: ' + line); - sys.exit(1); - elif (ptypewide == '#'): - hasFlags = pname; - if funcsNow: - ptype = 'flags'; - else: - ptype = 'flags'; - else: - ptype = ptypewide; - if (ptype.find('?') >= 0): - pmasktype = re.match(r'([a-z_][a-z0-9_]*)\.([0-9]+)\?([A-Za-z0-9<>\._]+)', ptype); - if (not pmasktype or pmasktype.group(1) != hasFlags): - print('Bad param found: "' + param + '" in line: ' + line); - sys.exit(1); - ptype = pmasktype.group(3); - if (ptype.find('<') >= 0): - templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', ptype); - if (templ): - vectemplate = templ.group(2); - if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+\.[A-Z]', vectemplate)): - ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - elif (vectemplate == 'int' or vectemplate == 'long' or vectemplate == 'string' or vectemplate == 'bytes'): - ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - else: - foundmeta = ''; - for metatype in typesDict: - for typedata in typesDict[metatype]: - if (typedata[0] == vectemplate): - foundmeta = metatype; - break; - if (len(foundmeta) > 0): - break; - if (len(foundmeta) > 0): - ptype = templ.group(1) + 'MTP' + foundmeta.replace('.', '_') + '>'; - else: - print('Bad vector param: ' + vectemplate); - sys.exit(1); - else: - print('Bad template type: ' + ptype); - sys.exit(1); - if (not pname in conditions): - conditionsList.append(pname); - conditions[pname] = pmasktype.group(2); - if (ptype == 'true'): - trivialConditions[pname] = 1; - elif (ptype.find('<') >= 0): - templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', ptype); - if (templ): - vectemplate = templ.group(2); - if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+\.[A-Z]', vectemplate)): - ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - elif (vectemplate == 'int' or vectemplate == 'long' or vectemplate == 'string' or vectemplate == 'bytes'): - ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - else: - foundmeta = ''; - for metatype in typesDict: - for typedata in typesDict[metatype]: - if (typedata[0] == vectemplate): - foundmeta = metatype; - break; - if (len(foundmeta) > 0): - break; - if (len(foundmeta) > 0): - ptype = templ.group(1) + 'MTP' + foundmeta.replace('.', '_') + '>'; - else: - print('Bad vector param: ' + vectemplate); - sys.exit(1); - else: - print('Bad template type: ' + ptype); - sys.exit(1); - prmsList.append(pname); - prms[pname] = ptype.replace('.', '_'); - - if (isTemplate == '' and resType == 'X'): - print('Bad response type "X" in "' + name +'" in line: ' + line); - sys.exit(1); - - if funcsNow: - methodBodies = '' - if (isTemplate != ''): - funcsText += '\ntemplate '; - funcsText += '\nclass MTP' + name + ' { // RPC method \'' + nametype.group(1) + '\'\n'; # class - - funcsText += 'public:\n'; - - prmsStr = []; - prmsInit = []; - prmsNames = []; - if (hasFlags != ''): - funcsText += '\tenum class Flag : uint32 {\n'; - maxbit = 0; - parentFlagsCheck['MTP' + name] = {}; - for paramName in conditionsList: - funcsText += '\t\tf_' + paramName + ' = (1U << ' + conditions[paramName] + '),\n'; - parentFlagsCheck['MTP' + name][paramName] = conditions[paramName]; - maxbit = max(maxbit, int(conditions[paramName])); - if (maxbit > 0): - funcsText += '\n'; - funcsText += '\t\tMAX_FIELD = (1U << ' + str(maxbit) + '),\n'; - funcsText += '\t};\n'; - funcsText += '\tusing Flags = base::flags;\n'; - funcsText += '\tfriend inline constexpr bool is_flag_type(Flag) { return true; };\n'; - funcsText += '\n'; - - if (len(prms) > len(trivialConditions)): - for paramName in prmsList: - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - prmsInit.append('_' + paramName + '(' + paramName + '_)'); - prmsNames.append(paramName + '_'); - if (paramName == isTemplate): - ptypeFull = paramType; - else: - ptypeFull = 'MTP' + paramType; - if (paramType in ['int', 'Int', 'bool', 'Bool', 'flags']): - prmsStr.append(ptypeFull + ' ' + paramName + '_'); - else: - prmsStr.append('const ' + ptypeFull + ' &' + paramName + '_'); - - funcsText += '\tMTP' + name + '();\n';# = default; # constructor - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'MTP' + name + '::MTP' + name + '() = default;\n'; - else: - methodBodies += 'MTP' + name + '::MTP' + name + '() = default;\n'; - if (len(prms) > len(trivialConditions)): - funcsText += '\tMTP' + name + '(' + ', '.join(prmsStr) + ');\n'; - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'MTP' + name + '::MTP' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n}\n'; - else: - methodBodies += 'MTP' + name + '::MTP' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n}\n'; - - funcsText += '\n'; - funcsText += '\tuint32 innerLength() const;\n'; # count size - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'uint32 MTP' + name + '::innerLength() const {\n'; - else: - methodBodies += 'uint32 MTP' + name + '::innerLength() const {\n'; - size = []; - for k in prmsList: - v = prms[k]; - if (k in conditionsList): - if (not k in trivialConditions): - size.append('((_' + hasFlags + '.v & Flag::f_' + k + ') ? _' + k + '.innerLength() : 0)'); - else: - size.append('_' + k + '.innerLength()'); - if (not len(size)): - size.append('0'); - methodBodies += '\treturn ' + ' + '.join(size) + ';\n'; - methodBodies += '}\n'; - - funcsText += '\tmtpTypeId type() const {\n\t\treturn mtpc_' + name + ';\n\t}\n'; # type id - - funcsText += '\t[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_' + name + ');\n'; # read method - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'bool MTP' + name + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n'; - else: - methodBodies += 'bool MTP' + name + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n'; - readFunc = '' - for k in prmsList: - v = prms[k]; - if (k in conditionsList): - if (not k in trivialConditions): - readFunc += '\t\t&& ((_' + hasFlags + '.v & Flag::f_' + k + ') ? _' + k + '.read(from, end) : ((_' + k + ' = MTP' + v + '()), true))\n'; - else: - readFunc += '\t\t&& _' + k + '.read(from, end)\n'; - if readFunc != '': - methodBodies += '\treturn' + readFunc[4:len(readFunc)-1] + ';\n'; - else: - methodBodies += '\treturn true;\n'; - methodBodies += '}\n'; - - funcsText += '\tvoid write(mtpBuffer &to) const;\n'; # write method - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'void MTP' + name + '::write(mtpBuffer &to) const {\n'; - else: - methodBodies += 'void MTP' + name + '::write(mtpBuffer &to) const {\n'; - for k in prmsList: - v = prms[k]; - if (k in conditionsList): - if (not k in trivialConditions): - methodBodies += '\tif (_' + hasFlags + '.v & Flag::f_' + k + ') _' + k + '.write(to);\n'; - else: - methodBodies += '\t_' + k + '.write(to);\n'; - methodBodies += '}\n'; - - if (isTemplate != ''): - funcsText += '\n\tusing ResponseType = typename TQueryType::ResponseType;\n\n'; - inlineMethods += methodBodies; - else: - funcsText += '\n\tusing ResponseType = MTP' + resType + ';\n\n'; # method return type - methods += methodBodies; - - if (len(prms) > len(trivialConditions)): - funcsText += 'private:\n'; - for paramName in prmsList: - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - if (paramName == isTemplate): - ptypeFull = paramType; - else: - ptypeFull = 'MTP' + paramType; - funcsText += '\t' + ptypeFull + ' _' + paramName + ';\n'; - funcsText += '\n'; - - funcsText += '};\n'; # class ending - if (isTemplate != ''): - funcsText += 'template \n'; - funcsText += 'using MTP' + Name + ' = MTPBoxed>;\n'; - else: - funcsText += 'using MTP' + Name + ' = MTPBoxed;\n'; - funcs = funcs + 1; - - if (not restype in funcsDict): - funcsList.append(restype); - funcsDict[restype] = []; -# TypesDict[restype] = resType; - funcsDict[restype].append([name, typeid, prmsList, prms, hasFlags, conditionsList, conditions, trivialConditions, isTemplate]); - else: - if (isTemplate != ''): - print('Template types not allowed: "' + resType + '" in line: ' + line); - continue; - if (not restype in typesDict): - typesList.append(restype); - typesDict[restype] = []; - TypesDict[restype] = resType; - typesDict[restype].append([name, typeid, prmsList, prms, hasFlags, conditionsList, conditions, trivialConditions, isTemplate]); - - consts = consts + 1; - -# text serialization: types and funcs -def addTextSerialize(lst, dct, dataLetter): - result = ''; - for restype in lst: - v = dct[restype]; - for data in v: - name = data[0]; - prmsList = data[2]; - prms = data[3]; - hasFlags = data[4]; - conditionsList = data[5]; - conditions = data[6]; - trivialConditions = data[7]; - isTemplate = data[8]; - - templateArgument = '' - if (isTemplate != ''): - templateArgument = '' - - result += 'bool Serialize_' + name + '(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n'; - if (len(conditions)): - result += '\tauto flag = MTP' + dataLetter + name + templateArgument + '::Flags::from_raw(iflag);\n\n'; - if (len(prms)): - result += '\tif (stage) {\n'; - result += '\t\tto.add(",\\n").addSpaces(lev);\n'; - result += '\t} else {\n'; - result += '\t\tto.add("{ ' + name + '");\n'; - result += '\t\tto.add("\\n").addSpaces(lev);\n'; - result += '\t}\n'; - result += '\tswitch (stage) {\n'; - stage = 0; - for k in prmsList: - v = prms[k]; - result += '\tcase ' + str(stage) + ': to.add(" ' + k + ': "); ++stages.back(); '; - if (k == hasFlags): - result += 'if (start >= end) return false; else flags.back() = *start; '; - if (k in trivialConditions): - result += 'if (flag & MTP' + dataLetter + name + templateArgument + '::Flag::f_' + k + ') { '; - result += 'to.add("YES [ BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); '; - result += '} else { to.add("[ SKIPPED BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); } '; - else: - if (k in conditions): - result += 'if (flag & MTP' + dataLetter + name + templateArgument + '::Flag::f_' + k + ') { '; - result += 'types.push_back('; - vtypeget = re.match(r'^[Vv]ector', v); - if (vtypeget): - if (not re.match(r'^[A-Z]', v)): - result += 'mtpc_vector'; - else: - result += '0'; - restype = vtypeget.group(1); - try: - if boxed[restype]: - restype = 0; - except KeyError: - if re.match(r'^[A-Z]', restype): - restype = 0; - else: - restype = v; - try: - if boxed[restype]: - restype = 0; - except KeyError: - if re.match(r'^[A-Z]', restype): - restype = 0; - if (restype): - try: - conses = typesDict[restype]; - if (len(conses) > 1): - print('Complex bare type found: "' + restype + '" trying to serialize "' + k + '" of type "' + v + '"'); - continue; - if (vtypeget): - result += '); vtypes.push_back('; - result += 'mtpc_' + conses[0][0]; - if (not vtypeget): - result += '); vtypes.push_back(0'; - except KeyError: - if (vtypeget): - result += '); vtypes.push_back('; - if (re.match(r'^flags<', restype)): - result += 'mtpc_flags'; - else: - result += 'mtpc_' + restype + '+0'; - if (not vtypeget): - result += '); vtypes.push_back(0'; - else: - if (not vtypeget): - result += '0'; - result += '); vtypes.push_back(0'; - result += '); stages.push_back(0); flags.push_back(0); '; - if (k in conditions): - result += '} else { to.add("[ SKIPPED BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); } '; - result += 'break;\n'; - stage = stage + 1; - result += '\tdefault: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n'; - result += '\t}\n'; - else: - result += '\tto.add("{ ' + name + ' }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();\n'; - result += '\treturn true;\n'; - result += '}\n\n'; - return result; - -# text serialization: types and funcs -def addTextSerializeInit(lst, dct): - result = ''; - for restype in lst: - v = dct[restype]; - for data in v: - name = data[0]; - result += '\tresult.insert(mtpc_' + name + ', Serialize_' + name + ');\n'; - return result; - -textSerializeMethods += addTextSerialize(typesList, typesDict, 'D'); -textSerializeInit += addTextSerializeInit(typesList, typesDict) + '\n'; -textSerializeMethods += addTextSerialize(funcsList, funcsDict, ''); -textSerializeInit += addTextSerializeInit(funcsList, funcsDict) + '\n'; - -for restype in typesList: - v = typesDict[restype]; - resType = TypesDict[restype]; - withData = 0; - creatorsDeclarations = ''; - creatorsBodies = ''; - flagDeclarations = ''; - constructsText = ''; - constructsBodies = ''; - - forwards += 'class MTP' + restype + ';\n'; - forwTypedefs += 'using MTP' + resType + ' = MTPBoxed;\n'; - - withType = (len(v) > 1); - switchLines = ''; - friendDecl = ''; - getters = ''; - visitor = ''; - reader = ''; - writer = ''; - sizeList = []; - sizeFast = ''; - newFast = ''; - sizeCases = ''; - for data in v: - name = data[0]; - typeid = data[1]; - prmsList = data[2]; - prms = data[3]; - hasFlags = data[4]; - conditionsList = data[5]; - conditions = data[6]; - trivialConditions = data[7]; - - dataText = ''; - if (len(prms) > len(trivialConditions)): - withData = 1; - dataText += '\nclass MTPD' + name + ' : public MTP::internal::TypeData {\n'; # data class - else: - dataText += '\nclass MTPD' + name + ' {\n'; # empty data class for visitors - dataText += 'public:\n'; - dataText += '\ttemplate \n'; - dataText += '\tstatic constexpr bool Is() { return std::is_same_v, MTPD' + name + '>; };\n\n'; - sizeList = []; - creatorParams = []; - creatorParamsList = []; - readText = ''; - writeText = ''; - - if (hasFlags != ''): - dataText += '\tenum class Flag : uint32 {\n'; - maxbit = 0; - parentFlagsCheck['MTPD' + name] = {}; - for paramName in conditionsList: - dataText += '\t\tf_' + paramName + ' = (1U << ' + conditions[paramName] + '),\n'; - parentFlagsCheck['MTPD' + name][paramName] = conditions[paramName]; - maxbit = max(maxbit, int(conditions[paramName])); - if (maxbit > 0): - dataText += '\n'; - dataText += '\t\tMAX_FIELD = (1U << ' + str(maxbit) + '),\n'; - dataText += '\t};\n'; - dataText += '\tusing Flags = base::flags;\n'; - dataText += '\tfriend inline constexpr bool is_flag_type(Flag) { return true; };\n'; - dataText += '\n'; - if (len(conditions)): - for paramName in conditionsList: - if (paramName in trivialConditions): - dataText += '\t[[nodiscard]] bool is_' + paramName + '() const;\n'; - constructsBodies += 'bool MTPD' + name + '::is_' + paramName + '() const {\n'; - constructsBodies += '\treturn _' + hasFlags + '.v & Flag::f_' + paramName + ';\n'; - constructsBodies += '}\n'; - dataText += '\n'; - - switchLines += '\tcase mtpc_' + name + ': '; # for by-type-id type constructor - getters += '\t[[nodiscard]] const MTPD' + name + ' &c_' + name + '() const;\n'; # const getter - visitor += '\tcase mtpc_' + name + ': return base::match_method(c_' + name + '(), std::forward(method), std::forward(methods)...);\n'; - - forwards += 'class MTPD' + name + ';\n'; # data class forward declaration - if (len(prms) > len(trivialConditions)): - dataText += '\tMTPD' + name + '();\n'; # default constructor - switchLines += 'setData(new MTPD' + name + '()); '; - - constructsBodies += 'MTPD' + name + '::MTPD' + name + '() = default;\n'; - constructsBodies += 'const MTPD' + name + ' &MTP' + restype + '::c_' + name + '() const {\n'; - if (withType): - constructsBodies += '\tExpects(_type == mtpc_' + name + ');\n\n'; - constructsBodies += '\treturn queryData();\n'; - constructsBodies += '}\n'; - - constructsText += '\texplicit MTP' + restype + '(const MTPD' + name + ' *data);\n'; # by-data type constructor - constructsBodies += 'MTP' + restype + '::MTP' + restype + '(const MTPD' + name + ' *data) : TypeDataOwner(data)'; - if (withType): - constructsBodies += ', _type(mtpc_' + name + ')'; - constructsBodies += ' {\n}\n'; - - dataText += '\tMTPD' + name + '('; # params constructor - prmsStr = []; - prmsInit = []; - for paramName in prmsList: - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - - if (paramType in ['int', 'Int', 'bool', 'Bool']): - prmsStr.append('MTP' + paramType + ' ' + paramName + '_'); - creatorParams.append('MTP' + paramType + ' ' + paramName + '_'); - else: - prmsStr.append('const MTP' + paramType + ' &' + paramName + '_'); - creatorParams.append('const MTP' + paramType + ' &' + paramName + '_'); - creatorParamsList.append(paramName + '_'); - prmsInit.append('_' + paramName + '(' + paramName + '_)'); - if (paramName in conditions): - readText += '\t\t&& (v' + paramName + '() ? _' + paramName + '.read(from, end) : ((_' + paramName + ' = MTP' + paramType + '()), true))\n'; - writeText += '\t\tif (const auto v' + paramName + ' = v.v' + paramName + '()) v' + paramName + '->write(to);\n'; - sizeList.append('(v.v' + paramName + '() ? v.v' + paramName + '()->innerLength() : 0)'); - else: - readText += '\t\t&& _' + paramName + '.read(from, end)\n'; - writeText += '\t\tv.v' + paramName + '().write(to);\n'; - sizeList.append('v.v' + paramName + '().innerLength()'); - - dataText += ', '.join(prmsStr) + ');\n'; - - constructsBodies += 'MTPD' + name + '::MTPD' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n}\n'; - - dataText += '\n'; - dataText += '\t[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end);\n'; - dataText += '\n'; - - constructsBodies += 'bool MTPD' + name + '::read(const mtpPrime *&from, const mtpPrime *end) {\n'; - if readText != '': - constructsBodies += '\treturn' + readText[4:len(readText)-1] + ';\n'; - else: - constructsBodies += '\treturn true;\n'; - constructsBodies += '}\n'; - - if len(prmsList) > 0: - for paramName in prmsList: # getters - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - if (paramName in conditions): - dataText += '\t[[nodiscard]] MTP::conditional v' + paramName + '() const;\n'; - constructsBodies += 'MTP::conditional MTPD' + name + '::v' + paramName + '() const {\n'; - constructsBodies += '\treturn (_' + hasFlags + '.v & Flag::f_' + paramName + ') ? &_' + paramName + ' : nullptr;\n'; - constructsBodies += '}\n'; - else: - dataText += '\t[[nodiscard]] const MTP' + paramType + ' &v' + paramName + '() const;\n'; - constructsBodies += 'const MTP' + paramType + ' &MTPD' + name + '::v' + paramName + '() const {\n'; - constructsBodies += '\treturn _' + paramName + ';\n'; - constructsBodies += '}\n'; - dataText += '\n'; - dataText += 'private:\n'; - for paramName in prmsList: # fields declaration - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - dataText += '\tMTP' + paramType + ' _' + paramName + ';\n'; - dataText += '\n'; - sizeCases += '\tcase mtpc_' + name + ': {\n'; - sizeCases += '\t\tconst MTPD' + name + ' &v(c_' + name + '());\n'; - sizeCases += '\t\treturn ' + ' + '.join(sizeList) + ';\n'; - sizeCases += '\t}\n'; - sizeFast = '\tconst MTPD' + name + ' &v(c_' + name + '());\n\treturn ' + ' + '.join(sizeList) + ';\n'; - newFast = 'new MTPD' + name + '()'; - else: - constructsBodies += 'const MTPD' + name + ' &MTP' + restype + '::c_' + name + '() const {\n'; - if (withType): - constructsBodies += '\tExpects(_type == mtpc_' + name + ');\n\n'; - constructsBodies += '\tstatic const MTPD' + name + ' result;\n'; - constructsBodies += '\treturn result;\n'; - constructsBodies += '}\n'; - - sizeFast = '\treturn 0;\n'; - - switchLines += 'break;\n'; - dataText += '};\n'; # class ending - - dataTexts += dataText; # add data class - - if (not friendDecl): - friendDecl += '\tfriend class MTP::internal::TypeCreator;\n'; - creatorProxyText += '\tinline static MTP' + restype + ' new_' + name + '(' + ', '.join(creatorParams) + ') {\n'; - if (len(prms) > len(trivialConditions)): # creator with params - creatorProxyText += '\t\treturn MTP' + restype + '(new MTPD' + name + '(' + ', '.join(creatorParamsList) + '));\n'; - else: - if (withType): # creator by type - creatorProxyText += '\t\treturn MTP' + restype + '(mtpc_' + name + ');\n'; - else: # single creator - creatorProxyText += '\t\treturn MTP' + restype + '();\n'; - creatorProxyText += '\t}\n'; - creatorsDeclarations += 'MTP' + restype + ' MTP_' + name + '(' + ', '.join(creatorParams) + ');\n'; - creatorsBodies += 'MTP' + restype + ' MTP_' + name + '(' + ', '.join(creatorParams) + ') {\n'; - creatorsBodies += '\treturn MTP::internal::TypeCreator::new_' + name + '(' + ', '.join(creatorParamsList) + ');\n'; - creatorsBodies += '}\n'; - - if (withType): - reader += '\tcase mtpc_' + name + ': _type = cons; '; # read switch line - if (len(prms) > len(trivialConditions)): - reader += '{\n'; - reader += '\t\tif (const auto data = new MTPD' + name + '(); data->read(from, end)) {\n'; - reader += '\t\t\tsetData(data);\n'; - reader += '\t\t} else {\n'; - reader += '\t\t\tdelete data;\n'; - reader += '\t\t\treturn false;\n'; - reader += '\t\t}\n'; - reader += '\t} break;\n'; - - writer += '\tcase mtpc_' + name + ': {\n'; # write switch line - writer += '\t\tconst MTPD' + name + ' &v = c_' + name + '();\n'; - writer += writeText; - writer += '\t} break;\n'; - else: - reader += 'break;\n'; - else: - if (len(prms) > len(trivialConditions)): - reader += '\tif (const auto data = new MTPD' + name + '(); data->read(from, end)) {\n'; - reader += '\t\tsetData(data);\n'; - reader += '\t} else {\n'; - reader += '\t\tdelete data;\n'; - reader += '\t\treturn false;\n'; - reader += '\t}\n'; - - writer += '\tconst MTPD' + name + ' &v = c_' + name + '();\n'; - writer += writeText; - - forwards += '\n'; - - typesText += '\nclass MTP' + restype; # type class declaration - if (withData): - typesText += ' : private MTP::internal::TypeDataOwner'; # if has data fields - typesText += ' {\n'; - typesText += 'public:\n'; - typesText += '\tMTP' + restype + '();\n'; # default constructor - if (withData and not withType): - methods += '\nMTP' + restype + '::MTP' + restype + '() : TypeDataOwner(' + newFast + ') {\n}\n'; - else: - methods += '\nMTP' + restype + '::MTP' + restype + '() = default;\n'; - - typesText += getters; - typesText += '\n'; - typesText += '\ttemplate \n'; - typesText += '\tdecltype(auto) match(Method &&method, Methods &&...methods) const;\n'; - visitorMethods += 'template \n'; - visitorMethods += 'decltype(auto) MTP' + restype + '::match(Method &&method, Methods &&...methods) const {\n'; - if (withType): - visitorMethods += '\tswitch (_type) {\n'; - visitorMethods += visitor; - visitorMethods += '\t}\n'; - visitorMethods += '\tUnexpected("Type in MTP' + restype + '::match.");\n'; - else: - visitorMethods += '\treturn base::match_method(c_' + v[0][0] + '(), std::forward(method), std::forward(methods)...);\n'; - visitorMethods += '}\n\n'; - - typesText += '\n\tuint32 innerLength() const;\n'; # size method - methods += '\nuint32 MTP' + restype + '::innerLength() const {\n'; - if (withType and sizeCases): - methods += '\tswitch (_type) {\n'; - methods += sizeCases; - methods += '\t}\n'; - methods += '\treturn 0;\n'; - else: - methods += sizeFast; - methods += '}\n'; - - typesText += '\tmtpTypeId type() const;\n'; # type id method - methods += 'mtpTypeId MTP' + restype + '::type() const {\n'; - if (withType): - methods += '\tExpects(_type != 0);\n\n'; - methods += '\treturn _type;\n'; - else: - methods += '\treturn mtpc_' + v[0][0] + ';\n'; - methods += '}\n'; - - typesText += '\t[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons'; # read method - if (not withType): - typesText += ' = mtpc_' + name; - typesText += ');\n'; - methods += 'bool MTP' + restype + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n'; - if (withData): - if not (withType): - methods += '\tif (cons != mtpc_' + v[0][0] + ') return false;\n'; - if (withType): - methods += '\tswitch (cons) {\n' - methods += reader; - methods += '\tdefault: return false;\n'; - methods += '\t}\n'; - else: - methods += reader; - methods += '\treturn true;\n'; - methods += '}\n'; - - typesText += '\tvoid write(mtpBuffer &to) const;\n'; # write method - methods += 'void MTP' + restype + '::write(mtpBuffer &to) const {\n'; - if (withType and writer != ''): - methods += '\tswitch (_type) {\n'; - methods += writer; - methods += '\t}\n'; - else: - methods += writer; - methods += '}\n'; - - typesText += '\n\tusing ResponseType = void;\n'; # no response types declared - - typesText += '\nprivate:\n'; # private constructors - if (withType): # by-type-id constructor - typesText += '\texplicit MTP' + restype + '(mtpTypeId type);\n'; - methods += 'MTP' + restype + '::MTP' + restype + '(mtpTypeId type) : '; - methods += '_type(type)'; - methods += ' {\n'; - methods += '\tswitch (type) {\n'; # type id check - methods += switchLines; - methods += '\tdefault: Unexpected("Type in MTP' + restype + '::MTP' + restype + '.");\n'; - methods += '\t}\n'; - methods += '}\n'; # by-type-id constructor end - - if (withData): - typesText += constructsText; - methods += constructsBodies; - - if (friendDecl): - typesText += '\n' + friendDecl; - - if (withType): - typesText += '\n\tmtpTypeId _type = 0;\n'; # type field var - - typesText += '};\n'; # type class ended - - flagOperators += flagDeclarations; - factories += creatorsDeclarations; - methods += creatorsBodies; - typesText += 'using MTP' + resType + ' = MTPBoxed;\n'; # boxed type definition - -flagOperators += '\n' - -for childName in parentFlagsList: - parentName = parentFlags[childName]; - for flag in parentFlagsCheck[childName]: -# -# 'channelForbidden' has 'until_date' flag and 'channel' doesn't have it. -# But as long as flags don't collide this is not a problem. -# -# if (not flag in parentFlagsCheck[parentName]): -# print('Flag ' + flag + ' not found in ' + parentName + ' which should be a flags-parent of ' + childName); -# sys.exit(1); -# - if (flag in parentFlagsCheck[parentName]): - if (parentFlagsCheck[childName][flag] != parentFlagsCheck[parentName][flag]): - print('Flag ' + flag + ' has different value in ' + parentName + ' which should be a flags-parent of ' + childName); - sys.exit(1); - else: - parentFlagsCheck[parentName][flag] = parentFlagsCheck[childName][flag]; - flagOperators += 'inline ' + parentName + '::Flags mtpCastFlags(' + childName + '::Flags flags) { return static_cast<' + parentName + '::Flag>(flags.value()); }\n'; - flagOperators += 'inline ' + parentName + '::Flags mtpCastFlags(MTPflags<' + childName + '::Flags> flags) { return mtpCastFlags(flags.v); }\n'; - -# manual types added here -textSerializeMethods += '\ -bool _serialize_rpc_result(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\ - if (stage) {\n\ - to.add(",\\n").addSpaces(lev);\n\ - } else {\n\ - to.add("{ rpc_result");\n\ - to.add("\\n").addSpaces(lev);\n\ - }\n\ - switch (stage) {\n\ - case 0: to.add(" req_msg_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - case 1: to.add(" result: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n\ - }\n\ - return true;\n\ -}\n\ -\n\ -bool _serialize_msg_container(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\ - if (stage) {\n\ - to.add(",\\n").addSpaces(lev);\n\ - } else {\n\ - to.add("{ msg_container");\n\ - to.add("\\n").addSpaces(lev);\n\ - }\n\ - switch (stage) {\n\ - case 0: to.add(" messages: "); ++stages.back(); types.push_back(mtpc_vector); vtypes.push_back(mtpc_core_message); stages.push_back(0); flags.push_back(0); break;\n\ - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n\ - }\n\ - return true;\n\ -}\n\ -\n\ -bool _serialize_core_message(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\ - if (stage) {\n\ - to.add(",\\n").addSpaces(lev);\n\ - } else {\n\ - to.add("{ core_message");\n\ - to.add("\\n").addSpaces(lev);\n\ - }\n\ - switch (stage) {\n\ - case 0: to.add(" msg_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - case 1: to.add(" seq_no: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - case 2: to.add(" bytes: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - case 3: to.add(" body: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n\ - }\n\ - return true;\n\ -}\n\ -\n'; - -textSerializeInit += '\ - result.insert(mtpc_rpc_result, _serialize_rpc_result);\n\ - result.insert(mtpc_msg_container, _serialize_msg_container);\n\ - result.insert(mtpc_core_message, _serialize_core_message);\n'; - -# module itself - -header = '\ -/*\n\ -WARNING! All changes made in this file will be lost!\n\ -Created from \'' + os.path.basename(input_file) + '\' by \'codegen_scheme\'\n\ -\n\ -This file is part of Telegram Desktop,\n\ -the official desktop application for the Telegram messaging service.\n\ -\n\ -For license and copyright information please follow this link:\n\ -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL\n\ -*/\n\ -#pragma once\n\ -\n\ -#include "mtproto/core_types.h"\n\ -#include "base/flags.h"\n\ -\n\ -// Creator current layer and proxy class declaration\n\ -namespace MTP {\n\ -namespace internal {\n\ -\n\ -' + layer + '\n\ -\n\ -class TypeCreator;\n\ -\n\ -} // namespace internal\n\ -} // namespace MTP\n\ -\n\ -// Type id constants\n\ -enum {\n\ -' + ',\n'.join(enums) + '\n\ -};\n\ -\n\ -// Type forward declarations\n\ -' + forwards + '\n\ -// Boxed types definitions\n\ -' + forwTypedefs + '\n\ -// Type classes definitions\n\ -' + typesText + '\n\ -// Type constructors with data\n\ -' + dataTexts + '\n\ -// RPC methods\n\ -' + funcsText + '\n\ -// Template methods definition\n\ -' + inlineMethods + '\n\ -// Visitor definition\n\ -' + visitorMethods + '\n\ -// Flag operators definition\n\ -' + flagOperators + '\n\ -// Factory methods declaration\n\ -' + factories + '\n\ -// Human-readable text serialization\n\ -[[nodiscard]] bool mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons);\n' - -source = '\ -/*\n\ -WARNING! All changes made in this file will be lost!\n\ -Created from \'' + os.path.basename(input_file) + '\' by \'codegen_scheme\'\n\ -\n\ -This file is part of Telegram Desktop,\n\ -the official desktop application for the Telegram messaging service.\n\ -\n\ -For license and copyright information please follow this link:\n\ -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL\n\ -*/\n\ -#include "scheme.h"\n\ -\n\ -// Creator proxy class definition\n\ -namespace MTP {\n\ -namespace internal {\n\ -\n\ -class TypeCreator {\n\ -public:\n\ -' + creatorProxyText + '\n\ -};\n\ -\n\ -} // namespace internal\n\ -} // namespace MTP\n\ -\n\ -// Methods definition\n\ -' + methods + '\n\ -\n\ -using Types = QVector;\n\ -using StagesFlags = QVector;\n\ -\n\ -' + textSerializeMethods + '\n\ -namespace {\n\ -\n\ -using TextSerializer = bool (*)(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag);\n\ -using TextSerializers = QMap;\n\ -\n\ -QMap createTextSerializers() {\n\ - auto result = QMap();\n\ -\n\ -' + textSerializeInit + '\n\ - return result;\n\ -}\n\ -\n\ -} // namespace\n\ -\n\ -bool mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons) {\n\ - static auto serializers = createTextSerializers();\n\ -\n\ - QVector types, vtypes;\n\ - QVector stages, flags;\n\ - types.reserve(20); vtypes.reserve(20); stages.reserve(20); flags.reserve(20);\n\ - types.push_back(mtpTypeId(cons)); vtypes.push_back(mtpTypeId(vcons)); stages.push_back(0); flags.push_back(0);\n\ -\n\ - mtpTypeId type = cons, vtype = vcons;\n\ - int32 stage = 0, flag = 0;\n\ -\n\ - while (!types.isEmpty()) {\n\ - type = types.back();\n\ - vtype = vtypes.back();\n\ - stage = stages.back();\n\ - flag = flags.back();\n\ - if (!type) {\n\ - if (from >= end) {\n\ - to.error("insufficient data");\n\ - return false;\n\ - } else if (stage) {\n\ - to.error("unknown type on stage > 0");\n\ - return false;\n\ - }\n\ - types.back() = type = *from;\n\ - ++from;\n\ - }\n\ -\n\ - int32 lev = level + types.size() - 1;\n\ - auto it = serializers.constFind(type);\n\ - if (it != serializers.cend()) {\n\ - if (!(*it.value())(to, stage, lev, types, vtypes, stages, flags, from, end, flag)) {\n\ - to.error();\n\ - return false;\n\ - }\n\ - } else if (mtpTextSerializeCore(to, from, end, type, lev, vtype)) {\n\ - types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();\n\ - } else {\n\ - to.error();\n\ - return false;\n\ - }\n\ - }\n\ - return true;\n\ -}\n'; - -already_header = '' -if os.path.isfile(output_header): - with open(output_header, 'r') as already: - already_header = already.read() -if already_header != header: - with open(output_header, 'w') as out: - out.write(header) - -already_source = '' -if os.path.isfile(output_source): - with open(output_source, 'r') as already: - already_source = already.read() -if already_source != source: - with open(output_source, 'w') as out: - out.write(source) +sys.dont_write_bytecode = True +scriptPath = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(scriptPath + '/../../../lib_tl/tl') +from generate_tl import generate + +generate({ + 'namespaces': { + 'creator': 'MTP::internal', + }, + 'prefixes': { + 'type': 'MTP', + 'data': 'MTPD', + 'id': 'mtpc', + 'construct': 'MTP_', + }, + 'types': { + 'prime': 'mtpPrime', + 'typeId': 'mtpTypeId', + 'buffer': 'mtpBuffer', + }, + 'sections': [ + 'serialization', + 'read-write', + ], + + # define some checked flag conversions + # the key flag type should be a subset of the value flag type + # with exact the same names, then the key flag can be implicitly + # casted to the value flag type + 'flagInheritance': { + 'messageService': 'message', + 'updateShortMessage': 'message', + 'updateShortChatMessage': 'message', + 'updateShortSentMessage': 'message', + 'replyKeyboardHide': 'replyKeyboardMarkup', + 'replyKeyboardForceReply': 'replyKeyboardMarkup', + 'inputPeerNotifySettings': 'peerNotifySettings', + 'peerNotifySettings': 'inputPeerNotifySettings', + 'channelForbidden': 'channel', + 'dialogFolder': 'dialog', + }, + + 'typeIdExceptions': [ + 'channel#c88974ac', + 'ipPortSecret#37982646', + 'accessPointRule#4679b65f', + 'help.configSimple#5a592a6c', + ], + + 'renamedTypes': { + 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow': 'passwordKdfAlgoModPow', + }, + + 'skip': [ + 'int ? = Int;', + 'long ? = Long;', + 'double ? = Double;', + 'string ? = String;', + + 'vector {t:Type} # [ t ] = Vector t;', + + 'int128 4*[ int ] = Int128;', + 'int256 8*[ int ] = Int256;', + + 'vector#1cb5c415 {t:Type} # [ t ] = Vector t;', + ], + 'builtin': [ + 'int', + 'long', + 'double', + 'string', + 'bytes', + 'int128', + 'int256', + ], + 'builtinTemplates': [ + 'vector', + 'flags', + ], + 'synonyms': { + 'bytes': 'string', + }, + 'builtinInclude': 'mtproto/core_types.h', + +}) diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index 9bf5bbad04..9b8d8e8ecb 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -7,16 +7,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include -#include -#include -#include #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 +#include +#include +#include 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 - const DataType &queryData() const { - Expects(_data != nullptr); - - return static_cast(*_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 -class MTPBoxed : public bareT { -public: - using bareT::bareT; - MTPBoxed() = default; - MTPBoxed(const MTPBoxed &v) = default; - MTPBoxed &operator=(const MTPBoxed &v) = default; - MTPBoxed(const bareT &v) : bareT(v) { - } - MTPBoxed &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 -class MTPBoxed > { - typename T::CantMakeBoxedBoxedType v; -}; - namespace MTP { namespace details { @@ -257,17 +129,6 @@ struct SecureRequestCreateTag { } // namespace details -template -struct is_boxed : std::false_type { -}; - -template -struct is_boxed> : std::true_type { -}; - -template -constexpr bool is_boxed_v = is_boxed::value; - class SecureRequestData; class SecureRequest { public: @@ -290,7 +151,7 @@ public: template < typename Request, - typename = std::enable_if_t>> + typename = std::enable_if_t>> 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 -struct RepeatHelper { - using type = Type; -}; -template -using Repeat = typename RepeatHelper::type; - -struct InnerHelper { - static void Check(...); - template ().v)> - static Result Check(const Type&); - - template - using type = std::decay_t()))>; -}; - -template -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, - typename = std::enable_if_t>> - Inner value_or(Repeat fallback) const { - return _value ? _value->v : fallback; - } - - template < - typename Inner = InnerHelper::type, - typename = std::enable_if_t>> - 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; template -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(*(from++))); - return true; - } - void write(mtpBuffer &to) const { - to.push_back(static_cast(v.value())); - } - -private: - explicit MTPflags(Flags val) : v(val) { - } - - template - friend MTPflags> MTP_flags(base::flags v); - - template - friend MTPflags> MTP_flags(T v); - -}; +using MTPflags = tl::flags_type; template inline MTPflags> MTP_flags(base::flags v) { - return MTPflags>(v); + return tl::make_flags(v); } template ::value>> inline MTPflags> MTP_flags(T v) { - return MTPflags>(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 -using MTPFlags = MTPBoxed>; +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; - -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; - -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; - -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; - -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; -using MTPBytes = MTPBoxed; +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(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 -class MTPvector { -public: - MTPvector() = default; +using MTPvector = tl::vector_type; - 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(*(from++)); - - auto vector = QVector(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 v; - -private: - explicit MTPvector(QVector &&data) : v(std::move(data)) { - } - - template - friend MTPvector MTP_vector(uint32 count); - template - friend MTPvector MTP_vector(uint32 count, const U &value); - template - friend MTPvector MTP_vector(const QVector &v); - template - friend MTPvector MTP_vector(QVector &&v); - template - friend MTPvector MTP_vector(); - -}; template inline MTPvector MTP_vector(uint32 count) { - return MTPvector(QVector(count)); + return tl::make_vector(count); } template inline MTPvector MTP_vector(uint32 count, const T &value) { - return MTPvector(QVector(count, value)); + return tl::make_vector(count, value); } template inline MTPvector MTP_vector(const QVector &v) { - return MTPvector(QVector(v)); + return tl::make_vector(v); } template inline MTPvector MTP_vector(QVector &&v) { - return MTPvector(std::move(v)); + return tl::make_vector(std::move(v)); } template inline MTPvector MTP_vector() { - return MTPvector(); -} -template -using MTPVector = MTPBoxed>; - -template -inline bool operator==(const MTPvector &a, const MTPvector &b) { - return a.c_vector().v == b.c_vector().v; -} -template -inline bool operator!=(const MTPvector &a, const MTPvector &b) { - return a.c_vector().v != b.c_vector().v; + return tl::make_vector(); } // Human-readable text serialization diff --git a/Telegram/SourceFiles/settings/settings_codes.cpp b/Telegram/SourceFiles/settings/settings_codes.cpp index a97f13942d..505146b57e 100644 --- a/Telegram/SourceFiles/settings/settings_codes.cpp +++ b/Telegram/SourceFiles/settings/settings_codes.cpp @@ -156,6 +156,7 @@ auto GenerateCodes() { Ui::show(Box("All sound overrides were reset.")); } }); + return codes; } diff --git a/Telegram/gyp/lib_scheme.gyp b/Telegram/gyp/lib_scheme.gyp index d9ec6806ce..9b58783d53 100644 --- a/Telegram/gyp/lib_scheme.gyp +++ b/Telegram/gyp/lib_scheme.gyp @@ -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', ], diff --git a/Telegram/lib_tl b/Telegram/lib_tl new file mode 160000 index 0000000000..ab4e30d389 --- /dev/null +++ b/Telegram/lib_tl @@ -0,0 +1 @@ +Subproject commit ab4e30d38914142d6abbb64389a00cd6f8ef55d2