Skip to content

Instantly share code, notes, and snippets.

@tshm
Last active February 2, 2020 03:01
Show Gist options
  • Save tshm/4d4b004ceb2ece330a0938bcfe24ab3c to your computer and use it in GitHub Desktop.
Save tshm/4d4b004ceb2ece330a0938bcfe24ab3c to your computer and use it in GitHub Desktop.
typescript annotaion for fixed size message convertion
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