You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
7.9 KiB
TypeScript

import { Binary, UUID } from './binary';
import { Code } from './code';
import { DBRef } from './db_ref';
import { Decimal128 } from './decimal128';
import { Double } from './double';
import { Int32 } from './int_32';
import { Long } from './long';
import { MaxKey } from './max_key';
import { MinKey } from './min_key';
import { ObjectId } from './objectid';
import { internalCalculateObjectSize } from './parser/calculate_size';
// Parts of the parser
import { internalDeserialize, DeserializeOptions } from './parser/deserializer';
import { serializeInto, SerializeOptions } from './parser/serializer';
import { BSONRegExp } from './regexp';
import { BSONSymbol } from './symbol';
import { Timestamp } from './timestamp';
import { ByteUtils } from './utils/byte_utils';
export type { UUIDExtended, BinaryExtended, BinaryExtendedLegacy, BinarySequence } from './binary';
export type { CodeExtended } from './code';
export type { DBRefLike } from './db_ref';
export type { Decimal128Extended } from './decimal128';
export type { DoubleExtended } from './double';
export type { EJSONOptions } from './extended_json';
export type { Int32Extended } from './int_32';
export type { LongExtended } from './long';
export type { MaxKeyExtended } from './max_key';
export type { MinKeyExtended } from './min_key';
export type { ObjectIdExtended, ObjectIdLike } from './objectid';
export type { BSONRegExpExtended, BSONRegExpExtendedLegacy } from './regexp';
export type { BSONSymbolExtended } from './symbol';
export type { LongWithoutOverrides, TimestampExtended, TimestampOverrides } from './timestamp';
export type { LongWithoutOverridesClass } from './timestamp';
export type { SerializeOptions, DeserializeOptions };
export {
Code,
BSONSymbol,
DBRef,
Binary,
ObjectId,
UUID,
Long,
Timestamp,
Double,
Int32,
MinKey,
MaxKey,
BSONRegExp,
Decimal128
};
export { BSONValue } from './bson_value';
export { BSONError, BSONVersionError, BSONRuntimeError } from './error';
export { BSONType } from './constants';
export { EJSON } from './extended_json';
/** @public */
export interface Document {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}
/** @internal */
// Default Max Size
const MAXSIZE = 1024 * 1024 * 17;
// Current Internal Temporary Serialization Buffer
let buffer = ByteUtils.allocate(MAXSIZE);
/**
* Sets the size of the internal serialization buffer.
*
* @param size - The desired size for the internal serialization buffer in bytes
* @public
*/
export function setInternalBufferSize(size: number): void {
// Resize the internal serialization buffer if needed
if (buffer.length < size) {
buffer = ByteUtils.allocate(size);
}
}
/**
* Serialize a Javascript object.
*
* @param object - the Javascript object to serialize.
* @returns Buffer object containing the serialized object.
* @public
*/
export function serialize(object: Document, options: SerializeOptions = {}): Uint8Array {
// Unpack the options
const checkKeys = typeof options.checkKeys === 'boolean' ? options.checkKeys : false;
const serializeFunctions =
typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
const ignoreUndefined =
typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
const minInternalBufferSize =
typeof options.minInternalBufferSize === 'number' ? options.minInternalBufferSize : MAXSIZE;
// Resize the internal serialization buffer if needed
if (buffer.length < minInternalBufferSize) {
buffer = ByteUtils.allocate(minInternalBufferSize);
}
// Attempt to serialize
const serializationIndex = serializeInto(
buffer,
object,
checkKeys,
0,
0,
serializeFunctions,
ignoreUndefined,
null
);
// Create the final buffer
const finishedBuffer = ByteUtils.allocate(serializationIndex);
// Copy into the finished buffer
finishedBuffer.set(buffer.subarray(0, serializationIndex), 0);
// Return the buffer
return finishedBuffer;
}
/**
* Serialize a Javascript object using a predefined Buffer and index into the buffer,
* useful when pre-allocating the space for serialization.
*
* @param object - the Javascript object to serialize.
* @param finalBuffer - the Buffer you pre-allocated to store the serialized BSON object.
* @returns the index pointing to the last written byte in the buffer.
* @public
*/
export function serializeWithBufferAndIndex(
object: Document,
finalBuffer: Uint8Array,
options: SerializeOptions = {}
): number {
// Unpack the options
const checkKeys = typeof options.checkKeys === 'boolean' ? options.checkKeys : false;
const serializeFunctions =
typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
const ignoreUndefined =
typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
const startIndex = typeof options.index === 'number' ? options.index : 0;
// Attempt to serialize
const serializationIndex = serializeInto(
buffer,
object,
checkKeys,
0,
0,
serializeFunctions,
ignoreUndefined,
null
);
finalBuffer.set(buffer.subarray(0, serializationIndex), startIndex);
// Return the index
return startIndex + serializationIndex - 1;
}
/**
* Deserialize data as BSON.
*
* @param buffer - the buffer containing the serialized set of BSON documents.
* @returns returns the deserialized Javascript Object.
* @public
*/
export function deserialize(buffer: Uint8Array, options: DeserializeOptions = {}): Document {
return internalDeserialize(ByteUtils.toLocalBufferType(buffer), options);
}
/** @public */
export type CalculateObjectSizeOptions = Pick<
SerializeOptions,
'serializeFunctions' | 'ignoreUndefined'
>;
/**
* Calculate the bson size for a passed in Javascript object.
*
* @param object - the Javascript object to calculate the BSON byte size for
* @returns size of BSON object in bytes
* @public
*/
export function calculateObjectSize(
object: Document,
options: CalculateObjectSizeOptions = {}
): number {
options = options || {};
const serializeFunctions =
typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
const ignoreUndefined =
typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
return internalCalculateObjectSize(object, serializeFunctions, ignoreUndefined);
}
/**
* Deserialize stream data as BSON documents.
*
* @param data - the buffer containing the serialized set of BSON documents.
* @param startIndex - the start index in the data Buffer where the deserialization is to start.
* @param numberOfDocuments - number of documents to deserialize.
* @param documents - an array where to store the deserialized documents.
* @param docStartIndex - the index in the documents array from where to start inserting documents.
* @param options - additional options used for the deserialization.
* @returns next index in the buffer after deserialization **x** numbers of documents.
* @public
*/
export function deserializeStream(
data: Uint8Array | ArrayBuffer,
startIndex: number,
numberOfDocuments: number,
documents: Document[],
docStartIndex: number,
options: DeserializeOptions
): number {
const internalOptions = Object.assign(
{ allowObjectSmallerThanBufferSize: true, index: 0 },
options
);
const bufferData = ByteUtils.toLocalBufferType(data);
let index = startIndex;
// Loop over all documents
for (let i = 0; i < numberOfDocuments; i++) {
// Find size of the document
const size =
bufferData[index] |
(bufferData[index + 1] << 8) |
(bufferData[index + 2] << 16) |
(bufferData[index + 3] << 24);
// Update options with index
internalOptions.index = index;
// Parse the document at this point
documents[docStartIndex + i] = internalDeserialize(bufferData, internalOptions);
// Adjust index by the document size
index = index + size;
}
// Return object containing end index of parsing and list of documents
return index;
}