Skip to content

Commit 35228a2

Browse files
committed
merged @pwmckenna's fix for 53bit numbers
2 parents 0f11f05 + 8a408fc commit 35228a2

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

lib/encode.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ encode._encode = function( buffers, data ) {
3333
: encode.dict( buffers, data )
3434
break
3535
}
36-
36+
3737
}
3838

3939
var buff_e = new Buffer('e')
@@ -46,14 +46,13 @@ encode.bytes = function( buffers, data ) {
4646
}
4747

4848
encode.number = function( buffers, data ) {
49-
50-
var maxLo = 4294967295
49+
var maxLo = 0x80000000
5150
var hi = ( data / maxLo ) << 0
5251
var lo = ( data % maxLo ) << 0
5352
var val = hi * maxLo + lo
54-
53+
5554
buffers.push( new Buffer( 'i' + val + 'e' ))
56-
55+
5756
if( val !== data && !encode._floatConversionDetected ) {
5857
encode._floatConversionDetected = true
5958
console.warn(
@@ -62,7 +61,7 @@ encode.number = function( buffers, data ) {
6261
)
6362
console.trace()
6463
}
65-
64+
6665
}
6766

6867
encode.dict = function( buffers, data ) {

test/encode.test.js

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ var assert = require("assert");
22
var bencode = require('./lib.js');
33

44
describe("bencode", function() {
5+
6+
// prevent the warning showing up in the test
7+
bencode.encode._floatConversionDetected = true
8+
59
describe("#encode()", function() {
610
it('should always return a Buffer', function() {
711
assert.ok(Buffer.isBuffer(bencode.encode({})), "its not a buffer for empty dicts");
@@ -36,17 +40,42 @@ describe("bencode", function() {
3640
it('should be able to encode a negative float (as int)', function() {
3741
assert.equal(bencode.encode(-123.5), 'i-123e');
3842
})
39-
it('should be able to encode a positive 64 bit int', function() {
40-
assert.equal(bencode.encode(4777722361), 'i4777722361e');
43+
it('should be able to safely encode numbers between -/+ 2 ^ 53 (as ints)', function() {
44+
assert.equal(bencode.encode(0), 'i' + 0 + 'e');
45+
46+
var JAVASCRIPT_INT_BITS = 53;
47+
var MAX_JAVASCRIPT_INT = Math.pow(2, JAVASCRIPT_INT_BITS);
48+
49+
for (var exp = 1; exp < JAVASCRIPT_INT_BITS; ++exp) {
50+
var val = Math.pow(2, exp);
51+
// try the positive and negative
52+
assert.equal(bencode.encode(val), 'i' + val + 'e');
53+
assert.equal(bencode.encode(-val), 'i-' + val + 'e');
54+
55+
// try the value, one above and one below, both positive and negative
56+
var above = val + 1;
57+
var below = val - 1;
58+
59+
assert.equal(bencode.encode(above), 'i' + above + 'e');
60+
assert.equal(bencode.encode(-above), 'i-' + above + 'e');
61+
62+
assert.equal(bencode.encode(below), 'i' + below + 'e');
63+
assert.equal(bencode.encode(-below), 'i-' + below + 'e');
64+
}
65+
assert.equal(bencode.encode(MAX_JAVASCRIPT_INT), 'i' + MAX_JAVASCRIPT_INT + 'e');
66+
assert.equal(bencode.encode(-MAX_JAVASCRIPT_INT), 'i-' + MAX_JAVASCRIPT_INT + 'e');
67+
});
68+
it('should be able to encode a previously problematice 64 bit int', function() {
69+
assert.equal(bencode.encode(2433088826), 'i' + 2433088826 + 'e');
4170
})
4271
it('should be able to encode a negative 64 bit int', function() {
43-
assert.equal(bencode.encode(-4777722361), 'i-4777722361e');
72+
assert.equal(bencode.encode(-0xffffffff), 'i-' + 0xffffffff + 'e');
4473
})
4574
it('should be able to encode a positive 64 bit float (as int)', function() {
46-
assert.equal(bencode.encode(4777722361.5), 'i4777722361e');
75+
assert.equal(bencode.encode(0xffffffff + 0.5), 'i' + 0xffffffff + 'e');
4776
})
4877
it('should be able to encode a negative 64 bit float (as int)', function() {
49-
assert.equal(bencode.encode(-4777722361.5), 'i-4777722361e');
78+
assert.equal(bencode.encode(-0xffffffff - 0.5), 'i-' + 0xffffffff + 'e');
5079
})
5180
it('should be able to encode a string', function() {
5281
assert.equal(bencode.encode("asdf"), '4:asdf');

0 commit comments

Comments
 (0)