Nerdiest Political Manifesto

    struct-buffer
    TypeScript icon, indicating that this package has built-in type declarations

    5.1.3 • Public • Published

    struct-buffer

    Add structure to ArrayBuffer

    Install

    $ npm i struct-buffer
    

    how to use

    import { float, string_t, StructBuffer, pack } from "struct-buffer";
    
    const struct = new StructBuffer("Player", {
      hp: float,
      mp: float,
      name: string_t[3],
    });
    
    const buffer: DataView = pack("2f3s", 10, 100, "abc");
    
    // decode
    const data = struct.decode(buffer);
    // data => { hp: 10, mp: 100, name: 'abc' }
    
    // encode
    const view = struct.encode({
      hp: 10,
      mp: 100,
      name: "abc",
    });
    // view => <41 20 00 00 42 c8 00 00 61 62 63>

    Use in browser

    <script src="struct-buffer.js"></script>
    <script>
      const { DWORD, string_t, StructBuffer, uint32_t } = window.StructBuffer;
    </script>

    Use "type" for conversion

    import { DWORD } from "struct-buffer";
    
    // encode
    const view = DWORD[2].encode([1, 2]); 
    // view => <00 00 00 01 00 00 00 02>
    
    // decode
    const data = DWORD[2].decode(view);
    // data => [ 1, 2 ]

    register Type

    const myShort = registerType("short", 2, false);
    
    const struct = new StructBuffer("Player", {
      hp: myShort,
      mp: myShort,
      pos: myShort[2],
    });
    
    // encode
    const view = struct.encode({
      hp: 2,
      mp: 10,
      pos: [100, 200],
    });
    // view => <00 02 00 0a 00 64 00 c8>
    
    // decode
    const data = struct.decode(view);
    // data => { hp: 2, mp: 10, pos: [ 100, 200 ] }

    typedef

    const HANDLE = typedef("HANDLE", DWORD);
    HANDLE.size // 4
    HANDLE.unsigned // true

    Nested struct

    /*
    typedef struct _XINPUT_STATE {
      DWORD          dwPacketNumber;
      XINPUT_GAMEPAD Gamepad;
    } XINPUT_STATE, *PXINPUT_STATE;
    
    
    typedef struct _XINPUT_GAMEPAD {
      WORD  wButtons;
      BYTE  bLeftTrigger;
      BYTE  bRightTrigger;
      SHORT sThumbLX;
      SHORT sThumbLY;
      SHORT sThumbRX;
      SHORT sThumbRY;
    } XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
    */
    
    XINPUT_GAMEPAD = new StructBuffer("XINPUT_GAMEPAD", {
      wButtons: WORD,
      bLeftTrigger: BYTE,
      bRightTrigger: BYTE,
      sThumbLX: int16_t,
      sThumbLY: int16_t,
      sThumbRX: int16_t,
      sThumbRY: int16_t,
    });
    
    XINPUT_STATE = new StructBuffer("XINPUT_STATE", {
      dwPacketNumber: DWORD,
      Gamepad: XINPUT_GAMEPAD,
    });
    
    // decode
    XINPUT_STATE.decode(
        new Uint8Array([
          0, 0, 0, 0, // dwPacketNumber
          0, 1, // wButtons
          0,    // bLeftTrigger
          0,    // bRightTrigger
          0, 1, // sThumbLX
          0, 2, // sThumbLY
          0, 3, // sThumbRX
          0, 4, // sThumbRY
        ])
    );
    
    // encode
    XINPUT_STATE.encode({
      dwPacketNumber: 0,
      Gamepad: {
        wButtons: 1,
        bLeftTrigger: 0,
        bRightTrigger: 0,
        sThumbLX: 1,
        sThumbLY: 2,
        sThumbRX: 3,
        sThumbRY: 4,
      },
    });

    parse c-struct

    import { CStruct } from "struct-buffer";
    
    const cStruct = `
    //
    // Structures used by XInput APIs
    //
    typedef struct _XINPUT_GAMEPAD
    {
        WORD                                wButtons;
        BYTE                                bLeftTrigger;
        BYTE                                bRightTrigger;
        SHORT                               sThumbLX;
        SHORT                               sThumbLY;
        SHORT                               sThumbRX;
        SHORT                               sThumbRY;
    } XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
    
    typedef struct _XINPUT_STATE
    {
        DWORD                               dwPacketNumber;
        XINPUT_GAMEPAD                      Gamepad;
    } XINPUT_STATE, *PXINPUT_STATE;
    
    typedef struct _XINPUT_VIBRATION
    {
        WORD                                wLeftMotorSpeed;
        WORD                                wRightMotorSpeed;
    } XINPUT_VIBRATION, *PXINPUT_VIBRATION;
    
    typedef struct _XINPUT_BATTERY_INFORMATION
    {
        BYTE BatteryType;
        BYTE BatteryLevel;
    } XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;
    `;
    
    const structs = CStruct.parse(cStruct);
    sizeof(structs.XINPUT_GAMEPAD) // 12
    sizeof(structs.XINPUT_STATE) // 16
    sizeof(structs.XINPUT_VIBRATION) // 4
    sizeof(structs.XINPUT_BATTERY_INFORMATION) // 2

    struct list

    const User = new StructBuffer("User", {
      name: string_t[2],
      name2: string_t[2],
    });
    
    const Users = new StructBuffer("Users", {
      users: User[2],
    });
    
    const data = Users.decode(
      new Uint8Array([0x61, 0x31, 0x61, 0x32, 0x62, 0x31, 0x62, 0x32])
    );
    // data.users.length => 2
    // data.users[0] => { name: "a1", name2: "a2" }
    // data.users[1] => { name: "b1", name2: "b2" }
    
    // or
    
    const users = User[2].decode(
      new Uint8Array([0x61, 0x31, 0x61, 0x32, 0x62, 0x31, 0x62, 0x32])
    );
    // users => [ { name: 'a1', name2: 'a2' }, { name: 'b1', name2: 'b2' } ]

    StructBuffer to c-struct

    import { CStruct } from "struct-buffer";
    
    const XINPUT_GAMEPAD = new StructBuffer("XINPUT_GAMEPAD", {
      wButtons: WORD,
      bLeftTrigger: BYTE,
      bRightTrigger: BYTE,
      sThumbLX: int16_t,
      sThumbLY: int16_t,
      sThumbRX: int16_t,
      sThumbRY: int16_t[2],
    });
    const cStruct = CStruct.from(XINPUT_GAMEPAD);
    
    // console.log(cStruct) => 
    typedef struct _XINPUT_GAMEPAD
    {
        WORD wButtons;
        BYTE bLeftTrigger;
        BYTE bRightTrigger;
        int16_t sThumbLX;
        int16_t sThumbLY;
        int16_t sThumbRX;
        int16_t sThumbRY[2];
    } XINPUT_GAMEPAD, *XINPUT_GAMEPAD;

    "string_t" Truncate when encountering 0

    string_t[4].decode(new Uint8Array([0x61, 0x62, 0x63, 0x64]); // abcd
    string_t[4].decode(new Uint8Array([0x61, 0x62, 0x00, 0x64]); // ab

    bits

    import { DWORD, bits, StructBuffer } from "struct-buffer";
    
    const EFLAG_DATA = 0x00000246;
    const littleEndian = true;
    const EFLAG = bits(DWORD, {
      CF: 0,
      PF: 2,
      AF: 4,
      ZF: 6,
      SF: 7,
      TF: 8,
      IF: 9,
      DF: 10,
      OF: 11,
    });
    
    // decode
    const data = EFLAG.decode(new Uint32Array([EFLAG_DATA]), littleEndian);
    // => { CF: 0, PF: 1, AF: 0, ZF: 1, SF: 0, TF: 0, IF: 1, DF: 0, OF: 0 }
    
    // encode
    const view = EFLAG.encode(
      {
        PF: 1,
        ZF: 1,
        IF: 1,
      },
      littleEndian
    );
    // => <44 02 00 00>

    bitFields

    import { uint8_t, bitFields, StructBuffer, sbytes as b, } from "struct-buffer";
    
    const bf = bitFields(uint8_t, {
      a: 1,
      b: 2,
      c: 3,
    });
    
    const v = bf.encode({
      a: 1,
      b: 2,
      c: 3,
    });
    // => <1D>
    
    const data = bf.decode(b("1D"));
    // => { a: 1, b: 2, c: 3 }

    pack and unpack

    import { pack, pack_into, unpack, unpack_from, iter_unpack, calcsize, Struct, sbytes as b } from "struct-buffer";
    
    pack("b2xb", 2, 1)
    // => <02 00 00 01>
    
    unpack("b2xb", b("02 00 00 01"))
    // => [ 2, 1 ]
    
    calcsize("hhl")
    // => 8
    
    
    const [hp, mp, name] = unpack(
      ">II3s",
      b("00 00 00 64 00 00 00 0A 61 62 63")
    );
    expect(hp).toBe(100);
    expect(mp).toBe(10);
    expect(name).toBe('abc');

    Note: Without "@, =, P", the default byte order is ">"

    Some utility functions

    import { createDataView, makeDataView, sbytes as b, sbytes2 as b2, sview, TEXT } from "struct-buffer";
    
    createDataView(3)
    // => <00 00 00>
    
    makeDataView([1, 2, 3])
    // => <01 02 03>
    
    b("01 02 03")
    // => <01 02 03>
    
    b2("abc\\x1\\x2\\x3")
    // => <61 62 63 01 02 03>
    
    TEXT(pack("3s2b3s2I", "abc", 1, 2, "xyz", 8, 9))
    // => "abc..xyz........"

    test

    $ npm test

    build

    $ npm run build

    See also:

    Install

    npm i struct-buffer

    DownloadsWeekly Downloads

    19

    Version

    5.1.3

    License

    MIT

    Unpacked Size

    162 kB

    Total Files

    58

    Last publish

    Collaborators

    • ajanuw