Skip to content

Commit

Permalink
added raw buffer type
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacob Jewell committed Jul 29, 2014
1 parent 1610979 commit 6186d7c
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 54 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
# CHANGELOG

## 0.4.0 (2013-03-26)
- Added default value field

## 0.3.2 (2013-03-24)
- Performance improvements for field encoding, write to the same buffer when encoding fields

Expand Down
63 changes: 36 additions & 27 deletions README.md
Expand Up @@ -35,6 +35,7 @@ The Javascript object specification is used to specify endianness and a descript
{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 }
]
}

Expand All @@ -44,6 +45,7 @@ The Javascript object specification is used to specify endianness and a descript
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
Expand Down Expand Up @@ -74,23 +76,26 @@ All fields must have a name, a starting byte, and a type. The name is used for a
### Example

```javascript
var DecoderRing = require("decoder-ring")
var DecoderRing = require("decoder-ring");
var decoderRing = new DecoderRing();

var bufferBE = new Buffer(47)
bufferBE.fill(0)
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)
var bufferBE = new Buffer(51);
bufferBE.fill(0);
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);

var testBuffer = new Buffer("test");
testBuffer.copy(bufferBE, 47, 0, 4);

var spec = {
bigEndian: true,
Expand All @@ -101,37 +106,39 @@ var spec = {
{ 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: "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: "field14", start: 46, type: 'int8', default: 42 },
{ name: "field15", start: 47, type: 'buffer', length: 4 }
]
}
};

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

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

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

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

Result of the above example

```javascript
{ field1: -127,
{
field1: -127,
field2: 254,
field3: 5327,
field4: 5328,
Expand All @@ -144,7 +151,9 @@ Result of the above example
field11: true,
field12: 79001,
field13: -79001,
field14: 1 }
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>

Expand Down
55 changes: 30 additions & 25 deletions example.js
@@ -1,20 +1,23 @@
var DecoderRing = require("decoder-ring")
var DecoderRing = require("decoder-ring");
var decoderRing = new DecoderRing();

var bufferBE = new Buffer(47)
bufferBE.fill(0)
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)
var bufferBE = new Buffer(51);
bufferBE.fill(0);
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);

var testBuffer = new Buffer("test");
testBuffer.copy(bufferBE, 47, 0, 4);

var spec = {
bigEndian: true,
Expand All @@ -25,28 +28,30 @@ var spec = {
{ 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: "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: "field14", start: 46, type: 'int8', default: 42 },
{ name: "field15", start: 47, type: 'buffer', length: 4 }
]
}
};

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

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

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

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

2 changes: 2 additions & 0 deletions src/FieldDecoder.coffee
Expand Up @@ -11,6 +11,7 @@ class FieldDecoder
when 'double' then buffer.readDoubleBE(fieldSpec.start)
when 'ascii' then buffer.toString('ascii', fieldSpec.start, fieldSpec.start+fieldSpec.length)
when 'utf8' then buffer.toString('utf8', fieldSpec.start, fieldSpec.start+fieldSpec.length)
when 'buffer' then buffer.slice(fieldSpec.start, fieldSpec.start+fieldSpec.length)
when 'bit'
i = buffer.readUInt8(fieldSpec.start)
(i & Math.pow(2, fieldSpec.position)) > 0
Expand All @@ -28,6 +29,7 @@ class FieldDecoder
when 'double' then buffer.readDoubleLE(fieldSpec.start)
when 'ascii' then buffer.toString('ascii', fieldSpec.start, fieldSpec.start+fieldSpec.length)
when 'utf8' then buffer.toString('utf8', fieldSpec.start, fieldSpec.start+fieldSpec.length)
when 'buffer' then buffer.slice(fieldSpec.start, fieldSpec.start+fieldSpec.length)
when 'bit'
i = buffer.readUInt8(fieldSpec.start)
(i & Math.pow(2, fieldSpec.position)) > 0
Expand Down
4 changes: 3 additions & 1 deletion src/FieldEncoder.coffee
Expand Up @@ -13,7 +13,7 @@ class FieldEncoder
when 'int16', 'uint16' then 2
when 'uint32', 'int32', 'float' then 4
when 'double' then 8
when 'ascii', 'utf8' then field.length
when 'ascii', 'utf8', 'buffer' then field.length

return field.start + length

Expand All @@ -36,6 +36,7 @@ class FieldEncoder
when 'utf8' then buffer.write(val, fieldSpec.start, fieldSpec.length, 'utf8')
when 'uint32' then buffer.writeUInt32BE(val, fieldSpec.start)
when 'int32' then buffer.writeInt32BE(val, fieldSpec.start)
when 'buffer' then val.copy(buffer, fieldSpec.start, 0, fieldSpec.length)
when 'bit'
if val is true # protection from type problems
buffer.writeUInt8(Math.pow(2, fieldSpec.position), fieldSpec.start)
Expand Down Expand Up @@ -63,6 +64,7 @@ class FieldEncoder
when 'utf8' then buffer.write(val, fieldSpec.start, fieldSpec.length, 'utf8')
when 'uint32' then buffer.writeUInt32LE(val, fieldSpec.start)
when 'int32' then buffer.writeInt32LE(val, fieldSpec.start)
when 'buffer' then val.copy(buffer, fieldSpec.start, 0, fieldSpec.length)
when 'bit'
if val is true # protection from type problems
buffer.writeUInt8(Math.pow(2, fieldSpec.position), fieldSpec.start)
Expand Down
2 changes: 2 additions & 0 deletions test/DecoderRingIntegrationTest.coffee
Expand Up @@ -28,6 +28,7 @@ describe "BinaryDecoderRing Integration Test", ->
expect(result.field11).to.be.true
expect(result.field12).to.equal(79001)
expect(result.field13).to.equal(-79001)
expect(result.field14).to.eql(new Buffer("test"))

it "decodes little endian specifications", ->
result = @subject.decode(@bufferLE, @bufferLESpec)
Expand All @@ -45,6 +46,7 @@ describe "BinaryDecoderRing Integration Test", ->
expect(result.field11).to.be.true
expect(result.field12).to.equal(79002)
expect(result.field13).to.equal(-79002)
expect(result.field14).to.eql(new Buffer("test"))

describe "#encode", ->
it "encodes big endian specifications", ->
Expand Down
10 changes: 10 additions & 0 deletions test/FieldDecoderUnitTest.coffee
Expand Up @@ -70,6 +70,11 @@ describe "FieldDecoder unit test", ->
result = @subject.decodeFieldBE(@bufferBE, fieldSpec)
expect(result).to.equal(-79001)

it "decodes a buffer field", ->
fieldSpec = {name: "foo", start: 46, type: 'buffer', length: 4}
result = @subject.decodeFieldBE(@bufferBE, fieldSpec)
expect(result).to.eql(new Buffer("test"))


describe "#decodeFieldLE", ->
it "decodes an int8 field", ->
Expand Down Expand Up @@ -127,3 +132,8 @@ describe "FieldDecoder unit test", ->
result = @subject.decodeFieldLE(@bufferLE, fieldSpec)
expect(result).to.equal(-79002)

it "decodes a buffer field", ->
fieldSpec = {name: "foo", start: 46, type: 'buffer', length: 4}
result = @subject.decodeFieldLE(@bufferLE, fieldSpec)
expect(result).to.eql(new Buffer("test"))

33 changes: 32 additions & 1 deletion test/FieldEncoderUnitTest.coffee
Expand Up @@ -215,6 +215,18 @@ describe "FieldEncoder unit test", ->
result = @subject.encodeFieldBE(outBuffer, obj, fieldSpec)
expect(result).to.deep.equal(expectedBuffer)

it "encodes a buffer field", ->
expectedBuffer = new Buffer("testing")

outBuffer = new Buffer(7)
outBuffer.fill(0)

obj = {field8: expectedBuffer}
fieldSpec = {name: "field8", start: 0, type: 'buffer', length: 7}

result = @subject.encodeFieldBE(outBuffer, obj, fieldSpec)
expect(result).to.deep.equal(expectedBuffer)

describe "#encodeFieldLE", ->
it "will use the default default value according to the fieldSpec when property is undefined", ->
expectedBuffer = new Buffer(2)
Expand Down Expand Up @@ -410,6 +422,19 @@ describe "FieldEncoder unit test", ->
result = @subject.encodeFieldLE(outBuffer, obj, fieldSpec)
expect(result).to.deep.equal(expectedBuffer)

it "encodes a buffer field", ->
expectedBuffer = new Buffer("testing")

outBuffer = new Buffer(7)
outBuffer.fill(0)

obj = {field8: expectedBuffer}
fieldSpec = {name: "field8", start: 0, type: 'buffer', length: 7}

result = @subject.encodeFieldLE(outBuffer, obj, fieldSpec)
expect(result).to.deep.equal(expectedBuffer)


describe "#findFieldLength", ->
it "works for int8's", ->
field = {name: "field1", start: 2, type: 'int8' }
Expand Down Expand Up @@ -471,9 +496,15 @@ describe "FieldEncoder unit test", ->
result = @subject.findFieldLength(field)
expect(result).to.equal(3)

it "works for buffers", ->
field = {name: "field1", start: 2, type: 'buffer', length: 3 }

result = @subject.findFieldLength(field)
expect(result).to.equal(5)

describe "#findSpecBufferSize", ->
it "finds the max size of a buffer", ->
result = @subject.findSpecBufferSize(@bufferLESpec)
expect(result).to.equal(46)
expect(result).to.equal(50)


4 changes: 4 additions & 0 deletions test/Fixtures.coffee
Expand Up @@ -10,6 +10,7 @@ bufferBE.write("utf8 text", 28, 9, 'utf8')
bufferBE.writeUInt8(129, 37)
bufferBE.writeUInt32BE(79001, 38)
bufferBE.writeInt32BE(-79001, 42)
bufferBE = Buffer.concat([bufferBE, new Buffer("test")])

bufferLE = new Buffer(46)
bufferLE.writeInt8(-127, 0)
Expand All @@ -23,6 +24,7 @@ bufferLE.write("utf8 text", 28, 9, 'utf8')
bufferLE.writeUInt8(129, 37)
bufferLE.writeUInt32LE(79002, 38)
bufferLE.writeInt32LE(-79002, 42)
bufferLE = Buffer.concat([bufferLE, new Buffer("test")])

bufferBESpec = {
bigEndian: true
Expand All @@ -40,6 +42,7 @@ bufferBESpec = {
{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: 'buffer', length: 4 }
]
}

Expand All @@ -59,6 +62,7 @@ bufferLESpec = {
{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: 'buffer', length: 4 }
]
}

Expand Down

0 comments on commit 6186d7c

Please sign in to comment.