Skip to content

Commit

Permalink
Merge changes resulting in v0.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
pabigot committed Nov 23, 2015
2 parents a369e1e + e872fd0 commit f891f5a
Show file tree
Hide file tree
Showing 5 changed files with 736 additions and 223 deletions.
94 changes: 81 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ Layout support is provided for these types of data:
* Signed and unsigned integral values from 1 to 6 bytes in length, in
little-endian or big-endian format;
* Float and double values (also little-endian or big-endian);
* Sequences of instances of an arbitrary layout;
* Structures with named fields containing arbitrary layouts;
* Sequences of up to a fixed number of instances of an arbitrary layout
* Bit fields within 8, 16, 24, or 32-bit unsigned integers, numbering
from the least or most significant bit;
* Unions of variant layouts where the type of data is recorded in a
prefix value, another layout element, or provided externally;
* Blobs of fixed length raw data.
* Bit fields within 8, 16, 24, or 32-bit unsigned integers, numbering
from the least or most significant bit;
* NUL-terminated C strings;
* Blobs of fixed or variable-length raw data.

## Installation

Expand All @@ -33,7 +34,6 @@ All examples are from the `test/examples.js` unit test and assume the
following context:

var assert = require("assert"),
_ = require("lodash"),
lo = require("buffer-layout");

The examples give only a taste of what can be done. Structures, unions,
Expand All @@ -56,7 +56,7 @@ The buffer-layout way:
b = new Buffer(8);
ds.encode([1, -1, 3, -3], b);
assert.equal(Buffer('0100ffff0300fdff', 'hex').compare(b), 0);
assert(_.isEqual(ds.decode(b), [1, -1, 3, -3]));
assert.deepEqual(ds.decode(b), [1, -1, 3, -3]);

See [Int](http://pabigot.github.io/buffer-layout/module-Layout-Int.html)
and [Sequence](http://pabigot.github.io/buffer-layout/module-Layout-Sequence.html).
Expand All @@ -79,7 +79,7 @@ The buffer-layout way:
b.fill(0xbd);
ds.encode({v:1, u32: 0x12345678}, b);
assert.equal(Buffer('01bdbdbd78563412', 'hex').compare(b), 0);
assert(_.isEqual(ds.decode(b), {v: 1, u32: 0x12345678}));
assert.deepEqual(ds.decode(b), {v: 1, u32: 0x12345678});

Note that the C language requires padding which must be explicitly added
in the buffer-layout structure definition. Since the padding is not
Expand All @@ -105,7 +105,7 @@ The buffer-layout way:
b.fill(0xbd);
ds.encode({v:1, u32: 0x12345678}, b);
assert.equal(Buffer('0178563412', 'hex').compare(b), 0);
assert(_.isEqual(ds.decode(b), {v: 1, u32: 0x12345678}));
assert.deepEqual(ds.decode(b), {v: 1, u32: 0x12345678});

### A tagged union of 4-byte values

Expand All @@ -130,9 +130,9 @@ The buffer-layout way:
s16 = un.addVariant('h'.charCodeAt(0), lo.seq(lo.s16(), 2), 's16'),
f32 = un.addVariant('f'.charCodeAt(0), lo.f32(), 'f32'),
b = new Buffer(un.span);
assert(_.isEqual(un.decode(Buffer('7778563412', 'hex')), { u32: 0x12345678 }));
assert(_.isEqual(un.decode(Buffer('660000bd41', 'hex')), { f32: 23.625 }));
assert(_.isEqual(un.decode(Buffer('a5a5a5a5a5', 'hex')), { t: 0xa5, u8:[ 0xa5, 0xa5, 0xa5, 0xa5 ]}));
assert.deepEqual(un.decode(Buffer('7778563412', 'hex')), { u32: 0x12345678 });
assert.deepEqual(un.decode(Buffer('660000bd41', 'hex')), { f32: 23.625 });
assert.deepEqual(un.decode(Buffer('a5a5a5a5a5', 'hex')), { t: 0xa5, u8:[ 0xa5, 0xa5, 0xa5, 0xa5 ]});
s16.encode({s16:[123, -123]}, b);
assert.equal(Buffer('687b0085ff', 'hex').compare(b), 0);

Expand Down Expand Up @@ -160,7 +160,7 @@ The buffer-layout way:
b.fill(0xff);
ds.encode({b00l03:3, b04l18:24, b1Cl04:4}, b);
assert.equal(Buffer('8b010040', 'hex').compare(b), 0);
assert(_.isEqual(ds.decode(b), {b00l03:3, b03l01:1, b04l18:24, b1Cl04:4}));
assert.deepEqual(ds.decode(b), {b00l03:3, b03l01:1, b04l18:24, b1Cl04:4});

See [BitStructure](http://pabigot.github.io/buffer-layout/module-Layout-BitStructure.html).

Expand Down Expand Up @@ -207,6 +207,74 @@ The buffer-layout way:
var span = st.getSpan(b);
assert.equal(span, 20);
assert.equal(Buffer('036b31007631006b32007632006b330065746300', 'hex').compare(b.slice(0, span)), 0);
assert(_.isEqual(st.decode(b), { n:3, a:arr}));
assert.deepEqual(st.decode(b), { n:3, a:arr});

See [OffsetLayout](http://pabigot.github.io/buffer-layout/module-Layout-OffsetLayout.html).

### Tagged values, or variable-length unions

Storing arbitrary date using a leading byte to identify the content then
a value that takes up only as much room as is necessary.

The example also shows how to extend the variant recognition API to
support abitrary constant without consuming space for them in the
encoded union. This could be used to make something similar to
[BSON](http://bsonspec.org/spec.html).

Here's the code that defines the union, the variants, and the
recognition of `true` and `false` values for `b` as distinct variants:

var un = lo.union(lo.u8('t')),
u8 = un.addVariant('B'.charCodeAt(0), lo.u8(), 'u8'),
s16 = un.addVariant('h'.charCodeAt(0), lo.s16(), 's16'),
s48 = un.addVariant('Q'.charCodeAt(0), lo.s48(), 's48'),
cstr = un.addVariant('s'.charCodeAt(0), lo.cstr(), 'str'),
tr = un.addVariant('T'.charCodeAt(0), lo.const(true), 'b'),
fa = un.addVariant('F'.charCodeAt(0), lo.const(false), 'b'),
b = new Buffer(1+6);
un.configGetSourceVariant(function (src) {
if (src.hasOwnProperty('b')) {
return src.b ? tr : fa;
}
return this.defaultGetSourceVariant(src);
});

And here are examples of encoding, checking the encoded length, and
decoding each of the alternatives:

b.fill(0xff);
un.encode({u8: 1}, b);
assert.equal(un.getSpan(b), 2);
assert.equal(Buffer('4201ffffffffff', 'hex').compare(b), 0);
assert.equal(un.decode(b).u8, 1);

b.fill(0xff);
un.encode({s16: -32000}, b);
assert.equal(un.getSpan(b), 3);
assert.equal(Buffer('680083ffffffff', 'hex').compare(b), 0);
assert.equal(un.decode(b).s16, -32000);

b.fill(0xff);
var v48 = Math.pow(2, 47) - 1;
un.encode({s48: v48}, b);
assert.equal(un.getSpan(b), 7);
assert.equal(Buffer('51ffffffffff7f', 'hex').compare(b), 0);
assert.equal(un.decode(b).s48, v48);

b.fill(0xff);
un.encode({b: true}, b);
assert.equal(un.getSpan(b), 1);
assert.equal(Buffer('54ffffffffffff', 'hex').compare(b), 0);
assert.strictEqual(un.decode(b).b, true);

b.fill(0xff);
un.encode({b: false}, b);
assert.equal(un.getSpan(b), 1);
assert.equal(Buffer('46ffffffffffff', 'hex').compare(b), 0);
assert.strictEqual(un.decode(b).b, false);


**NOTE** This code tickles a long-standing [bug in
Buffer.writeInt{L,B}E](https://github.com/nodejs/node/pull/3994). `buffer-layout`
patches `Buffer` to fix the bug if it detects that the running Node has
has the error.
Loading

0 comments on commit f891f5a

Please sign in to comment.