npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@eflexsystems/decoder-ring

v6.0.1

Published

Decode binary buffers using a JSON specification

Downloads

43

Readme

node-decoder-ring

Build Status

Decoder Ring allows you to use a Javascript object as a specification to decode Node.js Buffers into a Javascript object.

Installation

npm install decoder-ring

Usage

Javascript Object Specification

The Javascript object specification is used to specify endianness and a description of the fields present in the buffer.

{
    bigEndian: true,
    fields: [
        {name: "field1", start: 0,  type: 'int8'  },
        {name: "field2", start: 1,  type: 'uint8' },
        {name: "field3", start: 2,  type: 'int16' },
        {name: "field4", start: 4,  type: 'uint16'},
        {name: "field5", start: 6,  type: 'float' },
        {name: "field6", start: 10, type: 'double'},
        {name: "field7", start: 18, type: 'ascii', length: 10 },
        {name: "field8", start: 28, type: 'utf8',  length: 9  },
        {name: "field9", start: 37, type: 'bit', position: 7},
        {name: "field10", start: 37, type: 'bit', position: 6},
        {name: "field11", start: 37, type: 'bit', position: 0},
        {name: "field12", start: 38, type: 'uint32'},
        {name: "field13", start: 42, type: 'int32'}
        {name: "field14", start: 46, type: 'int8', default: 42 }
        {name: "field15", start: 50, type: 'buffer', length: 4 }
    ]
}

All fields must have a name, a starting byte, and a type. The name is used for assigning the property in the resulting javascript object. Additionally, fields can have a default value which is used when encoding an object's properties that have null or undefined values.

Types

  • buffer - Raw buffer

  • int8 - Signed 8-bit integer

  • uint8 - Unsigned 8-bit integer

  • int16 - Signed 16-bit integer

  • uint16 - Unsigned 16-bit integer

  • int32 - Signed 32-bit integer

  • uint32 - Unsigned 32-bit integer

  • float - 4-bit floating point number

  • double - 8-bit double precision floating point number

  • ascii - 8-bit per character ASCII encoded text

    This field type must also have a length property which is a count of the number of characters.

  • utf8 - 8-bit per character UTF8 encoded text

    This field type must also have a length property which is a count of the number of characters.

  • bit - true/false values

    Bit fields are pieces of a 1-byte unsigned integer. Given a big endian, unsigned integer of 129, it will appear as the following when broken down into bits:

    | 128(2^7) | 64(2^6) | 32(2^5) | 16(2^4) | 8(2^3) | 4(2^2) | 2(2^1) | 1(2^0) | | :------: | :-----: | :-----: | :-----: | :----: | :----: | :----: | :----: | | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |

    Bit fields must have a position property which is used to check if a specific bit is on or off in the 1-byte unsigned integer. The position of the bit of interest, is defined as which power of two the bit falls in the integer. For the bit in the 128th's place, the position would be 7, for the bit in the 1's place the position would be 0.

API

decode: (buffer, spec)

encode: (obj, spec, { padding = null })

  • set padding to a character to right pad ascii and utf8 strings instead of using null termination

Example

const decoderRing = require("decoder-ring");

const bufferBE = Buffer.alloc(51);
bufferBE.writeInt8(-127, 0);
bufferBE.writeUInt8(254, 1);
bufferBE.writeInt16BE(5327, 2);
bufferBE.writeUInt16BE(5328, 4);
bufferBE.writeFloatBE(-15.33, 6);
bufferBE.writeDoubleBE(-1534.98, 10);
bufferBE.write("ascii", 18, 10, "ascii");
bufferBE.write("utf8 text", 28, 9, "utf8");
bufferBE.writeUInt8(129, 37);
bufferBE.writeUInt32BE(79001, 38);
bufferBE.writeInt32BE(-79001, 42);
bufferBE.writeInt8(1, 46);

let testBuffer = Buffer.from("test");
testBuffer.copy(bufferBE, 47, 0, 4);

let spec = {
  bigEndian: true,
  fields: [
    { name: "field1", start: 0, type: "int8" },
    { name: "field2", start: 1, type: "uint8" },
    { name: "field3", start: 2, type: "int16" },
    { name: "field4", start: 4, type: "uint16" },
    { name: "field5", start: 6, type: "float" },
    { name: "field6", start: 10, type: "double" },
    { name: "field7", start: 18, type: "ascii", length: 10 },
    { name: "field8", start: 28, type: "utf8", length: 9 },
    { name: "field9", start: 37, type: "bit", position: 7 },
    { name: "field10", start: 37, type: "bit", position: 6 },
    { name: "field11", start: 37, type: "bit", position: 0 },
    { name: "field12", start: 38, type: "uint32" },
    { name: "field13", start: 42, type: "int32" },
    { name: "field14", start: 46, type: "int8", default: 42 },
    { name: "field15", start: 47, type: "buffer", length: 4 },
  ],
};

// Decode the buffer into a javascript object
let result = decoderRing.decode(spec, bufferBE);
console.log(result);

// Assign field14 to undefined to test default value on encoding
result.field14 = undefined;

// Encode the object to a buffer
let buffer = decoderRing.encode(spec, result);
console.log(buffer);

// Decode buffer to object and check field14 for default value
let resultWithDefaultValue = decoderRing.decode(spec, buffer);
console.log("Field14 default value: " + resultWithDefaultValue.field14);

Result of the above example

{
  field1: -127,
  field2: 254,
  field3: 5327,
  field4: 5328,
  field5: -15.329999923706055,
  field6: -1534.98,
  field7: 'ascii\u0000\u0000\u0000\u0000\u0000',
  field8: 'utf8 text',
  field9: true,
  field10: false,
  field11: true,
  field12: 79001,
  field13: -79001,
  field14: 1,
  field15: <Buffer 74 65 73 74>
}

<Buffer 81 fe 14 cf 14 d0 c1 75 47 ae c0 97 fb eb 85 1e b8 52 61 73 63 69 69 20 20 20 20 20 75 74 66 38 20 74 65 78 74 81 00 01 34 99 ff fe cb 67 2a>

Field14 42

Development

Running tests

npm test

Testing the package locally

npm pack
npm install decoder-ring-0.4.0.tgz
node example.js