Skip to content

refactor: Removes dead code paths from number serialization #399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ export const BSON_INT64_MIN = -Math.pow(2, 63);

// JS MAX PRECISE VALUES
// Any integer up to 2^53 can be precisely represented by a double.
export const JS_INT_MAX = Number.MAX_SAFE_INTEGER + 1;
export const JS_INT_MAX = Math.pow(2, 53);
// Any integer down to -2^53 can be precisely represented by a double.
export const JS_INT_MIN = Number.MIN_SAFE_INTEGER - 1;
export const JS_INT_MIN = -Math.pow(2, 53);

/** Number BSON Type */
export const BSON_DATA_NUMBER = 1;
Expand Down
77 changes: 18 additions & 59 deletions src/parser/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,68 +80,27 @@ function serializeNumber(
isArray?: boolean
) {
// We have an integer value
// TODO(NODE-2769): Issue serializing large integers as doubles
// TODO(NODE-2529): Add support for big int
if (
Math.floor(value) === value &&
value >= constants.JS_INT_MIN &&
value <= constants.JS_INT_MAX
Number.isInteger(value) &&
value >= constants.BSON_INT32_MIN &&
value <= constants.BSON_INT32_MAX
) {
// If the value fits in 32 bits encode as int, if it fits in a double
// encode it as a double, otherwise long
if (value >= constants.BSON_INT32_MIN && value <= constants.BSON_INT32_MAX) {
// Set int type 32 bits or less
buffer[index++] = constants.BSON_DATA_INT;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
// Encode the name
index = index + numberOfWrittenBytes;
buffer[index++] = 0;
// Write the int value
buffer[index++] = value & 0xff;
buffer[index++] = (value >> 8) & 0xff;
buffer[index++] = (value >> 16) & 0xff;
buffer[index++] = (value >> 24) & 0xff;
} else if (value >= constants.JS_INT_MIN && value <= constants.JS_INT_MAX) {
// Encode as double
buffer[index++] = constants.BSON_DATA_NUMBER;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
// Encode the name
index = index + numberOfWrittenBytes;
buffer[index++] = 0;
// Write float
writeIEEE754(buffer, value, index, 'little', 52, 8);
// Adjust index
index = index + 8;
} else {
// Set long type
buffer[index++] = constants.BSON_DATA_LONG;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
// Encode the name
index = index + numberOfWrittenBytes;
buffer[index++] = 0;
const longVal = Long.fromNumber(value);
const lowBits = longVal.getLowBits();
const highBits = longVal.getHighBits();
// Encode low bits
buffer[index++] = lowBits & 0xff;
buffer[index++] = (lowBits >> 8) & 0xff;
buffer[index++] = (lowBits >> 16) & 0xff;
buffer[index++] = (lowBits >> 24) & 0xff;
// Encode high bits
buffer[index++] = highBits & 0xff;
buffer[index++] = (highBits >> 8) & 0xff;
buffer[index++] = (highBits >> 16) & 0xff;
buffer[index++] = (highBits >> 24) & 0xff;
}
// If the value fits in 32 bits encode as int32
// Set int type 32 bits or less
buffer[index++] = constants.BSON_DATA_INT;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
// Encode the name
index = index + numberOfWrittenBytes;
buffer[index++] = 0;
// Write the int value
buffer[index++] = value & 0xff;
buffer[index++] = (value >> 8) & 0xff;
buffer[index++] = (value >> 16) & 0xff;
buffer[index++] = (value >> 24) & 0xff;
} else {
// Encode as double
buffer[index++] = constants.BSON_DATA_NUMBER;
Expand Down