97 lines
2.4 KiB
TypeScript
97 lines
2.4 KiB
TypeScript
|
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
|
||
|
}
|
||
|
|
||
|
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
|
||
|
}
|