Skip to content

feat(NODE-6537): add support for binary vectors #730

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 13 commits into from
Nov 18, 2024
Merged
Prev Previous commit
Next Next commit
refactor: moved validation to free function
  • Loading branch information
nbbeeken committed Nov 18, 2024
commit 1dc36adc693cae95fc084da48ed74f469edf0899
55 changes: 27 additions & 28 deletions src/binary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export class Binary extends BSONValue {
options = options || {};

if (this.sub_type === Binary.SUBTYPE_VECTOR) {
Binary.validateVector(this);
validateBinaryVector(this);
}

const base64String = ByteUtils.toBase64(this.buffer);
Expand Down Expand Up @@ -514,40 +514,39 @@ export class Binary extends BSONValue {

return new this(bytes, Binary.SUBTYPE_VECTOR);
}
}

/** @internal */
static validateVector(vector: Binary): void {
if (vector.sub_type !== this.SUBTYPE_VECTOR) return;
export function validateBinaryVector(vector: Binary): void {
if (vector.sub_type !== Binary.SUBTYPE_VECTOR) return;

const size = vector.position;
const size = vector.position;

// NOTE: Validation is only applied to **KNOWN** vector types
// If a new datatype is introduced, a future version of the library will need to add validation
const datatype = vector.buffer[0];
// NOTE: Validation is only applied to **KNOWN** vector types
// If a new datatype is introduced, a future version of the library will need to add validation
const datatype = vector.buffer[0];

// NOTE: We do not enable noUncheckedIndexedAccess so TS believes this is always number
// a Binary vector may be empty, in which case the padding is undefined
// this possible value is tolerable for our validation checks
const padding: number | undefined = vector.buffer[1];
// NOTE: We do not enable noUncheckedIndexedAccess so TS believes this is always number
// a Binary vector may be empty, in which case the padding is undefined
// this possible value is tolerable for our validation checks
const padding: number | undefined = vector.buffer[1];

if (
(datatype === this.VECTOR_TYPE.Float32 || datatype === this.VECTOR_TYPE.Int8) &&
padding !== 0
) {
throw new BSONError('Invalid Vector: padding must be zero for int8 and float32 vectors');
}
if (
(datatype === Binary.VECTOR_TYPE.Float32 || datatype === Binary.VECTOR_TYPE.Int8) &&
padding !== 0
) {
throw new BSONError('Invalid Vector: padding must be zero for int8 and float32 vectors');
}

if (datatype === this.VECTOR_TYPE.PackedBit && padding !== 0 && size === 2) {
throw new BSONError(
'Invalid Vector: padding must be zero for packed bit vectors that are empty'
);
}
if (datatype === Binary.VECTOR_TYPE.PackedBit && padding !== 0 && size === 2) {
throw new BSONError(
'Invalid Vector: padding must be zero for packed bit vectors that are empty'
);
}

if (datatype === this.VECTOR_TYPE.PackedBit && padding > 7) {
throw new BSONError(
`Invalid Vector: padding must be a value between 0 and 7. found: ${padding}`
);
}
if (datatype === Binary.VECTOR_TYPE.PackedBit && padding > 7) {
throw new BSONError(
`Invalid Vector: padding must be a value between 0 and 7. found: ${padding}`
);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/parser/serializer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Binary } from '../binary';
import { Binary, validateBinaryVector } from '../binary';
import type { BSONSymbol, DBRef, Document, MaxKey } from '../bson';
import type { Code } from '../code';
import * as constants from '../constants';
Expand Down Expand Up @@ -496,7 +496,7 @@ function serializeBinary(buffer: Uint8Array, key: string, value: Binary, index:
}

if (value.sub_type === Binary.SUBTYPE_VECTOR) {
Binary.validateVector(value);
validateBinaryVector(value);
}

if (size <= 16) {
Expand Down