Last active
February 2, 2020 03:01
-
-
Save tshm/4d4b004ceb2ece330a0938bcfe24ab3c to your computer and use it in GitHub Desktop.
typescript annotaion for fixed size message convertion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'reflect-metadata'; | |
interface Iprops { | |
name: string; | |
size: number; | |
type: any; | |
} | |
let classes: { [key: string]: Iprops[] } = {}; | |
let totalsize = {}; | |
export function Init<T>( | |
ctor: new () => T, | |
props: Omit<T, '_totalsize' | 'Serialize' | 'spare'> | |
): T { | |
const base = new ctor(); | |
return Object.assign(base, props); | |
} | |
export class Serializable { | |
_totalsize: number; | |
Serialize(): string { | |
return classes[this.constructor.name] | |
.map(p => { | |
const v = this[p.name]; | |
if (p.type.name === 'String') { | |
return (Array(p.size + 1).join(' ') + v).slice(-p.size); | |
} | |
if (v instanceof Array) { | |
const str = v.map(i => (i as Serializable).Serialize()).join(''); | |
// console.log(classes, totalsize); | |
const len = p.size * totalsize[p.type.name]; | |
return str + ' '.repeat(len - str.length); | |
} | |
return (v as Serializable).Serialize(); | |
}) | |
.join(''); | |
} | |
constructor(str: string = '') { | |
let offset = 0; | |
this._totalsize = getTotalSize(this.constructor.name); | |
// console.log('totalsize', this.constructor.name, this.totalsize); | |
for (const p of classes[this.constructor.name]) { | |
if (p.type.name !== 'String') { | |
if (p.size === 1) { | |
this[p.name] = new p.type(str.slice(offset)); | |
offset += (this[p.name] as Serializable)._totalsize; | |
} else { | |
this[p.name] = Array.from(Array(p.size), () => { | |
const v = new p.type(str.slice(offset)); | |
offset += (v as Serializable)._totalsize; | |
return v; | |
}); | |
} | |
continue; | |
} | |
this[p.name] = str.slice(offset, offset + p.size); | |
offset += p.size; | |
} | |
} | |
} | |
function getTotalSize(className: string): number { | |
if (!classes[className]) { | |
console.error('cannot get classinfo', className); | |
return 0; | |
} | |
if (!totalsize[className]) { | |
totalsize[className] = classes[className] | |
.map(({ size, type }) => { | |
const isArray = type.name !== 'String'; | |
return isArray ? size * getTotalSize(type.name) : size; | |
}) | |
.reduce((acc, num) => acc + num, 0); | |
} | |
return totalsize[className]; | |
} | |
export function Size(len: number, arrayof: Function | null = null) { | |
return function(target: any, name: string) { | |
const className = target?.constructor?.name; | |
const type = Reflect.getMetadata('design:type', target, name); | |
if (!classes[className]) classes[className] = []; | |
classes[className].push({ | |
name, | |
size: len, | |
type: type?.name !== 'Array' ? type : arrayof | |
}); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment