serializer.js 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.serializeInto = void 0;
  4. var binary_1 = require("../binary");
  5. var constants = require("../constants");
  6. var ensure_buffer_1 = require("../ensure_buffer");
  7. var error_1 = require("../error");
  8. var extended_json_1 = require("../extended_json");
  9. var float_parser_1 = require("../float_parser");
  10. var long_1 = require("../long");
  11. var map_1 = require("../map");
  12. var utils_1 = require("./utils");
  13. var regexp = /\x00/; // eslint-disable-line no-control-regex
  14. var ignoreKeys = new Set(['$db', '$ref', '$id', '$clusterTime']);
  15. /*
  16. * isArray indicates if we are writing to a BSON array (type 0x04)
  17. * which forces the "key" which really an array index as a string to be written as ascii
  18. * This will catch any errors in index as a string generation
  19. */
  20. function serializeString(buffer, key, value, index, isArray) {
  21. // Encode String type
  22. buffer[index++] = constants.BSON_DATA_STRING;
  23. // Number of written bytes
  24. var numberOfWrittenBytes = !isArray
  25. ? buffer.write(key, index, undefined, 'utf8')
  26. : buffer.write(key, index, undefined, 'ascii');
  27. // Encode the name
  28. index = index + numberOfWrittenBytes + 1;
  29. buffer[index - 1] = 0;
  30. // Write the string
  31. var size = buffer.write(value, index + 4, undefined, 'utf8');
  32. // Write the size of the string to buffer
  33. buffer[index + 3] = ((size + 1) >> 24) & 0xff;
  34. buffer[index + 2] = ((size + 1) >> 16) & 0xff;
  35. buffer[index + 1] = ((size + 1) >> 8) & 0xff;
  36. buffer[index] = (size + 1) & 0xff;
  37. // Update index
  38. index = index + 4 + size;
  39. // Write zero
  40. buffer[index++] = 0;
  41. return index;
  42. }
  43. function serializeNumber(buffer, key, value, index, isArray) {
  44. // We have an integer value
  45. // TODO(NODE-2529): Add support for big int
  46. if (Number.isInteger(value) &&
  47. value >= constants.BSON_INT32_MIN &&
  48. value <= constants.BSON_INT32_MAX) {
  49. // If the value fits in 32 bits encode as int32
  50. // Set int type 32 bits or less
  51. buffer[index++] = constants.BSON_DATA_INT;
  52. // Number of written bytes
  53. var numberOfWrittenBytes = !isArray
  54. ? buffer.write(key, index, undefined, 'utf8')
  55. : buffer.write(key, index, undefined, 'ascii');
  56. // Encode the name
  57. index = index + numberOfWrittenBytes;
  58. buffer[index++] = 0;
  59. // Write the int value
  60. buffer[index++] = value & 0xff;
  61. buffer[index++] = (value >> 8) & 0xff;
  62. buffer[index++] = (value >> 16) & 0xff;
  63. buffer[index++] = (value >> 24) & 0xff;
  64. }
  65. else {
  66. // Encode as double
  67. buffer[index++] = constants.BSON_DATA_NUMBER;
  68. // Number of written bytes
  69. var numberOfWrittenBytes = !isArray
  70. ? buffer.write(key, index, undefined, 'utf8')
  71. : buffer.write(key, index, undefined, 'ascii');
  72. // Encode the name
  73. index = index + numberOfWrittenBytes;
  74. buffer[index++] = 0;
  75. // Write float
  76. float_parser_1.writeIEEE754(buffer, value, index, 'little', 52, 8);
  77. // Adjust index
  78. index = index + 8;
  79. }
  80. return index;
  81. }
  82. function serializeNull(buffer, key, _, index, isArray) {
  83. // Set long type
  84. buffer[index++] = constants.BSON_DATA_NULL;
  85. // Number of written bytes
  86. var numberOfWrittenBytes = !isArray
  87. ? buffer.write(key, index, undefined, 'utf8')
  88. : buffer.write(key, index, undefined, 'ascii');
  89. // Encode the name
  90. index = index + numberOfWrittenBytes;
  91. buffer[index++] = 0;
  92. return index;
  93. }
  94. function serializeBoolean(buffer, key, value, index, isArray) {
  95. // Write the type
  96. buffer[index++] = constants.BSON_DATA_BOOLEAN;
  97. // Number of written bytes
  98. var numberOfWrittenBytes = !isArray
  99. ? buffer.write(key, index, undefined, 'utf8')
  100. : buffer.write(key, index, undefined, 'ascii');
  101. // Encode the name
  102. index = index + numberOfWrittenBytes;
  103. buffer[index++] = 0;
  104. // Encode the boolean value
  105. buffer[index++] = value ? 1 : 0;
  106. return index;
  107. }
  108. function serializeDate(buffer, key, value, index, isArray) {
  109. // Write the type
  110. buffer[index++] = constants.BSON_DATA_DATE;
  111. // Number of written bytes
  112. var numberOfWrittenBytes = !isArray
  113. ? buffer.write(key, index, undefined, 'utf8')
  114. : buffer.write(key, index, undefined, 'ascii');
  115. // Encode the name
  116. index = index + numberOfWrittenBytes;
  117. buffer[index++] = 0;
  118. // Write the date
  119. var dateInMilis = long_1.Long.fromNumber(value.getTime());
  120. var lowBits = dateInMilis.getLowBits();
  121. var highBits = dateInMilis.getHighBits();
  122. // Encode low bits
  123. buffer[index++] = lowBits & 0xff;
  124. buffer[index++] = (lowBits >> 8) & 0xff;
  125. buffer[index++] = (lowBits >> 16) & 0xff;
  126. buffer[index++] = (lowBits >> 24) & 0xff;
  127. // Encode high bits
  128. buffer[index++] = highBits & 0xff;
  129. buffer[index++] = (highBits >> 8) & 0xff;
  130. buffer[index++] = (highBits >> 16) & 0xff;
  131. buffer[index++] = (highBits >> 24) & 0xff;
  132. return index;
  133. }
  134. function serializeRegExp(buffer, key, value, index, isArray) {
  135. // Write the type
  136. buffer[index++] = constants.BSON_DATA_REGEXP;
  137. // Number of written bytes
  138. var numberOfWrittenBytes = !isArray
  139. ? buffer.write(key, index, undefined, 'utf8')
  140. : buffer.write(key, index, undefined, 'ascii');
  141. // Encode the name
  142. index = index + numberOfWrittenBytes;
  143. buffer[index++] = 0;
  144. if (value.source && value.source.match(regexp) != null) {
  145. throw Error('value ' + value.source + ' must not contain null bytes');
  146. }
  147. // Adjust the index
  148. index = index + buffer.write(value.source, index, undefined, 'utf8');
  149. // Write zero
  150. buffer[index++] = 0x00;
  151. // Write the parameters
  152. if (value.ignoreCase)
  153. buffer[index++] = 0x69; // i
  154. if (value.global)
  155. buffer[index++] = 0x73; // s
  156. if (value.multiline)
  157. buffer[index++] = 0x6d; // m
  158. // Add ending zero
  159. buffer[index++] = 0x00;
  160. return index;
  161. }
  162. function serializeBSONRegExp(buffer, key, value, index, isArray) {
  163. // Write the type
  164. buffer[index++] = constants.BSON_DATA_REGEXP;
  165. // Number of written bytes
  166. var numberOfWrittenBytes = !isArray
  167. ? buffer.write(key, index, undefined, 'utf8')
  168. : buffer.write(key, index, undefined, 'ascii');
  169. // Encode the name
  170. index = index + numberOfWrittenBytes;
  171. buffer[index++] = 0;
  172. // Check the pattern for 0 bytes
  173. if (value.pattern.match(regexp) != null) {
  174. // The BSON spec doesn't allow keys with null bytes because keys are
  175. // null-terminated.
  176. throw Error('pattern ' + value.pattern + ' must not contain null bytes');
  177. }
  178. // Adjust the index
  179. index = index + buffer.write(value.pattern, index, undefined, 'utf8');
  180. // Write zero
  181. buffer[index++] = 0x00;
  182. // Write the options
  183. index = index + buffer.write(value.options.split('').sort().join(''), index, undefined, 'utf8');
  184. // Add ending zero
  185. buffer[index++] = 0x00;
  186. return index;
  187. }
  188. function serializeMinMax(buffer, key, value, index, isArray) {
  189. // Write the type of either min or max key
  190. if (value === null) {
  191. buffer[index++] = constants.BSON_DATA_NULL;
  192. }
  193. else if (value._bsontype === 'MinKey') {
  194. buffer[index++] = constants.BSON_DATA_MIN_KEY;
  195. }
  196. else {
  197. buffer[index++] = constants.BSON_DATA_MAX_KEY;
  198. }
  199. // Number of written bytes
  200. var numberOfWrittenBytes = !isArray
  201. ? buffer.write(key, index, undefined, 'utf8')
  202. : buffer.write(key, index, undefined, 'ascii');
  203. // Encode the name
  204. index = index + numberOfWrittenBytes;
  205. buffer[index++] = 0;
  206. return index;
  207. }
  208. function serializeObjectId(buffer, key, value, index, isArray) {
  209. // Write the type
  210. buffer[index++] = constants.BSON_DATA_OID;
  211. // Number of written bytes
  212. var numberOfWrittenBytes = !isArray
  213. ? buffer.write(key, index, undefined, 'utf8')
  214. : buffer.write(key, index, undefined, 'ascii');
  215. // Encode the name
  216. index = index + numberOfWrittenBytes;
  217. buffer[index++] = 0;
  218. // Write the objectId into the shared buffer
  219. if (typeof value.id === 'string') {
  220. buffer.write(value.id, index, undefined, 'binary');
  221. }
  222. else if (utils_1.isUint8Array(value.id)) {
  223. // Use the standard JS methods here because buffer.copy() is buggy with the
  224. // browser polyfill
  225. buffer.set(value.id.subarray(0, 12), index);
  226. }
  227. else {
  228. throw new error_1.BSONTypeError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
  229. }
  230. // Adjust index
  231. return index + 12;
  232. }
  233. function serializeBuffer(buffer, key, value, index, isArray) {
  234. // Write the type
  235. buffer[index++] = constants.BSON_DATA_BINARY;
  236. // Number of written bytes
  237. var numberOfWrittenBytes = !isArray
  238. ? buffer.write(key, index, undefined, 'utf8')
  239. : buffer.write(key, index, undefined, 'ascii');
  240. // Encode the name
  241. index = index + numberOfWrittenBytes;
  242. buffer[index++] = 0;
  243. // Get size of the buffer (current write point)
  244. var size = value.length;
  245. // Write the size of the string to buffer
  246. buffer[index++] = size & 0xff;
  247. buffer[index++] = (size >> 8) & 0xff;
  248. buffer[index++] = (size >> 16) & 0xff;
  249. buffer[index++] = (size >> 24) & 0xff;
  250. // Write the default subtype
  251. buffer[index++] = constants.BSON_BINARY_SUBTYPE_DEFAULT;
  252. // Copy the content form the binary field to the buffer
  253. buffer.set(ensure_buffer_1.ensureBuffer(value), index);
  254. // Adjust the index
  255. index = index + size;
  256. return index;
  257. }
  258. function serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, isArray, path) {
  259. if (checkKeys === void 0) { checkKeys = false; }
  260. if (depth === void 0) { depth = 0; }
  261. if (serializeFunctions === void 0) { serializeFunctions = false; }
  262. if (ignoreUndefined === void 0) { ignoreUndefined = true; }
  263. if (isArray === void 0) { isArray = false; }
  264. if (path === void 0) { path = []; }
  265. for (var i = 0; i < path.length; i++) {
  266. if (path[i] === value)
  267. throw new error_1.BSONError('cyclic dependency detected');
  268. }
  269. // Push value to stack
  270. path.push(value);
  271. // Write the type
  272. buffer[index++] = Array.isArray(value) ? constants.BSON_DATA_ARRAY : constants.BSON_DATA_OBJECT;
  273. // Number of written bytes
  274. var numberOfWrittenBytes = !isArray
  275. ? buffer.write(key, index, undefined, 'utf8')
  276. : buffer.write(key, index, undefined, 'ascii');
  277. // Encode the name
  278. index = index + numberOfWrittenBytes;
  279. buffer[index++] = 0;
  280. var endIndex = serializeInto(buffer, value, checkKeys, index, depth + 1, serializeFunctions, ignoreUndefined, path);
  281. // Pop stack
  282. path.pop();
  283. return endIndex;
  284. }
  285. function serializeDecimal128(buffer, key, value, index, isArray) {
  286. buffer[index++] = constants.BSON_DATA_DECIMAL128;
  287. // Number of written bytes
  288. var numberOfWrittenBytes = !isArray
  289. ? buffer.write(key, index, undefined, 'utf8')
  290. : buffer.write(key, index, undefined, 'ascii');
  291. // Encode the name
  292. index = index + numberOfWrittenBytes;
  293. buffer[index++] = 0;
  294. // Write the data from the value
  295. // Prefer the standard JS methods because their typechecking is not buggy,
  296. // unlike the `buffer` polyfill's.
  297. buffer.set(value.bytes.subarray(0, 16), index);
  298. return index + 16;
  299. }
  300. function serializeLong(buffer, key, value, index, isArray) {
  301. // Write the type
  302. buffer[index++] =
  303. value._bsontype === 'Long' ? constants.BSON_DATA_LONG : constants.BSON_DATA_TIMESTAMP;
  304. // Number of written bytes
  305. var numberOfWrittenBytes = !isArray
  306. ? buffer.write(key, index, undefined, 'utf8')
  307. : buffer.write(key, index, undefined, 'ascii');
  308. // Encode the name
  309. index = index + numberOfWrittenBytes;
  310. buffer[index++] = 0;
  311. // Write the date
  312. var lowBits = value.getLowBits();
  313. var highBits = value.getHighBits();
  314. // Encode low bits
  315. buffer[index++] = lowBits & 0xff;
  316. buffer[index++] = (lowBits >> 8) & 0xff;
  317. buffer[index++] = (lowBits >> 16) & 0xff;
  318. buffer[index++] = (lowBits >> 24) & 0xff;
  319. // Encode high bits
  320. buffer[index++] = highBits & 0xff;
  321. buffer[index++] = (highBits >> 8) & 0xff;
  322. buffer[index++] = (highBits >> 16) & 0xff;
  323. buffer[index++] = (highBits >> 24) & 0xff;
  324. return index;
  325. }
  326. function serializeInt32(buffer, key, value, index, isArray) {
  327. value = value.valueOf();
  328. // Set int type 32 bits or less
  329. buffer[index++] = constants.BSON_DATA_INT;
  330. // Number of written bytes
  331. var numberOfWrittenBytes = !isArray
  332. ? buffer.write(key, index, undefined, 'utf8')
  333. : buffer.write(key, index, undefined, 'ascii');
  334. // Encode the name
  335. index = index + numberOfWrittenBytes;
  336. buffer[index++] = 0;
  337. // Write the int value
  338. buffer[index++] = value & 0xff;
  339. buffer[index++] = (value >> 8) & 0xff;
  340. buffer[index++] = (value >> 16) & 0xff;
  341. buffer[index++] = (value >> 24) & 0xff;
  342. return index;
  343. }
  344. function serializeDouble(buffer, key, value, index, isArray) {
  345. // Encode as double
  346. buffer[index++] = constants.BSON_DATA_NUMBER;
  347. // Number of written bytes
  348. var numberOfWrittenBytes = !isArray
  349. ? buffer.write(key, index, undefined, 'utf8')
  350. : buffer.write(key, index, undefined, 'ascii');
  351. // Encode the name
  352. index = index + numberOfWrittenBytes;
  353. buffer[index++] = 0;
  354. // Write float
  355. float_parser_1.writeIEEE754(buffer, value.value, index, 'little', 52, 8);
  356. // Adjust index
  357. index = index + 8;
  358. return index;
  359. }
  360. function serializeFunction(buffer, key, value, index, _checkKeys, _depth, isArray) {
  361. if (_checkKeys === void 0) { _checkKeys = false; }
  362. if (_depth === void 0) { _depth = 0; }
  363. buffer[index++] = constants.BSON_DATA_CODE;
  364. // Number of written bytes
  365. var numberOfWrittenBytes = !isArray
  366. ? buffer.write(key, index, undefined, 'utf8')
  367. : buffer.write(key, index, undefined, 'ascii');
  368. // Encode the name
  369. index = index + numberOfWrittenBytes;
  370. buffer[index++] = 0;
  371. // Function string
  372. var functionString = utils_1.normalizedFunctionString(value);
  373. // Write the string
  374. var size = buffer.write(functionString, index + 4, undefined, 'utf8') + 1;
  375. // Write the size of the string to buffer
  376. buffer[index] = size & 0xff;
  377. buffer[index + 1] = (size >> 8) & 0xff;
  378. buffer[index + 2] = (size >> 16) & 0xff;
  379. buffer[index + 3] = (size >> 24) & 0xff;
  380. // Update index
  381. index = index + 4 + size - 1;
  382. // Write zero
  383. buffer[index++] = 0;
  384. return index;
  385. }
  386. function serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, isArray) {
  387. if (checkKeys === void 0) { checkKeys = false; }
  388. if (depth === void 0) { depth = 0; }
  389. if (serializeFunctions === void 0) { serializeFunctions = false; }
  390. if (ignoreUndefined === void 0) { ignoreUndefined = true; }
  391. if (isArray === void 0) { isArray = false; }
  392. if (value.scope && typeof value.scope === 'object') {
  393. // Write the type
  394. buffer[index++] = constants.BSON_DATA_CODE_W_SCOPE;
  395. // Number of written bytes
  396. var numberOfWrittenBytes = !isArray
  397. ? buffer.write(key, index, undefined, 'utf8')
  398. : buffer.write(key, index, undefined, 'ascii');
  399. // Encode the name
  400. index = index + numberOfWrittenBytes;
  401. buffer[index++] = 0;
  402. // Starting index
  403. var startIndex = index;
  404. // Serialize the function
  405. // Get the function string
  406. var functionString = typeof value.code === 'string' ? value.code : value.code.toString();
  407. // Index adjustment
  408. index = index + 4;
  409. // Write string into buffer
  410. var codeSize = buffer.write(functionString, index + 4, undefined, 'utf8') + 1;
  411. // Write the size of the string to buffer
  412. buffer[index] = codeSize & 0xff;
  413. buffer[index + 1] = (codeSize >> 8) & 0xff;
  414. buffer[index + 2] = (codeSize >> 16) & 0xff;
  415. buffer[index + 3] = (codeSize >> 24) & 0xff;
  416. // Write end 0
  417. buffer[index + 4 + codeSize - 1] = 0;
  418. // Write the
  419. index = index + codeSize + 4;
  420. //
  421. // Serialize the scope value
  422. var endIndex = serializeInto(buffer, value.scope, checkKeys, index, depth + 1, serializeFunctions, ignoreUndefined);
  423. index = endIndex - 1;
  424. // Writ the total
  425. var totalSize = endIndex - startIndex;
  426. // Write the total size of the object
  427. buffer[startIndex++] = totalSize & 0xff;
  428. buffer[startIndex++] = (totalSize >> 8) & 0xff;
  429. buffer[startIndex++] = (totalSize >> 16) & 0xff;
  430. buffer[startIndex++] = (totalSize >> 24) & 0xff;
  431. // Write trailing zero
  432. buffer[index++] = 0;
  433. }
  434. else {
  435. buffer[index++] = constants.BSON_DATA_CODE;
  436. // Number of written bytes
  437. var numberOfWrittenBytes = !isArray
  438. ? buffer.write(key, index, undefined, 'utf8')
  439. : buffer.write(key, index, undefined, 'ascii');
  440. // Encode the name
  441. index = index + numberOfWrittenBytes;
  442. buffer[index++] = 0;
  443. // Function string
  444. var functionString = value.code.toString();
  445. // Write the string
  446. var size = buffer.write(functionString, index + 4, undefined, 'utf8') + 1;
  447. // Write the size of the string to buffer
  448. buffer[index] = size & 0xff;
  449. buffer[index + 1] = (size >> 8) & 0xff;
  450. buffer[index + 2] = (size >> 16) & 0xff;
  451. buffer[index + 3] = (size >> 24) & 0xff;
  452. // Update index
  453. index = index + 4 + size - 1;
  454. // Write zero
  455. buffer[index++] = 0;
  456. }
  457. return index;
  458. }
  459. function serializeBinary(buffer, key, value, index, isArray) {
  460. // Write the type
  461. buffer[index++] = constants.BSON_DATA_BINARY;
  462. // Number of written bytes
  463. var numberOfWrittenBytes = !isArray
  464. ? buffer.write(key, index, undefined, 'utf8')
  465. : buffer.write(key, index, undefined, 'ascii');
  466. // Encode the name
  467. index = index + numberOfWrittenBytes;
  468. buffer[index++] = 0;
  469. // Extract the buffer
  470. var data = value.value(true);
  471. // Calculate size
  472. var size = value.position;
  473. // Add the deprecated 02 type 4 bytes of size to total
  474. if (value.sub_type === binary_1.Binary.SUBTYPE_BYTE_ARRAY)
  475. size = size + 4;
  476. // Write the size of the string to buffer
  477. buffer[index++] = size & 0xff;
  478. buffer[index++] = (size >> 8) & 0xff;
  479. buffer[index++] = (size >> 16) & 0xff;
  480. buffer[index++] = (size >> 24) & 0xff;
  481. // Write the subtype to the buffer
  482. buffer[index++] = value.sub_type;
  483. // If we have binary type 2 the 4 first bytes are the size
  484. if (value.sub_type === binary_1.Binary.SUBTYPE_BYTE_ARRAY) {
  485. size = size - 4;
  486. buffer[index++] = size & 0xff;
  487. buffer[index++] = (size >> 8) & 0xff;
  488. buffer[index++] = (size >> 16) & 0xff;
  489. buffer[index++] = (size >> 24) & 0xff;
  490. }
  491. // Write the data to the object
  492. buffer.set(data, index);
  493. // Adjust the index
  494. index = index + value.position;
  495. return index;
  496. }
  497. function serializeSymbol(buffer, key, value, index, isArray) {
  498. // Write the type
  499. buffer[index++] = constants.BSON_DATA_SYMBOL;
  500. // Number of written bytes
  501. var numberOfWrittenBytes = !isArray
  502. ? buffer.write(key, index, undefined, 'utf8')
  503. : buffer.write(key, index, undefined, 'ascii');
  504. // Encode the name
  505. index = index + numberOfWrittenBytes;
  506. buffer[index++] = 0;
  507. // Write the string
  508. var size = buffer.write(value.value, index + 4, undefined, 'utf8') + 1;
  509. // Write the size of the string to buffer
  510. buffer[index] = size & 0xff;
  511. buffer[index + 1] = (size >> 8) & 0xff;
  512. buffer[index + 2] = (size >> 16) & 0xff;
  513. buffer[index + 3] = (size >> 24) & 0xff;
  514. // Update index
  515. index = index + 4 + size - 1;
  516. // Write zero
  517. buffer[index++] = 0x00;
  518. return index;
  519. }
  520. function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, isArray) {
  521. // Write the type
  522. buffer[index++] = constants.BSON_DATA_OBJECT;
  523. // Number of written bytes
  524. var numberOfWrittenBytes = !isArray
  525. ? buffer.write(key, index, undefined, 'utf8')
  526. : buffer.write(key, index, undefined, 'ascii');
  527. // Encode the name
  528. index = index + numberOfWrittenBytes;
  529. buffer[index++] = 0;
  530. var startIndex = index;
  531. var output = {
  532. $ref: value.collection || value.namespace,
  533. $id: value.oid
  534. };
  535. if (value.db != null) {
  536. output.$db = value.db;
  537. }
  538. output = Object.assign(output, value.fields);
  539. var endIndex = serializeInto(buffer, output, false, index, depth + 1, serializeFunctions);
  540. // Calculate object size
  541. var size = endIndex - startIndex;
  542. // Write the size
  543. buffer[startIndex++] = size & 0xff;
  544. buffer[startIndex++] = (size >> 8) & 0xff;
  545. buffer[startIndex++] = (size >> 16) & 0xff;
  546. buffer[startIndex++] = (size >> 24) & 0xff;
  547. // Set index
  548. return endIndex;
  549. }
  550. function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializeFunctions, ignoreUndefined, path) {
  551. if (checkKeys === void 0) { checkKeys = false; }
  552. if (startingIndex === void 0) { startingIndex = 0; }
  553. if (depth === void 0) { depth = 0; }
  554. if (serializeFunctions === void 0) { serializeFunctions = false; }
  555. if (ignoreUndefined === void 0) { ignoreUndefined = true; }
  556. if (path === void 0) { path = []; }
  557. startingIndex = startingIndex || 0;
  558. path = path || [];
  559. // Push the object to the path
  560. path.push(object);
  561. // Start place to serialize into
  562. var index = startingIndex + 4;
  563. // Special case isArray
  564. if (Array.isArray(object)) {
  565. // Get object keys
  566. for (var i = 0; i < object.length; i++) {
  567. var key = '' + i;
  568. var value = object[i];
  569. // Is there an override value
  570. if (typeof (value === null || value === void 0 ? void 0 : value.toBSON) === 'function') {
  571. value = value.toBSON();
  572. }
  573. if (typeof value === 'string') {
  574. index = serializeString(buffer, key, value, index, true);
  575. }
  576. else if (typeof value === 'number') {
  577. index = serializeNumber(buffer, key, value, index, true);
  578. }
  579. else if (typeof value === 'bigint') {
  580. throw new error_1.BSONTypeError('Unsupported type BigInt, please use Decimal128');
  581. }
  582. else if (typeof value === 'boolean') {
  583. index = serializeBoolean(buffer, key, value, index, true);
  584. }
  585. else if (value instanceof Date || utils_1.isDate(value)) {
  586. index = serializeDate(buffer, key, value, index, true);
  587. }
  588. else if (value === undefined) {
  589. index = serializeNull(buffer, key, value, index, true);
  590. }
  591. else if (value === null) {
  592. index = serializeNull(buffer, key, value, index, true);
  593. }
  594. else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
  595. index = serializeObjectId(buffer, key, value, index, true);
  596. }
  597. else if (utils_1.isUint8Array(value)) {
  598. index = serializeBuffer(buffer, key, value, index, true);
  599. }
  600. else if (value instanceof RegExp || utils_1.isRegExp(value)) {
  601. index = serializeRegExp(buffer, key, value, index, true);
  602. }
  603. else if (typeof value === 'object' && value['_bsontype'] == null) {
  604. index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, true, path);
  605. }
  606. else if (typeof value === 'object' &&
  607. extended_json_1.isBSONType(value) &&
  608. value._bsontype === 'Decimal128') {
  609. index = serializeDecimal128(buffer, key, value, index, true);
  610. }
  611. else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
  612. index = serializeLong(buffer, key, value, index, true);
  613. }
  614. else if (value['_bsontype'] === 'Double') {
  615. index = serializeDouble(buffer, key, value, index, true);
  616. }
  617. else if (typeof value === 'function' && serializeFunctions) {
  618. index = serializeFunction(buffer, key, value, index, checkKeys, depth, true);
  619. }
  620. else if (value['_bsontype'] === 'Code') {
  621. index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, true);
  622. }
  623. else if (value['_bsontype'] === 'Binary') {
  624. index = serializeBinary(buffer, key, value, index, true);
  625. }
  626. else if (value['_bsontype'] === 'Symbol') {
  627. index = serializeSymbol(buffer, key, value, index, true);
  628. }
  629. else if (value['_bsontype'] === 'DBRef') {
  630. index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, true);
  631. }
  632. else if (value['_bsontype'] === 'BSONRegExp') {
  633. index = serializeBSONRegExp(buffer, key, value, index, true);
  634. }
  635. else if (value['_bsontype'] === 'Int32') {
  636. index = serializeInt32(buffer, key, value, index, true);
  637. }
  638. else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
  639. index = serializeMinMax(buffer, key, value, index, true);
  640. }
  641. else if (typeof value['_bsontype'] !== 'undefined') {
  642. throw new error_1.BSONTypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
  643. }
  644. }
  645. }
  646. else if (object instanceof map_1.Map || utils_1.isMap(object)) {
  647. var iterator = object.entries();
  648. var done = false;
  649. while (!done) {
  650. // Unpack the next entry
  651. var entry = iterator.next();
  652. done = !!entry.done;
  653. // Are we done, then skip and terminate
  654. if (done)
  655. continue;
  656. // Get the entry values
  657. var key = entry.value[0];
  658. var value = entry.value[1];
  659. // Check the type of the value
  660. var type = typeof value;
  661. // Check the key and throw error if it's illegal
  662. if (typeof key === 'string' && !ignoreKeys.has(key)) {
  663. if (key.match(regexp) != null) {
  664. // The BSON spec doesn't allow keys with null bytes because keys are
  665. // null-terminated.
  666. throw Error('key ' + key + ' must not contain null bytes');
  667. }
  668. if (checkKeys) {
  669. if ('$' === key[0]) {
  670. throw Error('key ' + key + " must not start with '$'");
  671. }
  672. else if (~key.indexOf('.')) {
  673. throw Error('key ' + key + " must not contain '.'");
  674. }
  675. }
  676. }
  677. if (type === 'string') {
  678. index = serializeString(buffer, key, value, index);
  679. }
  680. else if (type === 'number') {
  681. index = serializeNumber(buffer, key, value, index);
  682. }
  683. else if (type === 'bigint' || utils_1.isBigInt64Array(value) || utils_1.isBigUInt64Array(value)) {
  684. throw new error_1.BSONTypeError('Unsupported type BigInt, please use Decimal128');
  685. }
  686. else if (type === 'boolean') {
  687. index = serializeBoolean(buffer, key, value, index);
  688. }
  689. else if (value instanceof Date || utils_1.isDate(value)) {
  690. index = serializeDate(buffer, key, value, index);
  691. }
  692. else if (value === null || (value === undefined && ignoreUndefined === false)) {
  693. index = serializeNull(buffer, key, value, index);
  694. }
  695. else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
  696. index = serializeObjectId(buffer, key, value, index);
  697. }
  698. else if (utils_1.isUint8Array(value)) {
  699. index = serializeBuffer(buffer, key, value, index);
  700. }
  701. else if (value instanceof RegExp || utils_1.isRegExp(value)) {
  702. index = serializeRegExp(buffer, key, value, index);
  703. }
  704. else if (type === 'object' && value['_bsontype'] == null) {
  705. index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, false, path);
  706. }
  707. else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
  708. index = serializeDecimal128(buffer, key, value, index);
  709. }
  710. else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
  711. index = serializeLong(buffer, key, value, index);
  712. }
  713. else if (value['_bsontype'] === 'Double') {
  714. index = serializeDouble(buffer, key, value, index);
  715. }
  716. else if (value['_bsontype'] === 'Code') {
  717. index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined);
  718. }
  719. else if (typeof value === 'function' && serializeFunctions) {
  720. index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
  721. }
  722. else if (value['_bsontype'] === 'Binary') {
  723. index = serializeBinary(buffer, key, value, index);
  724. }
  725. else if (value['_bsontype'] === 'Symbol') {
  726. index = serializeSymbol(buffer, key, value, index);
  727. }
  728. else if (value['_bsontype'] === 'DBRef') {
  729. index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
  730. }
  731. else if (value['_bsontype'] === 'BSONRegExp') {
  732. index = serializeBSONRegExp(buffer, key, value, index);
  733. }
  734. else if (value['_bsontype'] === 'Int32') {
  735. index = serializeInt32(buffer, key, value, index);
  736. }
  737. else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
  738. index = serializeMinMax(buffer, key, value, index);
  739. }
  740. else if (typeof value['_bsontype'] !== 'undefined') {
  741. throw new error_1.BSONTypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
  742. }
  743. }
  744. }
  745. else {
  746. if (typeof (object === null || object === void 0 ? void 0 : object.toBSON) === 'function') {
  747. // Provided a custom serialization method
  748. object = object.toBSON();
  749. if (object != null && typeof object !== 'object') {
  750. throw new error_1.BSONTypeError('toBSON function did not return an object');
  751. }
  752. }
  753. // Iterate over all the keys
  754. for (var key in object) {
  755. var value = object[key];
  756. // Is there an override value
  757. if (typeof (value === null || value === void 0 ? void 0 : value.toBSON) === 'function') {
  758. value = value.toBSON();
  759. }
  760. // Check the type of the value
  761. var type = typeof value;
  762. // Check the key and throw error if it's illegal
  763. if (typeof key === 'string' && !ignoreKeys.has(key)) {
  764. if (key.match(regexp) != null) {
  765. // The BSON spec doesn't allow keys with null bytes because keys are
  766. // null-terminated.
  767. throw Error('key ' + key + ' must not contain null bytes');
  768. }
  769. if (checkKeys) {
  770. if ('$' === key[0]) {
  771. throw Error('key ' + key + " must not start with '$'");
  772. }
  773. else if (~key.indexOf('.')) {
  774. throw Error('key ' + key + " must not contain '.'");
  775. }
  776. }
  777. }
  778. if (type === 'string') {
  779. index = serializeString(buffer, key, value, index);
  780. }
  781. else if (type === 'number') {
  782. index = serializeNumber(buffer, key, value, index);
  783. }
  784. else if (type === 'bigint') {
  785. throw new error_1.BSONTypeError('Unsupported type BigInt, please use Decimal128');
  786. }
  787. else if (type === 'boolean') {
  788. index = serializeBoolean(buffer, key, value, index);
  789. }
  790. else if (value instanceof Date || utils_1.isDate(value)) {
  791. index = serializeDate(buffer, key, value, index);
  792. }
  793. else if (value === undefined) {
  794. if (ignoreUndefined === false)
  795. index = serializeNull(buffer, key, value, index);
  796. }
  797. else if (value === null) {
  798. index = serializeNull(buffer, key, value, index);
  799. }
  800. else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
  801. index = serializeObjectId(buffer, key, value, index);
  802. }
  803. else if (utils_1.isUint8Array(value)) {
  804. index = serializeBuffer(buffer, key, value, index);
  805. }
  806. else if (value instanceof RegExp || utils_1.isRegExp(value)) {
  807. index = serializeRegExp(buffer, key, value, index);
  808. }
  809. else if (type === 'object' && value['_bsontype'] == null) {
  810. index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, false, path);
  811. }
  812. else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
  813. index = serializeDecimal128(buffer, key, value, index);
  814. }
  815. else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
  816. index = serializeLong(buffer, key, value, index);
  817. }
  818. else if (value['_bsontype'] === 'Double') {
  819. index = serializeDouble(buffer, key, value, index);
  820. }
  821. else if (value['_bsontype'] === 'Code') {
  822. index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined);
  823. }
  824. else if (typeof value === 'function' && serializeFunctions) {
  825. index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
  826. }
  827. else if (value['_bsontype'] === 'Binary') {
  828. index = serializeBinary(buffer, key, value, index);
  829. }
  830. else if (value['_bsontype'] === 'Symbol') {
  831. index = serializeSymbol(buffer, key, value, index);
  832. }
  833. else if (value['_bsontype'] === 'DBRef') {
  834. index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
  835. }
  836. else if (value['_bsontype'] === 'BSONRegExp') {
  837. index = serializeBSONRegExp(buffer, key, value, index);
  838. }
  839. else if (value['_bsontype'] === 'Int32') {
  840. index = serializeInt32(buffer, key, value, index);
  841. }
  842. else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
  843. index = serializeMinMax(buffer, key, value, index);
  844. }
  845. else if (typeof value['_bsontype'] !== 'undefined') {
  846. throw new error_1.BSONTypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
  847. }
  848. }
  849. }
  850. // Remove the path
  851. path.pop();
  852. // Final padding byte for object
  853. buffer[index++] = 0x00;
  854. // Final size
  855. var size = index - startingIndex;
  856. // Write the size of the object
  857. buffer[startingIndex++] = size & 0xff;
  858. buffer[startingIndex++] = (size >> 8) & 0xff;
  859. buffer[startingIndex++] = (size >> 16) & 0xff;
  860. buffer[startingIndex++] = (size >> 24) & 0xff;
  861. return index;
  862. }
  863. exports.serializeInto = serializeInto;
  864. //# sourceMappingURL=serializer.js.map