Binary structures
- Pure TypeScript, run anywhere
- Strong static type checking
- Tree shaking friendly design
- Public interface compatible with
ArrayBufferView, like native binary types - Support for little-endian, big-endian, and dynamic endian
- Support for structures, unions, pointers, arrays, inheritance, and more
Endianness can be defined for each individual member.
import{int8,Struct,uint16BE,uint16LE}from'@hqtsm/struct';classExampleextendsStruct{declarepublicalpha: number;declarepublicbeta: number;declarepublicgamma: number;static{uint16LE(this,'alpha');uint16BE(this,'beta');int8(this,'gamma');}}constdata=newUint8Array(Example.BYTE_LENGTH);constexample=newExample(data.buffer);example.alpha=0xABCD;example.beta=0xBCDE;example.gamma=-123;console.assert(data.join(' ')==='205 171 188 222 133');Using the endian passed into the constructor, or host endianness.
import{Struct,uint16}from'@hqtsm/struct';classExampleextendsStruct{declarepublicalpha: number;declarepublicbeta: number;static{uint16(this,'alpha');uint16(this,'beta');}}constdata=newUint8Array(Example.BYTE_LENGTH);constexampleLE=newExample(data.buffer,0,true);exampleLE.alpha=0xABCD;exampleLE.beta=0xBCDE;console.assert(data.join(' ')==='205 171 222 188');constexampleBE=newExample(data.buffer,0,false);exampleBE.alpha=0xABCD;exampleBE.beta=0xBCDE;console.assert(data.join(' ')==='171 205 188 222');Structures can be extended with new child members.
import{float32,Struct,uint32}from'@hqtsm/struct';classVariableextendsStruct{declarepublictype: number;static{uint32(this,'type');}}classVariableFloatextendsVariable{declarepublicvalue: number;static{float32(this,'value');}}constdata=newUint8Array(VariableFloat.BYTE_LENGTH);constvarFloat=newVariableFloat(data.buffer,0,true);varFloat.type=0xF;varFloat.value=3.1415;console.assert(data.join(' ')==='15 0 0 0 86 14 73 64');Defining a child structure is easy.
import{Arr,array,member,Struct,uint16BE,Uint8Ptr}from'@hqtsm/struct';classChildextendsStruct{declarepublicalpha: number;declarepublicbeta: number;static{uint16BE(this,'alpha');uint16BE(this,'beta');}}classParentextendsStruct{declarepublicchild1: Child;declarepublicchild2: Child;static{member(Child,this,'child1');member(Child,this,'child2');}}constdata=newUint8Array(Parent.BYTE_LENGTH);conststru=newParent(data.buffer);stru.child1.alpha=97;stru.child1.beta=98;stru.child2.alpha=65;stru.child2.beta=66;console.assert(data.join(' ')==='0 97 0 98 0 65 0 66');Comes with pointers for primitives, and a factory for pointers to types.
import{int8,Int8Ptr,pointer,Struct}from'@hqtsm/struct';constdata=newInt8Array(6);// Starting at an offset.consti8p=newInt8Ptr(data.buffer,2);// Setting values by index.i8p[0]=0;i8p[1]=1;i8p[2]=2;i8p[3]=3;// Negative indexing also works, accessing memory before offset.i8p[-1]=-1;i8p[-2]=-2;console.assert(data.join(' ')==='-2 -1 0 1 2 3');classXYextendsStruct{declarepublicx: number;declarepublicy: number;static{int8(this,'x');int8(this,'y');}}// Pointer for custom type.constXYPtr=pointer(XY);constxyp=newXYPtr(data.buffer,2);console.assert(xyp[0].x===0);console.assert(xyp[0].y===1);console.assert(xyp[1].x===2);console.assert(xyp[1].y===3);console.assert(xyp[-1].x===-2);console.assert(xyp[-1].y===-1);// Type memory can also be assigned.constxy=newXY(newArrayBuffer(XY.BYTE_LENGTH));xy.x=88;xy.y=89;xyp[0]=xy;console.assert(data.join(' ')==='-2 -1 88 89 2 3');A pointer extended to a type of a fixed length.
import{Arr,array,int8,member,pointer,Struct,Uint8Ptr,}from'@hqtsm/struct';classXYextendsStruct{declarepublicx: number;declarepublicy: number;static{int8(this,'x');int8(this,'y');}}classExampleextendsStruct{declarepublicbytes: Arr<number>;declarepublicxys: Arr<XY>;static{member(array(Uint8Ptr,4),this,'bytes');member(array(XY,2),this,'xys');}}constdata=newUint8Array(Example.BYTE_LENGTH);constexample=newExample(data.buffer);example.bytes[0]=10;example.bytes[1]=20;example.bytes[2]=30;example.bytes[3]=40;example.xys[0].x=150;example.xys[0].y=160;example.xys[1].x=170;example.xys[1].y=180;console.assert(data.join(' ')==='10 20 30 40 150 160 170 180');A union will automatically use overlapping member memory.
import{Arr,array,member,uint32BE,Uint8Ptr,Union}from'@hqtsm/struct';classFourCCextendsUnion{declarepublicint: number;declarepublicchars: Arr<number>;static{uint32BE(this,'int');member(array(Uint8Ptr,4),this,'chars');}}constdata=newUint8Array(FourCC.BYTE_LENGTH);constfour=newFourCC(data.buffer);four.int=0x41424344;console.assert(four.chars[0]===0x41);console.assert(String.fromCharCode(...four.chars)==='ABCD');By default member memory is sequentially without alignment or padding.
import{pad,Struct,uint32,uint8}from'@hqtsm/struct';classExampleextendsStruct{declareprivatealpha: number;declareprotectedbeta: number;declarepublicgamma: number;publicsetAlpha(value: number): void{this.alpha=value;}publicsetBeta(value: number): void{this.beta=value;}static{uint8(this,'alpha'asnever);uint32(this,'beta'asnever);uint8(this,'gamma');}}console.assert(Example.BYTE_LENGTH===6);Padding can be manually added as a property or anonymously.
import{pad,Struct,uint32,uint8}from'@hqtsm/struct';classExampleextendsStruct{declareprivatealpha: number;declarepublicpadding: never;declareprotectedbeta: number;declarepublicgamma: number;publicsetAlpha(value: number): void{this.alpha=value;}publicsetBeta(value: number): void{this.beta=value;}static{uint8(this,'alpha'asnever);pad(3,this,'padding');// Property.uint32(this,'beta'asnever);uint8(this,'gamma');pad(3,this);// Anonymous.}}console.assert(Example.BYTE_LENGTH===12);Using intergers or arrays for padding also works.
Members can be made private or protected but type checking must be relaxed.
Casting the name to never or any will pass the type checker.
import{Struct,uint8}from'@hqtsm/struct';classExampleextendsStruct{declareprivatealpha: number;declareprotectedbeta: number;declarepublicgamma: number;publicsetAlpha(value: number): void{this.alpha=value;}publicsetBeta(value: number): void{this.beta=value;}static{uint8(this,'alpha'asnever);uint8(this,'beta'asnever);uint8(this,'gamma');}}constdata=newUint8Array(Example.BYTE_LENGTH);constexample=newExample(data.buffer);example.setAlpha(65);example.setBeta(66);example.gamma=71;console.assert(data.join(' ')==='65 66 71');