From b6db786098109ae8bc48a5101a8797bb7fff3326 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 31 May 2017 15:42:48 +1200 Subject: [PATCH] Add readUInt64LE and writeUInt64LE from bitcoinjs-lib --- src/bufferutils.js | 34 +++++++++++++++ test/bufferutils.js | 50 ++++++++++++++++++++++ test/fixtures/bufferutils.json | 76 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 src/bufferutils.js create mode 100644 test/bufferutils.js create mode 100644 test/fixtures/bufferutils.json diff --git a/src/bufferutils.js b/src/bufferutils.js new file mode 100644 index 0000000..87a5454 --- /dev/null +++ b/src/bufferutils.js @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2011-2016 bitcoinjs-lib contributors + */ + +// https://github.com/feross/buffer/blob/master/index.js#L1127 +function verifuint (value, max) { + if (typeof value !== 'number') throw new Error('cannot write a non-number as a number') + if (value < 0) throw new Error('specified a negative value for writing an unsigned value') + if (value > max) throw new Error('RangeError: value out of range') + if (Math.floor(value) !== value) throw new Error('value has a fractional component') +} + +function readUInt64LE (buffer, offset) { + var a = buffer.readUInt32LE(offset) + var b = buffer.readUInt32LE(offset + 4) + b *= 0x100000000 + + verifuint(b + a, 0x001fffffffffffff) + + return b + a +} + +function writeUInt64LE (buffer, value, offset) { + verifuint(value, 0x001fffffffffffff) + + buffer.writeInt32LE(value & -1, offset) + buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4) + return offset + 8 +} + +module.exports = { + readUInt64LE: readUInt64LE, + writeUInt64LE: writeUInt64LE +} diff --git a/test/bufferutils.js b/test/bufferutils.js new file mode 100644 index 0000000..414e843 --- /dev/null +++ b/test/bufferutils.js @@ -0,0 +1,50 @@ +/* global describe, it */ + +var assert = require('assert') +var bufferutils = require('../src/bufferutils') + +var fixtures = require('./fixtures/bufferutils.json') + +describe('bufferutils', function () { + describe('readUInt64LE', function () { + fixtures.valid.forEach(function (f) { + it('decodes ' + f.hex64 + ' correctly', function () { + var buffer = Buffer.from(f.hex64, 'hex') + var number = bufferutils.readUInt64LE(buffer, 0) + + assert.strictEqual(number, f.dec) + }) + }) + + fixtures.invalid.readUInt64LE.forEach(function (f) { + it('throws on ' + f.description, function () { + var buffer = Buffer.from(f.hex64, 'hex') + + assert.throws(function () { + bufferutils.readUInt64LE(buffer, 0) + }, new RegExp(f.exception)) + }) + }) + }) + + describe('writeUInt64LE', function () { + fixtures.valid.forEach(function (f) { + it('encodes ' + f.dec + ' correctly', function () { + var buffer = Buffer.alloc(8, 0) + + bufferutils.writeUInt64LE(buffer, f.dec, 0) + assert.strictEqual(buffer.toString('hex'), f.hex64) + }) + }) + + fixtures.invalid.readUInt64LE.forEach(function (f) { + it('throws on ' + f.description, function () { + var buffer = Buffer.alloc(8, 0) + + assert.throws(function () { + bufferutils.writeUInt64LE(buffer, f.dec, 0) + }, new RegExp(f.exception)) + }) + }) + }) +}) diff --git a/test/fixtures/bufferutils.json b/test/fixtures/bufferutils.json new file mode 100644 index 0000000..0b82d50 --- /dev/null +++ b/test/fixtures/bufferutils.json @@ -0,0 +1,76 @@ +{ + "valid": [ + { + "dec": 0, + "hex64": "0000000000000000" + }, + { + "dec": 1, + "hex64": "0100000000000000" + }, + { + "dec": 252, + "hex64": "fc00000000000000" + }, + { + "dec": 253, + "hex64": "fd00000000000000" + }, + { + "dec": 254, + "hex64": "fe00000000000000" + }, + { + "dec": 255, + "hex64": "ff00000000000000" + }, + { + "dec": 65534, + "hex64": "feff000000000000" + }, + { + "dec": 65535, + "hex64": "ffff000000000000" + }, + { + "dec": 65536, + "hex64": "0000010000000000" + }, + { + "dec": 65537, + "hex64": "0100010000000000" + }, + { + "dec": 4294967295, + "hex64": "ffffffff00000000" + }, + { + "dec": 4294967296, + "hex64": "0000000001000000" + }, + { + "dec": 4294967297, + "hex64": "0100000001000000" + }, + { + "dec": 9007199254740991, + "hex64": "ffffffffffff1f00" + } + ], + "invalid": { + "readUInt64LE": [ + { + "description": "n === 2^53", + "exception": "RangeError: value out of range", + "hex64": "0000000000002000", + "dec": 9007199254740992 + }, + { + "description": "n > 2^53", + "exception": "RangeError: value out of range", + "hex64": "0100000000002000", + "dec": 9007199254740993 + } + ] + } +}