Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

578 Commits

Repository files navigation

HQTSM: Struct

Binary structures

binarystructunionpointerarrayendiandataviewarraybuffer

JSRnpmCI

Features

  • 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

Usage

Fixed Endianness

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');

Dynamic Endianness

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');

Extending / Inheritance

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');

Child Structures

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');

Pointer

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');

Array

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');

Union

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');

Alignment / Padding

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.

Private / Protected

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');

Releases

Packages

Used by

Contributors

Languages