node-structor

0.9.3 • Public • Published

node-structor

Convert binary file data to JavaScript objects

Installation

npm i node-structor

Usage

In the example below we will be reading a list of people from a binary source.

const fs = require('fs');
const Structor = require('node-structor');

const structDef = {
    numPersons: {
        $format: 'byte',
        $ignore: true
    },
    persons: {
        $repeat: 'numPersons',
        $format: {
            firstName: 'string7',
            lastName: 'string7',
            address: {
                city: 'string7',
                street: 'string7',
                number: 'uint16',
                zipCode: 'string7'
            },
            numHobbies: {
                $ignore: true,
                $format: 'byte',
            },
            hobbies: {
                $format: 'string7',
                $repeat: 'numHobbies'
            }
        }
    }
};

let result = Structor.readStruct(structDef, fs.readFileSync('./examples/people.dat'));

console.log(result);

Not that 'string7' is used - this denotes a string that is prepended by the length of that string. Reference.

Running this will log the following:

{
    persons: [
        {
            firstName: 'John',
            lastName: 'A',
            address: {
                city: 'New York',
                street: '1st Ave.',
                number: 1165,
                zipCode: '10065'
            },
            hobbies: [ 'eating', 'coding', 'walking' ]
        },
        {
            firstName: 'Betty',
            lastName: 'B',
            address: {
                city: 'York',
                street: 'Bridge St.',
                number: 1,
                zipCode: 'YO1 6DD'
            },
            hobbies: []
        }
    ]
}

Types

Type Description
byte Unsigned byte (0 to 255)
uint8 Unsigned byte (0 to 255)
sbyte Signed byte (-128 to 127)
int8 Signed byte (-128 to 127)
uint16 16-bit unsigned integer (0 to 65,535)
int16 16-bit signed integer (-32,768 to 32,767)
uint32 32-bit unsigned integer (0 to 4,294,967,295)
int32 32-bit signed integer (-2,147,483,648 to 2,147,483,647)
uint64 64-bit unsigned integer (read as BigInt)
int64 64-bit signed integer (read as BigInt)
char_* A string of charactered with its length defined by the *. e.g. char_28
string A string terminated by a zero (0) byte or, when used with $format, $length and $encoding can be specified
string7 A string of charactered prepended by its 7-bit encoded length
buffer Read $length amount of bytes as a new Buffer

Note: By default the endianness is little-endian (LE) - But you can explicitly define the endianness e.g. int16be, uint64le, etc.

Directives

$format

Define the format.

Examples:

$format: 'uint16'         // Results in a single number
$format: {                // Results in an object
    a: 'byte',
    b: 'byte'
}
$format: ['byte', 'byte'] // Results in an array with two items

$repeat

Repeats the specified $format. Can be a number or the name of a property containing the value.

Examples:

{
    $format: 'byte',
    $repeat: 2
}
{
    numObjects: 'byte',
    objects: {
        $format: {
            ...
        }
        $repeat: 'numObjects'
    }
}

$foreach

A special form of $repeat. Must be a referenced value pointing to a previously read array combined with an alias.

Examples:

{
    numFiles: 'uint16',
    fileTable: {
        $repeat: 'numFiles',
        $format: {
            name: 'string',
            address: 'uint32',
            length: 'uint32'
        }
    },
    files: {
        // Iterate over each item in fileTable as 'file'
        $foreach: 'fileTable file', 
        $format: {
            fileName: {
                $value: 'file.name'
            },
            fileContent: {
                $goto: 'file.address',
                $format: 'buffer',
                $length: 'file.length'
            }
        }
    }
}

$switch

Read the next data differently based on a previously read value.

Examples:

{
    type: 'byte',
    shape: {
        $switch: 'type',
        $cases: [
            {
                $case: 1, // when type is 1, assume circle data follows
                $format: {
                    radius: 'uint32'
                }
            },
            {
                $case: 2, // 2 = square data
                $format: {
                    width: 'uint16',
                    height: 'uint16'
                }
            },
            {
                $case: 3, // 2 = polygonal data
                $format: {
                    numPoints: {
                        $ignore: true,
                        $format: 'byte'
                    },
                    points: {
                        $repeat: 'numPoints',
                        $format: 'byte'
                    }
                }
            }
        ]
    }
}
// Which could result in:
{
    type: 1,
    shape: {
        radius: 38892
    }
},
{
    type: 2,
    shape: {
        width: 96,
        height: 128
    }
},
{
    type: 3,
    shape: {
        points: [0, 2, 128, 24, 255, 8]
    }
}

$ignore

Read the data, but don't put the property in the eventual JS object.

Examples:

numObjects: {
    $format: 'byte',
    $ignore: true
}

$goto

Jumps to the specified byte location before reading the value.

Examples:

signature: {
    $goto: 0xf0,
    $format: 'char_2'    
}

$skip

Skips the specified number of bytes before reading the value.

Examples:

startOfHeader: {
    $skip: 255,
    $format: 'uint16'    
}

$length

Can only be used in conjunction with $format: 'string' and must be used when $format: 'buffer'.

Examples:

firstName: {
    $format: 'string',
    $length: 32
}

Note: when $format is 'string', $length is optional. If not present, characters will be read until a zero-byte is encountered.

blobData: {
    $format: 'buffer',
    $length: 64000
}

$encoding

Can only be used in conjunction with $format: 'string'.

Examples:

firstName: {
    $format: 'string',
    $encoding: 'ascii'
}

Note: the default value for $encoding is 'utf8'

$value

A special directive that doesn't read anything from the buffer and thus doesn't move the internal cursor. Used to copy a value from another source.

{
    name: 'string',
    nameCopy: {
        $value: 'name'
    }
}

Referenced values

Every numeric directive supports passing a reference value string instead of a hard-coded integer. This can be a simple name pointing to a sibling value, or a more complex path.

Examples:

{
    nameLength: 'byte',
    myName: {
        $format: 'string',
        $length: 'nameLength'
    }
}
{
    header: {
        config: {
            nameLength: 'byte'
        }
    },
    myName: {
        $format: 'string',
        $length: 'header.config.nameLength'
    }
}

Directives that support this:

  • $repeat
  • $switch
  • $length
  • $goto
  • $skip
  • $value

Package Sidebar

Install

npm i node-structor

Weekly Downloads

2

Version

0.9.3

License

MIT

Unpacked Size

31.1 kB

Total Files

6

Last publish

Collaborators

  • wiiseguy