Very Popular
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270// deno-lint-ignore-file no-explicit-anyimport { Binary, BinarySizes } from "../binary.ts";import { BSONRegExp, BSONSymbol, Code, DBRef, Decimal128, Document, Double, Long, MaxKey, MinKey, ObjectId, Timestamp,} from "../bson.ts";import * as constants from "../constants.ts";import { normalizedFunctionString } from "./utils.ts";
const utf8Encoder = new TextEncoder();
export function calculateObjectSize( object: Document, serializeFunctions?: boolean, ignoreUndefined?: boolean,): number { let totalLength = 4 + 1;
if (Array.isArray(object)) { for (let i = 0; i < object.length; i++) { totalLength += calculateElement( i.toString(), object[i], serializeFunctions, true, ignoreUndefined, ); } } else { // If we have toBSON defined, override the current object
if (object.toBSON) { object = object.toBSON(); }
// Calculate size for (const key in object) { totalLength += calculateElement( key, object[key], serializeFunctions, false, ignoreUndefined, ); } }
return totalLength;}
function calculateElement( name: string, value: any, serializeFunctions = false, isArray = false, ignoreUndefined = false,) { // If we have toBSON defined, override the current object if (value?.toBSON) { value = value.toBSON(); }
switch (typeof value) { case "string": return 1 + utf8Encoder.encode(name).length + 1 + 4 + utf8Encoder.encode(value).length + 1; case "number": if ( Math.floor(value) === value && value >= constants.JS_INT_MIN && value <= constants.JS_INT_MAX ) { return value >= constants.BSON_INT32_MIN && value <= constants.BSON_INT32_MAX ? (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (4 + 1) : (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (8 + 1); } else { // 64 bit return (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (8 + 1); } case "undefined": if (isArray || !ignoreUndefined) { return (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1; } return 0; case "boolean": return (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (1 + 1); case "object": if (value == null || value instanceof MinKey || value instanceof MaxKey) { return (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1; } else if (value instanceof ObjectId) { return (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (12 + 1); } else if (value instanceof Date) { return (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (8 + 1); } else if ( ArrayBuffer.isView(value) || value instanceof ArrayBuffer ) { return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (1 + 4 + 1) + value.byteLength ); } else if ( value instanceof Long || value instanceof Double || value instanceof Timestamp ) { return (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (8 + 1); } else if (value instanceof Decimal128) { return (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (16 + 1); } else if (value instanceof Code) { // Calculate size depending on the availability of a scope if (value.scope != null && Object.keys(value.scope).length > 0) { return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1 + 4 + 4 + utf8Encoder.encode(value.code.toString()).length + 1 + calculateObjectSize( value.scope, serializeFunctions, ignoreUndefined, ) ); } return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1 + 4 + utf8Encoder.encode(value.code.toString()).length + 1 ); } else if (value instanceof Binary) { // Check what kind of subtype we have return value.subType === BinarySizes.SUBTYPE_BYTE_ARRAY ? ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (value.buffer.length + 1 + 4 + 1 + 4) ) : ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + (value.buffer.length + 1 + 4 + 1) ); } else if (value instanceof BSONSymbol) { return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + utf8Encoder.encode(value.value).length + 4 + 1 + 1 ); } else if (value instanceof DBRef) { // Set up correct object for serialization const orderedValues = Object.assign( { $ref: value.collection, $id: value.oid, }, value.fields, );
// Add db reference if it exists if (value.db != null) { orderedValues.$db = value.db; }
return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1 + calculateObjectSize( orderedValues, serializeFunctions, ignoreUndefined, ) ); } else if (value instanceof RegExp) { return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1 + utf8Encoder.encode(value.source).length + 1 + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 ); } else if (value instanceof BSONRegExp) { return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1 + utf8Encoder.encode(value.pattern).length + 1 + utf8Encoder.encode(value.options).length + 1 ); } else { return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + calculateObjectSize(value, serializeFunctions, ignoreUndefined) + 1 ); } case "function": // WTF for 0.4.X where typeof /someregexp/ === 'function' if ( value instanceof RegExp || String.call(value) === "[object RegExp]" ) { return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1 + utf8Encoder.encode(value.source).length + 1 + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 ); } else { if ( serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0 ) { return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1 + 4 + 4 + utf8Encoder.encode(normalizedFunctionString(value)).length + 1 + calculateObjectSize( value.scope, serializeFunctions, ignoreUndefined, ) ); } if (serializeFunctions) { return ( (name != null ? utf8Encoder.encode(name).length + 1 : 0) + 1 + 4 + utf8Encoder.encode(normalizedFunctionString(value)).length + 1 ); } } }
return 0;}