143 lines
5 KiB
JavaScript
143 lines
5 KiB
JavaScript
|
// disclaimer: code sucks because tl itself sucks :shrug:
|
||
|
const { createWriter } = require('./common')
|
||
|
const schema = require('../raw-schema.json')
|
||
|
|
||
|
const output = createWriter('../binary/reader.js')
|
||
|
const { tab, untab, write } = output
|
||
|
|
||
|
write(`// This file is auto-generated. Do not edit.
|
||
|
"use strict";
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
|
||
|
exports.default = {`)
|
||
|
tab()
|
||
|
|
||
|
function getFunctionCallByTypeName(ns, type, arg) {
|
||
|
let funcName,
|
||
|
args = []
|
||
|
if (type === 'Object') return 'object()'
|
||
|
if (type === 'number') funcName = 'int32'
|
||
|
else if (type === 'Long') funcName = 'long'
|
||
|
else if (type === 'RawLong') funcName = 'rawLong'
|
||
|
else if (type === 'Int128') funcName = 'int128'
|
||
|
else if (type === 'Int256') funcName = 'int256'
|
||
|
else if (type === 'Double') funcName = 'double'
|
||
|
else if (type === 'string') funcName = 'string'
|
||
|
else if (type === 'Buffer') funcName = 'bytes'
|
||
|
else if (type.match(/^(boolean|true|false)$/)) funcName = 'boolean'
|
||
|
else if (type.endsWith('[]')) {
|
||
|
let typ = type.substr(0, type.length - 2)
|
||
|
|
||
|
let reader // = `(r, val) => r.${getFunctionCallByTypeName(ns, typ, 'val')}`
|
||
|
if (typ === '%Message') {
|
||
|
reader = 'exports.default[1538843921]' // because tl sucks :shrug:
|
||
|
} else if (typ[0] === '%')
|
||
|
throw new Error(
|
||
|
'Only bare mt_message is supported. Please update codegen for ' +
|
||
|
typ
|
||
|
)
|
||
|
else if (typ === 'number') reader = 'this.int32'
|
||
|
else if (typ === 'Buffer') reader = 'this.bytes'
|
||
|
else if (typ === 'Long') reader = 'this.long'
|
||
|
else if (typ === 'RawLong') reader = 'this.rawLong'
|
||
|
else if (typ === 'Int128') reader = 'this.int128'
|
||
|
else if (typ === 'Int256') reader = 'this.int256'
|
||
|
else if (typ === 'Double') reader = 'this.double'
|
||
|
else if (typ === 'string') reader = 'this.string'
|
||
|
else reader = 'this.object'
|
||
|
|
||
|
if (arg && arg.name === 'serverPublicKeyFingerprints')
|
||
|
reader = 'this.ulong'
|
||
|
|
||
|
funcName = `vector`
|
||
|
args = [reader]
|
||
|
|
||
|
if (typ === '%Message') args.push(true)
|
||
|
} else funcName = `object`
|
||
|
|
||
|
return `${funcName}(${args.join(', ')})`
|
||
|
}
|
||
|
|
||
|
const parsedManually = [
|
||
|
0x1cb5c415,
|
||
|
0x3072cfa1,
|
||
|
0xbc799737,
|
||
|
0x997275b5,
|
||
|
0x3fedd339,
|
||
|
0x56730bcc,
|
||
|
]
|
||
|
|
||
|
function writeNamespace(nsType) {
|
||
|
return ([namespace, content]) => {
|
||
|
let baseTypePrefix = nsType === 'mtproto' ? 'mtproto.' : ''
|
||
|
let nsPrefix = namespace === '$root' ? '' : namespace + '.'
|
||
|
let prefix = (nsType === 'mtproto' ? 'mt_' : '') + nsPrefix
|
||
|
|
||
|
const addObject = (isMethod) => {
|
||
|
return (cls) => {
|
||
|
if (cls.id === 0 || parsedManually.includes(cls.id)) return
|
||
|
|
||
|
write(`${cls.id}: function () {`)
|
||
|
tab()
|
||
|
|
||
|
if (cls.arguments?.length) {
|
||
|
write(`var ret = {};`)
|
||
|
write(`ret._ = '${prefix}${cls.name}';`)
|
||
|
|
||
|
cls.arguments.forEach((arg) => {
|
||
|
if (arg.type === '$FlagsBitField') {
|
||
|
write('var ' + arg.name + ' = this.uint32();')
|
||
|
} else if (arg.optional) {
|
||
|
let bitIndex = +arg.predicate.split('.')[1]
|
||
|
let condition = `${arg.predicate.split('.')[0]} & ${
|
||
|
2 ** bitIndex
|
||
|
}`
|
||
|
|
||
|
if (arg.type === 'true') {
|
||
|
write(`ret.${arg.name} = !!(${condition});`)
|
||
|
} else {
|
||
|
write(
|
||
|
`if (${condition}) ret.${
|
||
|
arg.name
|
||
|
} = this.${getFunctionCallByTypeName(
|
||
|
baseTypePrefix,
|
||
|
arg.type
|
||
|
)}`
|
||
|
)
|
||
|
}
|
||
|
} else {
|
||
|
write(
|
||
|
`ret.${
|
||
|
arg.name
|
||
|
} = this.${getFunctionCallByTypeName(
|
||
|
baseTypePrefix,
|
||
|
arg.type,
|
||
|
arg
|
||
|
)};`
|
||
|
)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
write('return ret;')
|
||
|
} else {
|
||
|
write(`return { _: '${prefix}${cls.name}' };`)
|
||
|
}
|
||
|
|
||
|
untab()
|
||
|
write('},')
|
||
|
}
|
||
|
}
|
||
|
|
||
|
content.classes.forEach(addObject(false))
|
||
|
// we don't really need to read methods :shrug:
|
||
|
// content.methods.forEach(addObject(true))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Object.entries(schema.mtproto).forEach(writeNamespace('mtproto'))
|
||
|
Object.entries(schema.api).forEach(writeNamespace())
|
||
|
|
||
|
// for readerMap
|
||
|
untab()
|
||
|
write('};')
|