99 lines
2.6 KiB
TypeScript
99 lines
2.6 KiB
TypeScript
import type { TlEntry } from './types.js'
|
|
|
|
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
|
|
}
|