Skip to content
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

feat(NODE-4506): Make UUID a subclass of binary #512

Merged
merged 11 commits into from
Aug 11, 2022
20 changes: 8 additions & 12 deletions src/binary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,7 @@ Object.defineProperty(Binary.prototype, '_bsontype', { value: 'Binary' });
export type UUIDExtended = {
$uuid: string;
};
const BYTE_LENGTH = 16;

const kId = Symbol('id');
const UUID_BYTE_LENGTH = 16;

/**
* A class representation of the BSON UUID type.
Expand All @@ -309,8 +307,6 @@ const kId = Symbol('id');
export class UUID extends Binary {
static cacheHexString: boolean;

/** UUID Bytes @internal */
private [kId]!: Buffer;
/** UUID hexString cache @internal */
private __id?: string;

Expand All @@ -325,9 +321,9 @@ export class UUID extends Binary {
if (input == null) {
bytes = UUID.generate();
} else if (input instanceof UUID) {
bytes = Buffer.from(input[kId]);
bytes = Buffer.from(input.buffer);
hexStr = input.__id;
} else if (ArrayBuffer.isView(input) && input.byteLength === BYTE_LENGTH) {
} else if (ArrayBuffer.isView(input) && input.byteLength === UUID_BYTE_LENGTH) {
bytes = ensureBuffer(input);
} else if (typeof input === 'string') {
bytes = uuidHexStringToBuffer(input);
Expand All @@ -337,7 +333,7 @@ export class UUID extends Binary {
);
}
super(bytes, BSON_BINARY_SUBTYPE_UUID_NEW);
this[kId] = bytes;
this.buffer = bytes;
nbbeeken marked this conversation as resolved.
Show resolved Hide resolved
this.__id = hexStr;
}

Expand All @@ -346,11 +342,11 @@ export class UUID extends Binary {
* @readonly
*/
get id(): Buffer {
return this[kId];
return this.buffer;
}

set id(value: Buffer) {
this[kId] = value;
this.buffer = value;

if (UUID.cacheHexString) {
this.__id = bufferToUuidHexString(value);
Expand Down Expand Up @@ -426,7 +422,7 @@ export class UUID extends Binary {
* Generates a populated buffer containing a v4 uuid
*/
static generate(): Buffer {
const bytes = randomBytes(BYTE_LENGTH);
const bytes = randomBytes(UUID_BYTE_LENGTH);

// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
// Kindly borrowed from https://github.com/uuidjs/uuid/blob/master/src/v4.js
Expand Down Expand Up @@ -455,7 +451,7 @@ export class UUID extends Binary {

if (isUint8Array(input)) {
// check for length & uuid version (https://tools.ietf.org/html/rfc4122#section-4.1.3)
if (input.length !== BYTE_LENGTH) {
if (input.length !== UUID_BYTE_LENGTH) {
return false;
}

Expand Down
20 changes: 20 additions & 0 deletions test/node/uuid_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const { inspect } = require('util');
const { validate: uuidStringValidate, version: uuidStringVersion } = require('uuid');
const BSON = require('../register-bson');
const BSONTypeError = BSON.BSONTypeError;
const BSON_DATA_BINARY = BSON.BSON_DATA_BINARY;
const BSON_BINARY_SUBTYPE_UUID_NEW = BSON.BSON_BINARY_SUBTYPE_UUID_NEW;

// Test values
const UPPERCASE_DASH_SEPARATED_UUID_STRING = 'AAAAAAAA-AAAA-4AAA-AAAA-AAAAAAAAAAAA';
Expand Down Expand Up @@ -170,5 +172,23 @@ describe('UUID', () => {
const plainUUIDSerialization = BSON.serialize({ uuid: exampleUUID });
expect(plainUUIDSerialization).to.deep.equal(toBinarySerialization);
});

it('should have a valid UUID _bsontype with Object input without error', () => {
const output = BSON.serialize({ uuid: new BSON.UUID() });
expect(output[4]).to.equal(BSON_DATA_BINARY);
expect(output[14]).to.equal(BSON_BINARY_SUBTYPE_UUID_NEW);
});

it('should have a valid UUID _bsontype with Map input without error', () => {
const output = BSON.serialize(new Map([['uuid', new BSON.UUID()]]));
expect(output[4]).to.equal(BSON_DATA_BINARY);
expect(output[14]).to.equal(BSON_BINARY_SUBTYPE_UUID_NEW);
});

it('should have as a valid UUID _bsontype with Array input without error', () => {
const output = BSON.serialize({ a: [new BSON.UUID()] });
expect(output[11]).to.equal(BSON_DATA_BINARY);
expect(output[18]).to.equal(BSON_BINARY_SUBTYPE_UUID_NEW);
});
});
});