Socket
Socket
Sign inDemoInstall

bitsyntax

Package Overview
Dependencies
1
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.2 to 0.0.3

.travis.yml

8

index.js
module.exports.parse = require('./lib/parse').parse;
module.exports.match = require('./lib/interp').match;
module.exports.compile = require('./lib/compile').compile;
module.exports.construct = require('./lib/constructor').construct;
module.exports.build = require('./lib/constructor').build;
module.exports.write = require('./lib/constructor').write;
module.exports.constructor = require('./lib/constructor').constructor;
module.exports.matcher = module.exports.compile =
require('./lib/compile').compile;
module.exports.builder = require('./lib/compile').compile_builder;
// Compile patterns to recognisers
require('buffer-more-ints');
var $ = require('util').format;

@@ -9,9 +10,23 @@ var parse = require('./parse').parse;

parse_float = interp.parse_float;
var construct = require('./constructor'),
write_int = construct.write_int,
write_float = construct.write_float;
var lines = [];
function $start() {
lines = [];
}
function $line(/* format , args */) {
lines.push($.apply(null, arguments));
}
function $result() {
return lines.join('\n');
}
function bits_expr(segment) {
if (typeof segment.size === 'string') {
return var_name(segment.size) + " * " + segment.unit;
return $('%s * %d', var_name(segment.size), segment.unit);
}
else {
return segment.size * segment.unit;
return (segment.size * segment.unit).toString();
}

@@ -21,23 +36,24 @@ }

function get_number(segment) {
var expr = "bits = " + bits_expr(segment) + ";\n";
var parser = (segment.type === 'integer') ? 'parse_int' : 'parse_float';
$line('bits = %s;\n', bits_expr(segment));
var parser = (segment.type === 'integer') ?
'parse_int' : 'parse_float';
var be = segment.bigendian, sg = segment.signed;
return expr +
"byteoffset = offset / 8; offset += bits\n" +
"if (offset > binsize) { return false; }\n" +
"else { result = " + parser +
"(bin, byteoffset, bits, " + be + ", " + sg + "); }\n";
$line("byteoffset = offset / 8; offset += bits");
$line("if (offset > binsize) { return false; }");
$line("else { result = %s(bin, byteoffset, bits / 8, %s, %s); }",
parser, be, sg);
}
function get_binary(segment) {
var expr = "byteoffset = offset / 8;\n";
$line("byteoffset = offset / 8;");
if (segment.size === true) {
return expr + "offset = binsize;\n" +
"result = bin.slice(byteoffset);\n";
$line("offset = binsize;");
$line("result = bin.slice(byteoffset);");
}
else {
expr += "bits = " + bits_expr(segment) + ";\n";
expr += "offset += bits;\n";
return expr + "if (offset > binsize) { return false; }\n" +
"else { result = bin.slice(byteoffset, byteoffset + bits / 8); }\n";
$line("bits = %s;", bits_expr(segment));
$line("offset += bits;");
$line("if (offset > binsize) { return false; }");
$line("else { result = bin.slice(byteoffset,",
"byteoffset + bits / 8); }");
}

@@ -47,8 +63,9 @@ }

function get_string(segment) {
var expr = "byteoffset = offset / 8;\n";
$line("byteoffset = offset / 8;");
var strlen = segment.value.length;
var strlenbits = strlen * 8;
expr += "offset += " + strlenbits + ";\n";
return expr + "if (offset > binsize) { return false; }\n" +
"else { result = bin.toString(byteoffset, byteoffset + " + strlen + "); }\n";
$line("offset += %d;", strlenbits);
$line("if (offset > binsize) { return false; }");
$line("else { result = bin.toString(byteoffset,",
$("byteoffset + %d); }", strlen));
}

@@ -59,16 +76,15 @@

// Damn. Have to look up the size.
var lookup = "var skipbits = " + var_name(segment.size) +
" * " + segment.unit + ";\n";
var test = "if (offset + skipbits > binsize) { return false; }\n" +
"else { offset += skipbits; }\n";
return lookup + test;
$line("var skipbits = %s * %d;",
var_name(segment.size), segment.unit);
$line("if (offset + skipbits > binsize) { return false; }");
$line("else { offset += skipbits; }");
}
else if (segment.size === true) {
return "if (offset % 8 === 0) { offset = binsize; }\n" +
"else { return false; }\n";
$line("if (offset % 8 === 0) { offset = binsize; }");
$line("else { return false; }");
}
else {
var bits = segment.unit * segment.size;
return "if (offset + " + bits + " > binsize) { return false; }\n" +
"else { offset += " + bits + "; }\n";
$line("if (offset + %d > binsize) { return false; }", bits);
$line("else { offset += %d; }", bits);
}

@@ -79,3 +95,3 @@ }

if (segment.name === '_') {
return skip_bits(segment);
skip_bits(segment);
}

@@ -87,20 +103,19 @@ else {

case 'float':
assign_result = get_number(segment);
get_number(segment);
break;
case 'binary':
assign_result = get_binary(segment);
get_binary(segment);
break;
case 'string':
assign_result = get_string(segment);
get_string(segment);
break;
}
var handle_result = "if (result === false) { return false; }\n";
$line("if (result === false) { return false; }");
if (segment.name) {
handle_result += "else { " + var_name(segment.name) + " = result; }\n";
$line("else { %s = result; }", var_name(segment.name));
}
else {
var repr = JSON.stringify(segment.value);
handle_result += "else if (result != " + repr + ") { return false; }\n";
$line("else if (result != %s) { return false; }", repr);
}
return assign_result + handle_result;
}

@@ -114,24 +129,22 @@ }

function variables(segments) {
var names = [];
var names = {};
for (var i = 0; i < segments.length; i++) {
name = segments[i].name;
if (name && name !== '_') {
names.push(name);
names[name] = true;
}
name = segments[i].size;
if (typeof name === 'string') {
names.push(name);
names[name] = true;
}
}
return names;
return Object.keys(names);
}
function compile_pattern(segments) {
var len = segments.length;
var func =
"return function(binary, vars) {\n" +
"var bin = binary, scope = vars || {};\n" +
"var offset = 0, binsize = bin.length * 8;\n" +
"var bits, result, byteoffset;\n";
$start();
$line("return function(binary, vars) {");
$line("var bin = binary, scope = vars || {};");
$line("var offset = 0, binsize = bin.length * 8;");
$line("var bits, result, byteoffset;");
var varnames = variables(segments);

@@ -141,26 +154,155 @@ var bindings = "";

var name = varnames[v];
func += "var " + var_name(name) + " = scope['" + name + "'];\n";
bindings += "bindings['" + name + "'] = " + var_name(name) + ";\n";
$line("var %s = scope['%s'];", var_name(name), name);
}
var len = segments.length;
for (var i = 0; i < len; i++) {
var segment = segments[i];
func += "// " + JSON.stringify(segment) + "\n";
func += match_seg(segment);
$line("// " + JSON.stringify(segment));
match_seg(segment);
}
func += "if (offset == binsize) {\n" +
"var bindings = {};\n" + bindings +
"return bindings; }\n";
func += "else { return false; }\n";
func += "}\n";
$line("if (offset == binsize) {");
$line("var bindings = {");
for (var v = 0; v < varnames.length; v++) {
var name = varnames[v];
$line("%s: %s,", name, var_name(name));
}
$line('}');
$line("return bindings; }");
$line("else { return false; }");
$line("}"); // end function
return new Function('parse_int', 'parse_float', func)(parse_int, parse_float);
var fn = new Function('parse_int', 'parse_float', $result());
return fn(parse_int, parse_float);
}
function write_seg(segment) {
switch (segment.type) {
case 'string':
$line("offset += buf.write(%s, offset, 'utf8');",
JSON.stringify(segment.value));
break;
case 'binary':
$line("val = bindings['%s'];", segment.name);
if (segment.size === true) {
$line('size = val.length;');
}
else if (typeof segment.size === 'string') {
$line("size = (bindings['%s'] * %d) / 8;",
segment.size, segment.unit);
}
else {
$line("size = %d;", (segment.size * segment.unit) / 8);
}
$line('val.copy(buf, offset, 0, size);');
$line('offset += size;');
break;
case 'integer':
case 'float':
write_number(segment);
break;
}
}
function write_number(segment) {
if (segment.name) {
$line("val = bindings['%s'];", segment.name);
}
else {
$line("val = %d", segment.value);
}
var writer = (segment.type === 'integer') ?
'write_int' : 'write_float';
if (typeof segment.size === 'string') {
$line("size = (bindings['%s'] * %d) / 8;",
segment.size, segment.unit);
}
else {
// could do this statically of course
$line('size = %d;', (segment.size * segment.unit) / 8);
}
$line('%s(buf, val, offset, size, %s);',
writer, segment.bigendian);
$line('offset += size;');
}
function size_of(segments) {
var variable = [];
var fixed = 0;
for (var i = 0; i < segments.length; i++) {
var segment = segments[i];
if (typeof segment.size === 'string' ||
segment.size === true) {
variable.push(segment);
}
else if (segment.type === 'string') {
fixed += Buffer.byteLength(segment.value);
}
else {
fixed += (segment.size * segment.unit) / 8;
}
}
$line('var buffersize = %d;', fixed);
if (variable.length > 0) {
for (var j = 0; j < variable.length; j++) {
var segment = variable[j];
if (segment.size === true) {
$line("buffersize += bindings['%s'].length;", segment.name);
}
else {
$line("buffersize += (bindings['%s'] * %d) / 8;",
segment.size, segment.unit);
}
}
}
}
function compile_write(segments) {
$start();
$line('return function(buf, offset, bindings) {');
$line('var val, size;');
var len = segments.length;
for (var i = 0; i < len; i++) {
var segment = segments[i];
$line('// %s', JSON.stringify(segment));
write_seg(segment);
}
$line('return offset;');
$line('}'); // end function
var fn = new Function('write_int', 'write_float', $result());
return fn(write_int, write_float);
}
function compile_ctor(segments) {
var writer = compile_write(segments);
$start();
$line('return function(bindings) {');
size_of(segments);
$line('var buf = new Buffer(buffersize);');
$line('write(buf, 0, bindings);');
$line('return buf;');
$line('}'); // end function
return new Function('write', $result())(writer);
}
module.exports.compile_pattern = compile_pattern;
module.exports.compile = function(str) {
str = (arguments.length > 1) ? [].join.call(arguments, ',') : str;
module.exports.compile = function() {
var str = [].join.call(arguments, ',');
var p = parse(str);
return compile_pattern(p);
};
module.exports.compile_write = compile_write;
module.exports.compile_builder = function() {
var str = [].join.call(arguments, ',');
var p = parse(str);
return compile_ctor(p);
};

@@ -5,2 +5,4 @@ // -*- js-indent-level: 2 -*-

var ints = require('buffer-more-ints');
// Interpret the pattern, writing values into a buffer

@@ -10,23 +12,15 @@ function write(buf, offset, pattern, bindings) {

var segment = pattern[i];
switch (segment.type) {
case 'string':
var str = segment.value;
buf.write(str, offset);
offset += Buffer.byteLength(str);
offset += buf.write(segment.value, offset, 'utf8');
break;
case 'binary':
// must be a variable reference
var bin = bindings[segment.name];
var size = segment.size;
size = (size === true) ? bin.length : size;
bin.copy(buf, offset, 0, size);
offset += size;
offset += writeBinary(segment, buf, offset, bindings);
break;
case 'integer':
writeInteger(segment, buf, offset, bindings);
offset += (segment.size * segment.unit) / 8;
offset += writeInteger(segment, buf, offset, bindings);
break;
case 'float':
writeFloat(segment, buf, offset, bindings);
offset += (segment.size * segment.unit) / 8;
offset += writeFloat(segment, buf, offset, bindings);
break;

@@ -38,3 +32,3 @@ }

function construct(pattern, bindings) {
function build(pattern, bindings) {
var bufsize = size_of(pattern, bindings);

@@ -46,2 +40,18 @@ var buf = new Buffer(bufsize);

// In bytes
function size_of_segment(segment, bindings) {
// size refers to a variable
if (typeof segment.size === 'string') {
return (bindings[segment.size] * segment.unit) / 8;
}
if (segment.type === 'string') {
return Buffer.byteLength(segment.value, 'utf8');
}
if (segment.type === 'binary' && segment.size === true) {
var val = bindings[segment.name];
return val.length;
}
return (segment.size * segment.unit) / 8;
}
// size of the to-be-constructed binary, in bytes

@@ -51,13 +61,3 @@ function size_of(segments, bindings) {

for (var i=0, len = segments.length; i < len; i++) {
var segment = segments[i];
if (segment.type === 'string') {
size += segment.value.length; // FIXME encoding
}
else if (segment.size === true) {
var val = bindings[segment.name];
size += val.length;
}
else {
size += (segment.size * segment.unit) / 8;
}
size += size_of_segment(segments[i], bindings);
}

@@ -67,2 +67,9 @@ return size;

function writeBinary(segment, buf, offset, bindings) {
var bin = bindings[segment.name];
var size = size_of_segment(segment, bindings);
bin.copy(buf, offset, 0, size);
return size;
}
// TODO in ff might use the noAssert argument to Buffer.write*() but

@@ -73,21 +80,25 @@ // need to check that it does the right thing wrt little-endian

var value = (segment.name) ? bindings[segment.name] : segment.value;
var size = segment.size * segment.unit;
var size = size_of_segment(segment, bindings);
return write_int(buf, value, offset, size, segment.bigendian);
}
function write_int(buf, value, offset, size, bigendian) {
switch (size) {
case 8:
case 1:
buf.writeUInt8(value, offset);
break;
case 16:
(segment.bigendian) ?
case 2:
(bigendian) ?
buf.writeUInt16BE(value, offset) :
buf.writeUInt16LE(value, offset);
break;
case 32:
(segment.bigendian) ?
case 4:
(bigendian) ?
buf.writeUInt32BE(value, offset) :
buf.writeUInt32LE(value, offset);
break;
case 64:
(segment.bigendian) ?
buf.writeUInt64BE(value, offset) :
buf.writeUInt64LE(value, offset);
case 8:
(bigendian) ?
ints.writeUInt64BE(buf, value, offset) :
ints.writeUInt64LE(buf, value, offset);
break;

@@ -97,2 +108,3 @@ default:

}
return size;
}

@@ -102,10 +114,14 @@

var value = (segment.name) ? bindings[segment.name] : segment.value;
var size = segment.size * segment.unit;
if (size === 32) {
(segment.bigendian) ?
var size = size_of_segment(segment, bindings);
return write_float(buf, value, offset, size, segment.bigendian);
}
function write_float(buf, value, offset, size, bigendian) {
if (size === 4) {
(bigendian) ?
buf.writeFloatBE(value, offset) :
buf.writeFloatLE(value, offset);
}
else if (size === 64) {
(segment.bigendian) ?
else if (size === 8) {
(bigendian) ?
buf.writeDoubleBE(value, offset) :

@@ -117,2 +133,3 @@ buf.writeDoubleLE(value, offset);

}
return size;
}

@@ -123,9 +140,12 @@

module.exports.write = write;
module.exports.construct = construct;
module.exports.constructor = function(pstr) {
module.exports.build = build;
module.exports.write_int = write_int;
module.exports.write_float = write_float;
module.exports.builder = function(pstr) {
pstr = (arguments.length > 1) ? [].join.call(arguments, ',') : pstr;
var pattern = parse(pstr);
return function(vars) {
return exports.construct(pattern, vars);
return build(pattern, vars);
};
};

@@ -34,3 +34,3 @@ // -*- js-indent: 2 -*-

require('buffer-more-ints');
var ints = require('buffer-more-ints');

@@ -40,17 +40,28 @@ var debug = (process.env.DEBUG) ?

function parse_int(bin, off, sizeinbits, bigendian, signed) {
var sizeInBytes = sizeinbits / 8;
if (bigendian) {
return (signed) ? bin.readIntBE(sizeInBytes, off) : bin.readUIntBE(sizeInBytes, off);
function parse_int(bin, off, sizeInBytes, bigendian, signed) {
switch (sizeInBytes) {
case 1:
return (signed) ? bin.readInt8(off) : bin.readUInt8(off);
case 2:
return (bigendian) ?
(signed) ? bin.readInt16BE(off) : bin.readUInt16BE(off) :
(signed) ? bin.readInt16LE(off) : bin.readUInt16LE(off);
case 4:
return (bigendian) ?
(signed) ? bin.readInt32BE(off) : bin.readUInt32BE(off) :
(signed) ? bin.readInt32LE(off) : bin.readUInt32LE(off);
case 8:
return (bigendian) ?
((signed) ? ints.readInt64BE : ints.readUInt64BE)(bin, off) :
((signed) ? ints.readInt64LE : ints.readUInt64LE)(bin, off);
default:
throw "Integers must be 8-, 16-, 32- or 64-bit";
}
else {
return (signed) ? bin.readIntLE(sizeInBytes, off) : bin.readUIntLE(sizeInBytes, off);
}
}
function parse_float(bin, off, sizeinbits, bigendian) {
switch (sizeinbits) {
case 32:
function parse_float(bin, off, sizeInBytes, bigendian) {
switch (sizeInBytes) {
case 4:
return (bigendian) ? bin.readFloatBE(off) : bin.readFloatLE(off);
case 64:
case 8:
return (bigendian) ? bin.readDoubleBE(off) : bin.readDoubleLE(off);

@@ -125,3 +136,3 @@ default:

else {
return parse_int(binary, byteoffset, bitsize,
return parse_int(binary, byteoffset, bitsize / 8,
segment.bigendian, segment.signed);

@@ -141,3 +152,4 @@ }

else {
return parse_float(binary, byteoffset, bitsize, segment.bigendian);
return parse_float(binary, byteoffset,
bitsize / 8, segment.bigendian);
}

@@ -144,0 +156,0 @@ }

// Parse patterns in string form into the form we use for interpreting
// (and later, for compiling).
var peg = require('pegjs'),
ast = require('./pattern'),
path = require('path');
var ast = require('./pattern');
var parser = require('./parser');
var grammar = require('fs').readFileSync(
path.join(path.dirname(module.filename), 'grammar.pegjs')).toString();
var parser = peg.buildParser(grammar);
function parse_pattern(string) {

@@ -32,5 +27,5 @@ var segments = parser.parse(string);

module.exports.parse = function(str) {
str = (arguments.length > 1) ? [].join.call(arguments, ',') : str;
module.exports.parse = function() {
var str = [].join.call(arguments, ',');
return parse_pattern(str);
};

@@ -8,3 +8,3 @@ {

"description": "Pattern-matching on byte buffers",
"version": "0.0.2",
"version": "0.0.3",
"repository": {

@@ -16,3 +16,4 @@ "type": "git",

"scripts": {
"test": "make test"
"test": "make test",
"prepublish": "make all"
},

@@ -23,6 +24,8 @@ "engines": {

"dependencies": {
"pegjs": "~0.7",
"buffer-more-ints": ""
"buffer-more-ints": "0.0.2"
},
"devDependencies": {}
"devDependencies": {
"pegjs": "0.7.x",
"mocha": "0.9.x"
}
}
# Byte-wise matching for Node.JS
[![Build Status](https://travis-ci.org/squaremo/bitsyntax-js.png?branch=master)](https://travis-ci.org/squaremo/bitsyntax-js)
Gives a compact syntax for parsing and constructing byte buffers,

@@ -7,7 +9,9 @@ derived from [Erlang's bit

var bitsyntax = require('bitsyntax');
var pattern = bitsyntax.compile('len:8/integer, string:len/binary');
var bound = pattern(new Buffer([4, 0x41, 0x42, 0x43, 0x44]));
bound.string
// => <Buffer 41 42 43 44>
```js
var bitsyntax = require('bitsyntax');
var pattern = bitsyntax.matcher('len:8/integer, str:len/binary');
var bound = pattern(new Buffer([4, 0x41, 0x42, 0x43, 0x44]));
bound.str
// => <Buffer 41 42 43 44>
```

@@ -17,20 +21,25 @@ A typical use of this is parsing byte streams from sockets. For

var framePattern = bitsyntax.compile('len:32/integer, frame:len/binary, rest/binary');
socket.on('data', function process(data) {
var m;
if (m = framePattern(data)) {
emit('frame', m.frame);
process(m.rest);
}
else {
stashForNextData(data);
}
});
```js
var framePattern = bitsyntax.matcher('len:32/integer, frame:len/binary, rest/binary');
socket.on('data', function process(data) {
var m;
if (m = framePattern(data)) {
emit('frame', m.frame);
process(m.rest);
}
else {
stashForNextData(data);
}
});
```
Patterns can also be used to construct binaries from supplied values:
Patterns can also be used to construct byte buffers from supplied
values:
var spdyDataFrame = require('bitsyntax')
.constructor('streamId:32, flags:8, length:24, data/binary');
```js
var spdyDataFrame = require('bitsyntax')
.builder('streamId:32, flags:8, length:24, data/binary');
spdyDataFrame({streamId:5, flags:0, length:bin.length, data:bin});
spdyDataFrame({streamId:5, flags:0, length:bin.length, data:bin});
```

@@ -41,37 +50,53 @@ One or more segments of a pattern may also be supplied in multiple

var p = bitsyntax.compile('size:8, payload:size/binary',
'rest/binary');
```js
var p = bitsyntax.matcher('size:8, payload:size/binary',
'rest/binary');
```
## API
### `compile`
### `matcher`
Compiles a pattern to a function that will return either a map of
bindings, or `false`, given a buffer and optionally an
environment. The environment contains values for the bound variables
in the pattern (if there are any).
Compiles a pattern as a string (or strings), to a function that will
return either a map of bindings, or `false`, given a buffer and
optionally an environment. The environment contains values for the
bound variables in the pattern (if there are any).
var p = bitsyntax.compile('header:headerSize/binary, rest/binary');
var b = p(new Buffer([1, 2, 3, 4, 5]), {headerSize: 3});
b.header
// => <Buffer 01 02 03>
```js
var p = bitsyntax.matcher('header:headerSize/binary, rest/binary');
var b = p(new Buffer([1, 2, 3, 4, 5]), {headerSize: 3});
b.header
// => <Buffer 01 02 03>
```
A matcher will return `false` if the supplied buffer does not match
the pattern; for example, if it has too few bytes, or a literal is not
present.
```js
var p = bitsyntax.matcher('"foo:", str/binary');
p(new Buffer("bar:humbug"));
// => false
```
### `parse` and `match`
In combination, equivalent to `compile`; may be useful if you want to
When composed, equivalent to `matcher`; may be useful if you want to
examine the internal structure of patterns.
`parse` takes strings as for `compile`, and returns the internal
`parse` takes strings as for `matcher`, and returns the internal
representation of the pattern. `match` takes this representation, a
buffer, and optionally an environment, and returns the bindings or
false (as with `compile`).
`false` (as with `matcher`).
var p = bitsyntax.parse('header:headerSize/binary',
'rest/binary');
var b = bitsyntax.match(p, new Buffer([1, 2, 3, 4, 5]),
{headerSize: 3});
b.header
// => <Buffer 01 02 03>
```js
var p = bitsyntax.parse('header:headerSize/binary',
'rest/binary');
var b = bitsyntax.match(p, new Buffer([1, 2, 3, 4, 5]),
{headerSize: 3});
b.header
// => <Buffer 01 02 03>
```
### `constructor`
### `builder`

@@ -81,9 +106,38 @@ Takes a pattern and returns a function that will construct a byte

var cons = bitsyntax.constructor('size:8, bin/binary');
cons({size:6, bin:newBuffer('foobar')});
// => <Buffer 06 66 6f 6f 62 61 72>
```js
var cons = bitsyntax.builder('size:8, bin/binary');
cons({size:6, bin:new Buffer('foobar')});
// => <Buffer 06 66 6f 6f 62 61 72>
```
Patterns supplied to constructors are slightly different to patterns
Patterns supplied to builders are slightly different to patterns
supplied for matching, as noted below.
### `build`
Takes a parsed pattern and a map of variable values, and returns a
buffer. As with `match`, may be useful to debug patterns.
```js
var pattern = bitsyntax.parse('size:8, bin:size/binary');
bitsyntax.build(pattern, {size:6, bin: new Buffer('foobar')});
// => <Buffer 06 66 6f 6f 62 61 72>
```
### `write`
Writes variable values into a buffer, at an offset, according to the
parsed pattern given. Returns the finishing offset, i.e., the supplied
offset plus the number of bytes written.
```js
var pattern = bitsyntax.parse('size:8, bin/binary');
var buf = new Buffer(7);
bitsyntax.write(buf, 0, pattern,
{size:6, bin: new Buffer('foobar')});
// => 7
buf
// => <Buffer 06 66 6f 6f 62 61 72>
```
## Patterns

@@ -116,9 +170,9 @@

In constructors, the literal value will be copied into the result
binary according to the type it is given. A variable name indicates a
space into which a value supplied to the constructor will be copied.
When used in a builder, the literal value will be copied into the
buffer according to the type it is given. A variable name indicates a
slot into which a value supplied to the builder will be copied.
The special variable name `_` discards the value matched; i.e., it
simply skips over the appropriate number of bits in the input. '_' is
not allowed in constructors.
not allowed in builder patterns.

@@ -149,11 +203,12 @@ ### Size and unit

match all remaining bytes in the input; such a segment may only be
used at the end of a pattern.
used at the end of a pattern, when matching.
The size may also be given as an integer variable matched earlier in
the pattern, as in the example given at the top.
the pattern, as in the example given at the top. When constructing, a
size may be a variable referring to the supplied environment.
In constructors, numbers will be rounded, masked or padded to fit the
size and units given; for example, `'256:8'` gives the binary
`Buffer<00>` because the lowest eight bits are 0; `'255:16` gives the
binary `Buffer<00 ff>`.
In builders, numbers will be rounded, masked or padded to fit the size
and units given; for example, `'256:8'` gives the binary `Buffer<00>`
because the lowest eight bits are 0; `'255:16` gives the binary
`Buffer<00 ff>`.

@@ -197,3 +252,3 @@ ### Type name specifier

Signedness is ignored in constructors.
Signedness is ignored in builders.

@@ -210,4 +265,4 @@ ### Literal strings

When used in a constructor, a quoted string is copied verbatim into
the result.
When used in a builder, a quoted string is copied verbatim into the
result.

@@ -214,0 +269,0 @@ ## Examples

var assert = require('assert');
var parse = require('../').parse;
var construct = require('../').construct;
var constructor = require('../').constructor;
var build = require('../').build;
var builder = require('../').builder;
var write = require('../').write;

@@ -15,2 +15,6 @@

['n:8, "foobar", m:8', {n: 255, m:0}, [255, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0]],
['n:8, s:n/binary', {n:6, s: new Buffer('foobar')}, [6, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]],
['n:8, s:n/binary', {n:4, s: new Buffer('foobar')}, [4, 0x66, 0x6f, 0x6f, 0x62]],
['n:size', {n:4, size:8}, [4]],
['206:n/unit:8', {n:1}, [206]]
];

@@ -26,3 +30,3 @@

test(c[0], function() {
assert.deepEqual(c[2], bufferToArray(construct(p, c[1])));
assert.deepEqual(c[2], bufferToArray(build(p, c[1])));
});

@@ -36,3 +40,3 @@ test(c[0], function() {

test(c[0], function() {
var cons = constructor(c[0]);
var cons = builder(c[0]);
var buf = cons(c[1]);

@@ -39,0 +43,0 @@ assert.deepEqual(c[2], bufferToArray(buf));

var match = require('../').match;
var parse = require('../').parse;
var compile = require('../').compile;
var compile = require('../').matcher;
var assert = require('assert');

@@ -5,0 +5,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc