-
Notifications
You must be signed in to change notification settings - Fork 382
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
244 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
var UPPER32 = Math.pow(2, 32); | ||
|
||
var warnedPrecision = false; | ||
function warnPrecision() { | ||
if (!warnedPrecision) { | ||
warnedPrecision = true; | ||
console.warn('CBOR 64-bit integer array values may lose precision. No further warnings.'); | ||
} | ||
} | ||
|
||
/** | ||
* Unpacks 64-bit unsigned integer from byte array. | ||
* @param {Uint8Array} bytes | ||
*/ | ||
function decodeUint64LE(bytes) { | ||
warnPrecision(); | ||
|
||
var byteLen = bytes.byteLength; | ||
var arrLen = byteLen / 8; | ||
|
||
var buffer = bytes.buffer.slice(-byteLen); | ||
var uint32View = new Uint32Array(buffer); | ||
|
||
var arr = new Array(arrLen); | ||
for (var i = 0; i < arrLen; i++) { | ||
var si = i * 2; | ||
var lo = uint32View[si]; | ||
var hi = uint32View[si+1]; | ||
arr[i] = lo + UPPER32 * hi; | ||
} | ||
|
||
return arr; | ||
} | ||
|
||
/** | ||
* Unpacks 64-bit signed integer from byte array. | ||
* @param {Uint8Array} bytes | ||
*/ | ||
function decodeInt64LE(bytes) { | ||
warnPrecision(); | ||
|
||
var byteLen = bytes.byteLength; | ||
var arrLen = byteLen / 8; | ||
|
||
var buffer = bytes.buffer.slice(-byteLen); | ||
var uint32View = new Uint32Array(buffer); | ||
var int32View = new Int32Array(buffer); | ||
|
||
var arr = new Array(arrLen); | ||
for (var i = 0; i < arrLen; i++) { | ||
var si = i * 2; | ||
var lo = uint32View[si]; | ||
var hi = int32View[si+1]; | ||
arr[i] = lo + UPPER32 * hi; | ||
} | ||
|
||
return arr; | ||
} | ||
|
||
/** | ||
* Unpacks typed array from byte array. | ||
* @param {Uint8Array} bytes | ||
* @param {type} ArrayType - desired output array type | ||
*/ | ||
function decodeNativeArray(bytes, ArrayType) { | ||
var byteLen = bytes.byteLength; | ||
var buffer = bytes.buffer.slice(-byteLen); | ||
return new ArrayType(buffer); | ||
} | ||
|
||
/** | ||
* Support a subset of draft CBOR typed array tags: | ||
* <https://tools.ietf.org/html/draft-ietf-cbor-array-tags-00> | ||
* Only support little-endian tags for now. | ||
*/ | ||
var nativeArrayTypes = { | ||
64: Uint8Array, | ||
69: Uint16Array, | ||
70: Uint32Array, | ||
72: Int8Array, | ||
77: Int16Array, | ||
78: Int32Array, | ||
85: Float32Array, | ||
86: Float64Array | ||
}; | ||
|
||
/** | ||
* We can also decode 64-bit integer arrays, since ROS has these types. | ||
*/ | ||
var conversionArrayTypes = { | ||
71: decodeUint64LE, | ||
79: decodeInt64LE | ||
}; | ||
|
||
/** | ||
* Handles CBOR typed array tags during decoding. | ||
* @param {Uint8Array} data | ||
* @param {Number} tag | ||
*/ | ||
function cborTypedArrayTagger(data, tag) { | ||
if (tag in nativeArrayTypes) { | ||
var arrayType = nativeArrayTypes[tag]; | ||
return decodeNativeArray(data, arrayType); | ||
} | ||
if (tag in conversionArrayTypes) { | ||
return conversionArrayTypes[tag](data); | ||
} | ||
return data; | ||
} | ||
|
||
if (typeof module !== 'undefined' && module.exports) { | ||
module.exports = cborTypedArrayTagger; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
var expect = require('chai').expect; | ||
var CBOR = require('cbor-js'); | ||
var cborTypedArrayTagger = require('../src/util/cborTypedArrayTags.js'); | ||
|
||
/** Convert hex string to ArrayBuffer. */ | ||
function hexToBuffer(hex) { | ||
var tokens = hex.match(/[0-9a-fA-F]{2}/gi); | ||
var arr = tokens.map(function(t) { | ||
return parseInt(t, 16); | ||
}); | ||
return new Uint8Array(arr).buffer; | ||
} | ||
|
||
|
||
describe('CBOR Typed Array Tagger', function() { | ||
|
||
it('should convert tagged Uint16Array', function() { | ||
var data = hexToBuffer('d84546010002000300'); | ||
var msg = CBOR.decode(data, cborTypedArrayTagger); | ||
|
||
expect(msg).to.be.a('Uint16Array'); | ||
expect(msg).to.have.lengthOf(3); | ||
expect(msg[0]).to.equal(1); | ||
expect(msg[1]).to.equal(2); | ||
expect(msg[2]).to.equal(3); | ||
}); | ||
|
||
it('should convert tagged Uint32Array', function() { | ||
var data = hexToBuffer('d8464c010000000200000003000000'); | ||
var msg = CBOR.decode(data, cborTypedArrayTagger); | ||
|
||
expect(msg).to.be.a('Uint32Array'); | ||
expect(msg).to.have.lengthOf(3); | ||
expect(msg[0]).to.equal(1); | ||
expect(msg[1]).to.equal(2); | ||
expect(msg[2]).to.equal(3); | ||
}); | ||
|
||
it('should convert tagged Uint64Array', function() { | ||
var data = hexToBuffer('d8475818010000000000000002000000000000000300000000000000'); | ||
var msg = CBOR.decode(data, cborTypedArrayTagger); | ||
|
||
expect(msg).to.be.a('Array'); | ||
expect(msg).to.have.lengthOf(3); | ||
expect(msg[0]).to.equal(1); | ||
expect(msg[1]).to.equal(2); | ||
expect(msg[2]).to.equal(3); | ||
}); | ||
|
||
it('should convert tagged Int8Array', function() { | ||
var data = hexToBuffer('d8484301fe03'); | ||
var msg = CBOR.decode(data, cborTypedArrayTagger); | ||
|
||
expect(msg).to.be.a('Int8Array'); | ||
expect(msg).to.have.lengthOf(3); | ||
expect(msg[0]).to.equal(1); | ||
expect(msg[1]).to.equal(-2); | ||
expect(msg[2]).to.equal(3); | ||
}); | ||
|
||
it('should convert tagged Int16Array', function() { | ||
var data = hexToBuffer('d84d460100feff0300'); | ||
var msg = CBOR.decode(data, cborTypedArrayTagger); | ||
|
||
expect(msg).to.be.a('Int16Array'); | ||
expect(msg).to.have.lengthOf(3); | ||
expect(msg[0]).to.equal(1); | ||
expect(msg[1]).to.equal(-2); | ||
expect(msg[2]).to.equal(3); | ||
}); | ||
|
||
it('should convert tagged Int32Array', function() { | ||
var data = hexToBuffer('d84e4c01000000feffffff03000000'); | ||
var msg = CBOR.decode(data, cborTypedArrayTagger); | ||
|
||
expect(msg).to.be.a('Int32Array'); | ||
expect(msg).to.have.lengthOf(3); | ||
expect(msg[0]).to.equal(1); | ||
expect(msg[1]).to.equal(-2); | ||
expect(msg[2]).to.equal(3); | ||
}); | ||
|
||
it('should convert tagged Int64Array', function() { | ||
var data = hexToBuffer('d84f58180100000000000000feffffffffffffff0300000000000000'); | ||
var msg = CBOR.decode(data, cborTypedArrayTagger); | ||
|
||
expect(msg).to.be.a('Array'); | ||
expect(msg).to.have.lengthOf(3); | ||
expect(msg[0]).to.equal(1); | ||
expect(msg[1]).to.equal(-2); | ||
expect(msg[2]).to.equal(3); | ||
}); | ||
|
||
it('should convert tagged Float32Array', function() { | ||
var data = hexToBuffer('d8554ccdcc8c3fcdcc0cc033335340'); | ||
var msg = CBOR.decode(data, cborTypedArrayTagger); | ||
|
||
expect(msg).to.be.a('Float32Array'); | ||
expect(msg).to.have.lengthOf(3); | ||
expect(msg[0]).to.closeTo(1.1, 1e-5); | ||
expect(msg[1]).to.closeTo(-2.2, 1e-5); | ||
expect(msg[2]).to.closeTo(3.3, 1e-5); | ||
}); | ||
|
||
it('should convert tagged Float64Array', function() { | ||
var data = hexToBuffer('d85658189a9999999999f13f9a999999999901c06666666666660a40'); | ||
var msg = CBOR.decode(data, cborTypedArrayTagger); | ||
|
||
expect(msg).to.be.a('Float64Array'); | ||
expect(msg).to.have.lengthOf(3); | ||
expect(msg[0]).to.closeTo(1.1, 1e-5); | ||
expect(msg[1]).to.closeTo(-2.2, 1e-5); | ||
expect(msg[2]).to.closeTo(3.3, 1e-5); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters