Browse Source

Fix serializing negative longs

Parse JSONValue
master
Eduard Kuzmenko 3 years ago
parent
commit
f6f35f4b70
  1. 2
      src/layer.d.ts
  2. 82
      src/lib/mtproto/tl_utils.ts
  3. 5
      src/scripts/generate_mtproto_types.js

2
src/layer.d.ts vendored

@ -13015,7 +13015,7 @@ export interface MethodDeclMap {
'help.getTermsOfServiceUpdate': {req: HelpGetTermsOfServiceUpdate, res: HelpTermsOfServiceUpdate}, 'help.getTermsOfServiceUpdate': {req: HelpGetTermsOfServiceUpdate, res: HelpTermsOfServiceUpdate},
'help.acceptTermsOfService': {req: HelpAcceptTermsOfService, res: boolean}, 'help.acceptTermsOfService': {req: HelpAcceptTermsOfService, res: boolean},
'help.getDeepLinkInfo': {req: HelpGetDeepLinkInfo, res: HelpDeepLinkInfo}, 'help.getDeepLinkInfo': {req: HelpGetDeepLinkInfo, res: HelpDeepLinkInfo},
'help.getAppConfig': {req: HelpGetAppConfig, res: JSONValue}, 'help.getAppConfig': {req: HelpGetAppConfig, res: any},
'help.saveAppLog': {req: HelpSaveAppLog, res: boolean}, 'help.saveAppLog': {req: HelpSaveAppLog, res: boolean},
'help.getPassportConfig': {req: HelpGetPassportConfig, res: HelpPassportConfig}, 'help.getPassportConfig': {req: HelpGetPassportConfig, res: HelpPassportConfig},
'help.getSupportName': {req: HelpGetSupportName, res: HelpSupportName}, 'help.getSupportName': {req: HelpGetSupportName, res: HelpSupportName},

82
src/lib/mtproto/tl_utils.ts

@ -9,17 +9,29 @@
* https://github.com/zhukov/webogram/blob/master/LICENSE * https://github.com/zhukov/webogram/blob/master/LICENSE
*/ */
import { bytesToHex } from '../../helpers/bytes'; import { bytesFromHex, bytesToHex } from '../../helpers/bytes';
import { isObject, longFromInts } from './bin_utils'; import { addPadding, isObject, longFromInts } from './bin_utils';
import { MOUNT_CLASS_TO } from '../../config/debug'; import { MOUNT_CLASS_TO } from '../../config/debug';
import { str2bigInt, dup, divide_, bigInt2str } from '../../vendor/leemon'; import { str2bigInt, bigInt2str, int2bigInt, sub_ } from '../../vendor/leemon';
import Schema, { MTProtoConstructor } from './schema'; import Schema, { MTProtoConstructor } from './schema';
import { JSONValue } from '../../layer';
/// #if MTPROTO_WORKER /// #if MTPROTO_WORKER
// @ts-ignore // @ts-ignore
import { gzipUncompress } from '../crypto/crypto_utils'; import { gzipUncompress } from '../crypto/crypto_utils';
/// #endif /// #endif
// @ts-ignore
/* import {BigInteger} from 'jsbn';
export function bigint(num: number) {
return new BigInteger(num.toString(16), 16);
}
function bigStringInt(strNum: string) {
return new BigInteger(strNum, 10)
} */
const boolFalse = +Schema.API.constructors.find(c => c.predicate === 'boolFalse').id; const boolFalse = +Schema.API.constructors.find(c => c.predicate === 'boolFalse').id;
const boolTrue = +Schema.API.constructors.find(c => c.predicate === 'boolTrue').id; const boolTrue = +Schema.API.constructors.find(c => c.predicate === 'boolTrue').id;
const vector = +Schema.API.constructors.find(c => c.predicate === 'vector').id; const vector = +Schema.API.constructors.find(c => c.predicate === 'vector').id;
@ -155,28 +167,33 @@ class TLSerialization {
sLong = sLong ? sLong.toString() : '0'; sLong = sLong ? sLong.toString() : '0';
} }
const R = 0x100000000; /* let perf = performance.now();
//const divRem = bigStringInt(sLong).divideAndRemainder(bigint(R)); const jsbnBytes: Uint8Array = new Uint8Array(8);
const jsbnBigInt = bigStringInt(sLong);
for(let i = 0; i < 8; i++) {
jsbnBytes[i] = +jsbnBigInt.shiftRight(8 * i).and(bigint(255)).toString(10);
}
console.log('perf1', performance.now() - perf); */
const a = str2bigInt(sLong, 10, 64); // perf = performance.now();
const q = dup(a); let bigInt: number[];
const r = dup(a); if(sLong[0] === '-') { // leemon library can't parse signed numbers
divide_(a, str2bigInt((R).toString(16), 16, 64), q, r); bigInt = int2bigInt(0, 64, 8);
//divInt_(a, R); sub_(bigInt, str2bigInt(sLong.slice(1), 10, 64));
} else {
bigInt = str2bigInt(sLong, 10, 64);
}
const high = +bigInt2str(q, 10); const hex = bigInt2str(bigInt, 16).slice(-16);
let low = +bigInt2str(r, 10); const bytes = addPadding(bytesFromHex(hex).reverse(), 8, true, true, false);
if(high < low) { // console.log('perf2', performance.now() - perf);
low -= R;
}
//console.log('storeLong', sLong, divRem[0].intValue(), divRem[1].intValue(), high, low); this.storeRawBytes(bytes);
//this.writeInt(divRem[1].intValue(), (field || '') + ':long[low]'); // if(jsbnBytes.hex !== bytes.hex) {
//this.writeInt(divRem[0].intValue(), (field || '') + ':long[high]'); // console.error(bigInt, sLong, bigInt2str(bigInt, 10), negative(bigInt), jsbnBytes.hex, bigInt2str(bigInt, 16), bytes.hex);
this.writeInt(low, (field || '') + ':long[low]'); // }
this.writeInt(high, (field || '') + ':long[high]');
} }
public storeDouble(f: any, field?: string) { public storeDouble(f: any, field?: string) {
@ -806,9 +823,32 @@ class TLDeserialization<FetchLongAs extends Long> {
if(fallback) { if(fallback) {
this.mtproto = true; this.mtproto = true;
} }
if(type === 'JSONValue') {
return this.formatJSONValue(result);
}
return result; return result;
} }
private formatJSONValue(jsonValue: JSONValue): any {
if(!jsonValue._) return jsonValue;
switch(jsonValue._) {
case 'jsonNull':
return null;
case 'jsonObject': {
const out: any = {};
const objectValues = jsonValue.value;
for(let i = 0, length = objectValues.length; i < length; ++i) {
const objectValue = objectValues[i];
out[objectValue.key] = this.formatJSONValue(objectValue.value);
}
return out;
}
default:
return jsonValue.value;
}
}
public getOffset() { public getOffset() {
return this.offset; return this.offset;

5
src/scripts/generate_mtproto_types.js

@ -251,7 +251,10 @@ mtproto.methods.forEach((_method) => {
const camelizedMethod = camelizeName(method, true, true); const camelizedMethod = camelizeName(method, true, true);
methodsMap[method] = {req: camelizedMethod, res: processParamType(type, false/* , overrideMethodTypes */)}; methodsMap[method] = {
req: camelizedMethod,
res: processParamType(type, false, {'JSONValue': 'any'}/* , overrideMethodTypes */)
};
let str = `export type ${camelizedMethod} = {\n`; let str = `export type ${camelizedMethod} = {\n`;

Loading…
Cancel
Save