mtcute/packages/tl-utils/src/calculator.ts

105 lines
2.6 KiB
TypeScript
Raw Normal View History

import { TlEntry } from './types'
const PRIMITIVES_SIZES: Record<string, number> = {
int: 4,
long: 8,
int53: 8,
int128: 16,
int256: 32,
double: 8,
boolFalse: 4,
boolTrue: 4,
bool: 4,
Bool: 4,
'#': 4,
}
export function calculateStaticSizes(
entries: TlEntry[],
): Record<string, number> {
const staticSizes: Record<string, number> = {}
const unionSizes: Record<string, Record<string, number | null>> = {}
let changedInLastIteration = true
function getUnionStaticSize(name: string): number | null {
const values = Object.values(unionSizes[name] ?? {})
if (values.length === 0) return null
const first = values[0]
if (first === null) return null
for (const value of values) {
if (value !== first) return null
}
return first
}
function calculateStaticSize(entry: TlEntry): number | null {
if (entry.generics) return null // definitely not static sized
let size = 4 // constructor id
for (const arg of entry.arguments) {
if (arg.typeModifiers?.predicate) {
if (arg.type === 'true') {
continue // zero-size type
}
// cant be static sized
return null
}
if (
arg.typeModifiers?.isVector ||
arg.typeModifiers?.isBareVector
) {
// cant be static sized
return null
}
let unionSize
if (arg.type in PRIMITIVES_SIZES) {
size += PRIMITIVES_SIZES[arg.type]
} else if (arg.type in staticSizes) {
size += staticSizes[arg.type] - 4 // subtract constructor id
} else if ((unionSize = getUnionStaticSize(arg.type))) {
size += unionSize
} else {
// likely not static sized
return null
}
}
return size
}
while (changedInLastIteration) {
changedInLastIteration = false
for (const entry of entries) {
if (staticSizes[entry.name] !== undefined) continue
const size = calculateStaticSize(entry)
if (entry.kind === 'class') {
if (!unionSizes[entry.type]) {
unionSizes[entry.type] = {}
}
unionSizes[entry.type][entry.name] = size
}
if (size === null) {
continue
}
staticSizes[entry.name] = size
changedInLastIteration = true
}
}
return staticSizes
}