serializer.js 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194
  1. 'use strict';
  2. var writeIEEE754 = require('../float_parser').writeIEEE754,
  3. Long = require('../long').Long,
  4. Map = require('../map'),
  5. Binary = require('../binary').Binary;
  6. var normalizedFunctionString = require('./utils').normalizedFunctionString;
  7. // try {
  8. // var _Buffer = Uint8Array;
  9. // } catch (e) {
  10. // _Buffer = Buffer;
  11. // }
  12. var regexp = /\x00/; // eslint-disable-line no-control-regex
  13. var ignoreKeys = ['$db', '$ref', '$id', '$clusterTime'];
  14. // To ensure that 0.4 of node works correctly
  15. var isDate = function isDate(d) {
  16. return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]';
  17. };
  18. var isRegExp = function isRegExp(d) {
  19. return Object.prototype.toString.call(d) === '[object RegExp]';
  20. };
  21. var serializeString = function(buffer, key, value, index, isArray) {
  22. // Encode String type
  23. buffer[index++] = BSON.BSON_DATA_STRING;
  24. // Number of written bytes
  25. var numberOfWrittenBytes = !isArray
  26. ? buffer.write(key, index, 'utf8')
  27. : buffer.write(key, index, 'ascii');
  28. // Encode the name
  29. index = index + numberOfWrittenBytes + 1;
  30. buffer[index - 1] = 0;
  31. // Write the string
  32. var size = buffer.write(value, index + 4, 'utf8');
  33. // Write the size of the string to buffer
  34. buffer[index + 3] = ((size + 1) >> 24) & 0xff;
  35. buffer[index + 2] = ((size + 1) >> 16) & 0xff;
  36. buffer[index + 1] = ((size + 1) >> 8) & 0xff;
  37. buffer[index] = (size + 1) & 0xff;
  38. // Update index
  39. index = index + 4 + size;
  40. // Write zero
  41. buffer[index++] = 0;
  42. return index;
  43. };
  44. var serializeNumber = function(buffer, key, value, index, isArray) {
  45. // We have an integer value
  46. if (Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
  47. // If the value fits in 32 bits encode as int, if it fits in a double
  48. // encode it as a double, otherwise long
  49. if (value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) {
  50. // Set int type 32 bits or less
  51. buffer[index++] = BSON.BSON_DATA_INT;
  52. // Number of written bytes
  53. var numberOfWrittenBytes = !isArray
  54. ? buffer.write(key, index, 'utf8')
  55. : buffer.write(key, index, '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. } else if (value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
  65. // Encode as double
  66. buffer[index++] = BSON.BSON_DATA_NUMBER;
  67. // Number of written bytes
  68. numberOfWrittenBytes = !isArray
  69. ? buffer.write(key, index, 'utf8')
  70. : buffer.write(key, index, 'ascii');
  71. // Encode the name
  72. index = index + numberOfWrittenBytes;
  73. buffer[index++] = 0;
  74. // Write float
  75. writeIEEE754(buffer, value, index, 'little', 52, 8);
  76. // Ajust index
  77. index = index + 8;
  78. } else {
  79. // Set long type
  80. buffer[index++] = BSON.BSON_DATA_LONG;
  81. // Number of written bytes
  82. numberOfWrittenBytes = !isArray
  83. ? buffer.write(key, index, 'utf8')
  84. : buffer.write(key, index, 'ascii');
  85. // Encode the name
  86. index = index + numberOfWrittenBytes;
  87. buffer[index++] = 0;
  88. var longVal = Long.fromNumber(value);
  89. var lowBits = longVal.getLowBits();
  90. var highBits = longVal.getHighBits();
  91. // Encode low bits
  92. buffer[index++] = lowBits & 0xff;
  93. buffer[index++] = (lowBits >> 8) & 0xff;
  94. buffer[index++] = (lowBits >> 16) & 0xff;
  95. buffer[index++] = (lowBits >> 24) & 0xff;
  96. // Encode high bits
  97. buffer[index++] = highBits & 0xff;
  98. buffer[index++] = (highBits >> 8) & 0xff;
  99. buffer[index++] = (highBits >> 16) & 0xff;
  100. buffer[index++] = (highBits >> 24) & 0xff;
  101. }
  102. } else {
  103. // Encode as double
  104. buffer[index++] = BSON.BSON_DATA_NUMBER;
  105. // Number of written bytes
  106. numberOfWrittenBytes = !isArray
  107. ? buffer.write(key, index, 'utf8')
  108. : buffer.write(key, index, 'ascii');
  109. // Encode the name
  110. index = index + numberOfWrittenBytes;
  111. buffer[index++] = 0;
  112. // Write float
  113. writeIEEE754(buffer, value, index, 'little', 52, 8);
  114. // Ajust index
  115. index = index + 8;
  116. }
  117. return index;
  118. };
  119. var serializeNull = function(buffer, key, value, index, isArray) {
  120. // Set long type
  121. buffer[index++] = BSON.BSON_DATA_NULL;
  122. // Number of written bytes
  123. var numberOfWrittenBytes = !isArray
  124. ? buffer.write(key, index, 'utf8')
  125. : buffer.write(key, index, 'ascii');
  126. // Encode the name
  127. index = index + numberOfWrittenBytes;
  128. buffer[index++] = 0;
  129. return index;
  130. };
  131. var serializeBoolean = function(buffer, key, value, index, isArray) {
  132. // Write the type
  133. buffer[index++] = BSON.BSON_DATA_BOOLEAN;
  134. // Number of written bytes
  135. var numberOfWrittenBytes = !isArray
  136. ? buffer.write(key, index, 'utf8')
  137. : buffer.write(key, index, 'ascii');
  138. // Encode the name
  139. index = index + numberOfWrittenBytes;
  140. buffer[index++] = 0;
  141. // Encode the boolean value
  142. buffer[index++] = value ? 1 : 0;
  143. return index;
  144. };
  145. var serializeDate = function(buffer, key, value, index, isArray) {
  146. // Write the type
  147. buffer[index++] = BSON.BSON_DATA_DATE;
  148. // Number of written bytes
  149. var numberOfWrittenBytes = !isArray
  150. ? buffer.write(key, index, 'utf8')
  151. : buffer.write(key, index, 'ascii');
  152. // Encode the name
  153. index = index + numberOfWrittenBytes;
  154. buffer[index++] = 0;
  155. // Write the date
  156. var dateInMilis = Long.fromNumber(value.getTime());
  157. var lowBits = dateInMilis.getLowBits();
  158. var highBits = dateInMilis.getHighBits();
  159. // Encode low bits
  160. buffer[index++] = lowBits & 0xff;
  161. buffer[index++] = (lowBits >> 8) & 0xff;
  162. buffer[index++] = (lowBits >> 16) & 0xff;
  163. buffer[index++] = (lowBits >> 24) & 0xff;
  164. // Encode high bits
  165. buffer[index++] = highBits & 0xff;
  166. buffer[index++] = (highBits >> 8) & 0xff;
  167. buffer[index++] = (highBits >> 16) & 0xff;
  168. buffer[index++] = (highBits >> 24) & 0xff;
  169. return index;
  170. };
  171. var serializeRegExp = function(buffer, key, value, index, isArray) {
  172. // Write the type
  173. buffer[index++] = BSON.BSON_DATA_REGEXP;
  174. // Number of written bytes
  175. var numberOfWrittenBytes = !isArray
  176. ? buffer.write(key, index, 'utf8')
  177. : buffer.write(key, index, 'ascii');
  178. // Encode the name
  179. index = index + numberOfWrittenBytes;
  180. buffer[index++] = 0;
  181. if (value.source && value.source.match(regexp) != null) {
  182. throw Error('value ' + value.source + ' must not contain null bytes');
  183. }
  184. // Adjust the index
  185. index = index + buffer.write(value.source, index, 'utf8');
  186. // Write zero
  187. buffer[index++] = 0x00;
  188. // Write the parameters
  189. if (value.global) buffer[index++] = 0x73; // s
  190. if (value.ignoreCase) buffer[index++] = 0x69; // i
  191. if (value.multiline) buffer[index++] = 0x6d; // m
  192. // Add ending zero
  193. buffer[index++] = 0x00;
  194. return index;
  195. };
  196. var serializeBSONRegExp = function(buffer, key, value, index, isArray) {
  197. // Write the type
  198. buffer[index++] = BSON.BSON_DATA_REGEXP;
  199. // Number of written bytes
  200. var numberOfWrittenBytes = !isArray
  201. ? buffer.write(key, index, 'utf8')
  202. : buffer.write(key, index, 'ascii');
  203. // Encode the name
  204. index = index + numberOfWrittenBytes;
  205. buffer[index++] = 0;
  206. // Check the pattern for 0 bytes
  207. if (value.pattern.match(regexp) != null) {
  208. // The BSON spec doesn't allow keys with null bytes because keys are
  209. // null-terminated.
  210. throw Error('pattern ' + value.pattern + ' must not contain null bytes');
  211. }
  212. // Adjust the index
  213. index = index + buffer.write(value.pattern, index, 'utf8');
  214. // Write zero
  215. buffer[index++] = 0x00;
  216. // Write the options
  217. index =
  218. index +
  219. buffer.write(
  220. value.options
  221. .split('')
  222. .sort()
  223. .join(''),
  224. index,
  225. 'utf8'
  226. );
  227. // Add ending zero
  228. buffer[index++] = 0x00;
  229. return index;
  230. };
  231. var serializeMinMax = function(buffer, key, value, index, isArray) {
  232. // Write the type of either min or max key
  233. if (value === null) {
  234. buffer[index++] = BSON.BSON_DATA_NULL;
  235. } else if (value._bsontype === 'MinKey') {
  236. buffer[index++] = BSON.BSON_DATA_MIN_KEY;
  237. } else {
  238. buffer[index++] = BSON.BSON_DATA_MAX_KEY;
  239. }
  240. // Number of written bytes
  241. var numberOfWrittenBytes = !isArray
  242. ? buffer.write(key, index, 'utf8')
  243. : buffer.write(key, index, 'ascii');
  244. // Encode the name
  245. index = index + numberOfWrittenBytes;
  246. buffer[index++] = 0;
  247. return index;
  248. };
  249. var serializeObjectId = function(buffer, key, value, index, isArray) {
  250. // Write the type
  251. buffer[index++] = BSON.BSON_DATA_OID;
  252. // Number of written bytes
  253. var numberOfWrittenBytes = !isArray
  254. ? buffer.write(key, index, 'utf8')
  255. : buffer.write(key, index, 'ascii');
  256. // Encode the name
  257. index = index + numberOfWrittenBytes;
  258. buffer[index++] = 0;
  259. // Write the objectId into the shared buffer
  260. if (typeof value.id === 'string') {
  261. buffer.write(value.id, index, 'binary');
  262. } else if (value.id && value.id.copy) {
  263. value.id.copy(buffer, index, 0, 12);
  264. } else {
  265. throw new Error('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
  266. }
  267. // Ajust index
  268. return index + 12;
  269. };
  270. var serializeBuffer = function(buffer, key, value, index, isArray) {
  271. // Write the type
  272. buffer[index++] = BSON.BSON_DATA_BINARY;
  273. // Number of written bytes
  274. var numberOfWrittenBytes = !isArray
  275. ? buffer.write(key, index, 'utf8')
  276. : buffer.write(key, index, 'ascii');
  277. // Encode the name
  278. index = index + numberOfWrittenBytes;
  279. buffer[index++] = 0;
  280. // Get size of the buffer (current write point)
  281. var size = value.length;
  282. // Write the size of the string to buffer
  283. buffer[index++] = size & 0xff;
  284. buffer[index++] = (size >> 8) & 0xff;
  285. buffer[index++] = (size >> 16) & 0xff;
  286. buffer[index++] = (size >> 24) & 0xff;
  287. // Write the default subtype
  288. buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT;
  289. // Copy the content form the binary field to the buffer
  290. value.copy(buffer, index, 0, size);
  291. // Adjust the index
  292. index = index + size;
  293. return index;
  294. };
  295. var serializeObject = function(
  296. buffer,
  297. key,
  298. value,
  299. index,
  300. checkKeys,
  301. depth,
  302. serializeFunctions,
  303. ignoreUndefined,
  304. isArray,
  305. path
  306. ) {
  307. for (var i = 0; i < path.length; i++) {
  308. if (path[i] === value) throw new Error('cyclic dependency detected');
  309. }
  310. // Push value to stack
  311. path.push(value);
  312. // Write the type
  313. buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT;
  314. // Number of written bytes
  315. var numberOfWrittenBytes = !isArray
  316. ? buffer.write(key, index, 'utf8')
  317. : buffer.write(key, index, 'ascii');
  318. // Encode the name
  319. index = index + numberOfWrittenBytes;
  320. buffer[index++] = 0;
  321. var endIndex = serializeInto(
  322. buffer,
  323. value,
  324. checkKeys,
  325. index,
  326. depth + 1,
  327. serializeFunctions,
  328. ignoreUndefined,
  329. path
  330. );
  331. // Pop stack
  332. path.pop();
  333. // Write size
  334. return endIndex;
  335. };
  336. var serializeDecimal128 = function(buffer, key, value, index, isArray) {
  337. buffer[index++] = BSON.BSON_DATA_DECIMAL128;
  338. // Number of written bytes
  339. var numberOfWrittenBytes = !isArray
  340. ? buffer.write(key, index, 'utf8')
  341. : buffer.write(key, index, 'ascii');
  342. // Encode the name
  343. index = index + numberOfWrittenBytes;
  344. buffer[index++] = 0;
  345. // Write the data from the value
  346. value.bytes.copy(buffer, index, 0, 16);
  347. return index + 16;
  348. };
  349. var serializeLong = function(buffer, key, value, index, isArray) {
  350. // Write the type
  351. buffer[index++] = value._bsontype === 'Long' ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP;
  352. // Number of written bytes
  353. var numberOfWrittenBytes = !isArray
  354. ? buffer.write(key, index, 'utf8')
  355. : buffer.write(key, index, 'ascii');
  356. // Encode the name
  357. index = index + numberOfWrittenBytes;
  358. buffer[index++] = 0;
  359. // Write the date
  360. var lowBits = value.getLowBits();
  361. var highBits = value.getHighBits();
  362. // Encode low bits
  363. buffer[index++] = lowBits & 0xff;
  364. buffer[index++] = (lowBits >> 8) & 0xff;
  365. buffer[index++] = (lowBits >> 16) & 0xff;
  366. buffer[index++] = (lowBits >> 24) & 0xff;
  367. // Encode high bits
  368. buffer[index++] = highBits & 0xff;
  369. buffer[index++] = (highBits >> 8) & 0xff;
  370. buffer[index++] = (highBits >> 16) & 0xff;
  371. buffer[index++] = (highBits >> 24) & 0xff;
  372. return index;
  373. };
  374. var serializeInt32 = function(buffer, key, value, index, isArray) {
  375. // Set int type 32 bits or less
  376. buffer[index++] = BSON.BSON_DATA_INT;
  377. // Number of written bytes
  378. var numberOfWrittenBytes = !isArray
  379. ? buffer.write(key, index, 'utf8')
  380. : buffer.write(key, index, 'ascii');
  381. // Encode the name
  382. index = index + numberOfWrittenBytes;
  383. buffer[index++] = 0;
  384. // Write the int value
  385. buffer[index++] = value & 0xff;
  386. buffer[index++] = (value >> 8) & 0xff;
  387. buffer[index++] = (value >> 16) & 0xff;
  388. buffer[index++] = (value >> 24) & 0xff;
  389. return index;
  390. };
  391. var serializeDouble = function(buffer, key, value, index, isArray) {
  392. // Encode as double
  393. buffer[index++] = BSON.BSON_DATA_NUMBER;
  394. // Number of written bytes
  395. var numberOfWrittenBytes = !isArray
  396. ? buffer.write(key, index, 'utf8')
  397. : buffer.write(key, index, 'ascii');
  398. // Encode the name
  399. index = index + numberOfWrittenBytes;
  400. buffer[index++] = 0;
  401. // Write float
  402. writeIEEE754(buffer, value, index, 'little', 52, 8);
  403. // Ajust index
  404. index = index + 8;
  405. return index;
  406. };
  407. var serializeFunction = function(buffer, key, value, index, checkKeys, depth, isArray) {
  408. buffer[index++] = BSON.BSON_DATA_CODE;
  409. // Number of written bytes
  410. var numberOfWrittenBytes = !isArray
  411. ? buffer.write(key, index, 'utf8')
  412. : buffer.write(key, index, 'ascii');
  413. // Encode the name
  414. index = index + numberOfWrittenBytes;
  415. buffer[index++] = 0;
  416. // Function string
  417. var functionString = normalizedFunctionString(value);
  418. // Write the string
  419. var size = buffer.write(functionString, index + 4, 'utf8') + 1;
  420. // Write the size of the string to buffer
  421. buffer[index] = size & 0xff;
  422. buffer[index + 1] = (size >> 8) & 0xff;
  423. buffer[index + 2] = (size >> 16) & 0xff;
  424. buffer[index + 3] = (size >> 24) & 0xff;
  425. // Update index
  426. index = index + 4 + size - 1;
  427. // Write zero
  428. buffer[index++] = 0;
  429. return index;
  430. };
  431. var serializeCode = function(
  432. buffer,
  433. key,
  434. value,
  435. index,
  436. checkKeys,
  437. depth,
  438. serializeFunctions,
  439. ignoreUndefined,
  440. isArray
  441. ) {
  442. if (value.scope && typeof value.scope === 'object') {
  443. // Write the type
  444. buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE;
  445. // Number of written bytes
  446. var numberOfWrittenBytes = !isArray
  447. ? buffer.write(key, index, 'utf8')
  448. : buffer.write(key, index, 'ascii');
  449. // Encode the name
  450. index = index + numberOfWrittenBytes;
  451. buffer[index++] = 0;
  452. // Starting index
  453. var startIndex = index;
  454. // Serialize the function
  455. // Get the function string
  456. var functionString = typeof value.code === 'string' ? value.code : value.code.toString();
  457. // Index adjustment
  458. index = index + 4;
  459. // Write string into buffer
  460. var codeSize = buffer.write(functionString, index + 4, 'utf8') + 1;
  461. // Write the size of the string to buffer
  462. buffer[index] = codeSize & 0xff;
  463. buffer[index + 1] = (codeSize >> 8) & 0xff;
  464. buffer[index + 2] = (codeSize >> 16) & 0xff;
  465. buffer[index + 3] = (codeSize >> 24) & 0xff;
  466. // Write end 0
  467. buffer[index + 4 + codeSize - 1] = 0;
  468. // Write the
  469. index = index + codeSize + 4;
  470. //
  471. // Serialize the scope value
  472. var endIndex = serializeInto(
  473. buffer,
  474. value.scope,
  475. checkKeys,
  476. index,
  477. depth + 1,
  478. serializeFunctions,
  479. ignoreUndefined
  480. );
  481. index = endIndex - 1;
  482. // Writ the total
  483. var totalSize = endIndex - startIndex;
  484. // Write the total size of the object
  485. buffer[startIndex++] = totalSize & 0xff;
  486. buffer[startIndex++] = (totalSize >> 8) & 0xff;
  487. buffer[startIndex++] = (totalSize >> 16) & 0xff;
  488. buffer[startIndex++] = (totalSize >> 24) & 0xff;
  489. // Write trailing zero
  490. buffer[index++] = 0;
  491. } else {
  492. buffer[index++] = BSON.BSON_DATA_CODE;
  493. // Number of written bytes
  494. numberOfWrittenBytes = !isArray
  495. ? buffer.write(key, index, 'utf8')
  496. : buffer.write(key, index, 'ascii');
  497. // Encode the name
  498. index = index + numberOfWrittenBytes;
  499. buffer[index++] = 0;
  500. // Function string
  501. functionString = value.code.toString();
  502. // Write the string
  503. var size = buffer.write(functionString, index + 4, 'utf8') + 1;
  504. // Write the size of the string to buffer
  505. buffer[index] = size & 0xff;
  506. buffer[index + 1] = (size >> 8) & 0xff;
  507. buffer[index + 2] = (size >> 16) & 0xff;
  508. buffer[index + 3] = (size >> 24) & 0xff;
  509. // Update index
  510. index = index + 4 + size - 1;
  511. // Write zero
  512. buffer[index++] = 0;
  513. }
  514. return index;
  515. };
  516. var serializeBinary = function(buffer, key, value, index, isArray) {
  517. // Write the type
  518. buffer[index++] = BSON.BSON_DATA_BINARY;
  519. // Number of written bytes
  520. var numberOfWrittenBytes = !isArray
  521. ? buffer.write(key, index, 'utf8')
  522. : buffer.write(key, index, 'ascii');
  523. // Encode the name
  524. index = index + numberOfWrittenBytes;
  525. buffer[index++] = 0;
  526. // Extract the buffer
  527. var data = value.value(true);
  528. // Calculate size
  529. var size = value.position;
  530. // Add the deprecated 02 type 4 bytes of size to total
  531. if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) size = size + 4;
  532. // Write the size of the string to buffer
  533. buffer[index++] = size & 0xff;
  534. buffer[index++] = (size >> 8) & 0xff;
  535. buffer[index++] = (size >> 16) & 0xff;
  536. buffer[index++] = (size >> 24) & 0xff;
  537. // Write the subtype to the buffer
  538. buffer[index++] = value.sub_type;
  539. // If we have binary type 2 the 4 first bytes are the size
  540. if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
  541. size = size - 4;
  542. buffer[index++] = size & 0xff;
  543. buffer[index++] = (size >> 8) & 0xff;
  544. buffer[index++] = (size >> 16) & 0xff;
  545. buffer[index++] = (size >> 24) & 0xff;
  546. }
  547. // Write the data to the object
  548. data.copy(buffer, index, 0, value.position);
  549. // Adjust the index
  550. index = index + value.position;
  551. return index;
  552. };
  553. var serializeSymbol = function(buffer, key, value, index, isArray) {
  554. // Write the type
  555. buffer[index++] = BSON.BSON_DATA_SYMBOL;
  556. // Number of written bytes
  557. var numberOfWrittenBytes = !isArray
  558. ? buffer.write(key, index, 'utf8')
  559. : buffer.write(key, index, 'ascii');
  560. // Encode the name
  561. index = index + numberOfWrittenBytes;
  562. buffer[index++] = 0;
  563. // Write the string
  564. var size = buffer.write(value.value, index + 4, 'utf8') + 1;
  565. // Write the size of the string to buffer
  566. buffer[index] = size & 0xff;
  567. buffer[index + 1] = (size >> 8) & 0xff;
  568. buffer[index + 2] = (size >> 16) & 0xff;
  569. buffer[index + 3] = (size >> 24) & 0xff;
  570. // Update index
  571. index = index + 4 + size - 1;
  572. // Write zero
  573. buffer[index++] = 0x00;
  574. return index;
  575. };
  576. var serializeDBRef = function(buffer, key, value, index, depth, serializeFunctions, isArray) {
  577. // Write the type
  578. buffer[index++] = BSON.BSON_DATA_OBJECT;
  579. // Number of written bytes
  580. var numberOfWrittenBytes = !isArray
  581. ? buffer.write(key, index, 'utf8')
  582. : buffer.write(key, index, 'ascii');
  583. // Encode the name
  584. index = index + numberOfWrittenBytes;
  585. buffer[index++] = 0;
  586. var startIndex = index;
  587. var endIndex;
  588. // Serialize object
  589. if (null != value.db) {
  590. endIndex = serializeInto(
  591. buffer,
  592. {
  593. $ref: value.namespace,
  594. $id: value.oid,
  595. $db: value.db
  596. },
  597. false,
  598. index,
  599. depth + 1,
  600. serializeFunctions
  601. );
  602. } else {
  603. endIndex = serializeInto(
  604. buffer,
  605. {
  606. $ref: value.namespace,
  607. $id: value.oid
  608. },
  609. false,
  610. index,
  611. depth + 1,
  612. serializeFunctions
  613. );
  614. }
  615. // Calculate object size
  616. var size = endIndex - startIndex;
  617. // Write the size
  618. buffer[startIndex++] = size & 0xff;
  619. buffer[startIndex++] = (size >> 8) & 0xff;
  620. buffer[startIndex++] = (size >> 16) & 0xff;
  621. buffer[startIndex++] = (size >> 24) & 0xff;
  622. // Set index
  623. return endIndex;
  624. };
  625. var serializeInto = function serializeInto(
  626. buffer,
  627. object,
  628. checkKeys,
  629. startingIndex,
  630. depth,
  631. serializeFunctions,
  632. ignoreUndefined,
  633. path
  634. ) {
  635. startingIndex = startingIndex || 0;
  636. path = path || [];
  637. // Push the object to the path
  638. path.push(object);
  639. // Start place to serialize into
  640. var index = startingIndex + 4;
  641. // var self = this;
  642. // Special case isArray
  643. if (Array.isArray(object)) {
  644. // Get object keys
  645. for (var i = 0; i < object.length; i++) {
  646. var key = '' + i;
  647. var value = object[i];
  648. // Is there an override value
  649. if (value && value.toBSON) {
  650. if (typeof value.toBSON !== 'function') throw new Error('toBSON is not a function');
  651. value = value.toBSON();
  652. }
  653. var type = typeof value;
  654. if (type === 'string') {
  655. index = serializeString(buffer, key, value, index, true);
  656. } else if (type === 'number') {
  657. index = serializeNumber(buffer, key, value, index, true);
  658. } else if(type === 'bigint') {
  659. throw new TypeError('Unsupported type BigInt, please use Decimal128');
  660. } else if (type === 'boolean') {
  661. index = serializeBoolean(buffer, key, value, index, true);
  662. } else if (value instanceof Date || isDate(value)) {
  663. index = serializeDate(buffer, key, value, index, true);
  664. } else if (value === undefined) {
  665. index = serializeNull(buffer, key, value, index, true);
  666. } else if (value === null) {
  667. index = serializeNull(buffer, key, value, index, true);
  668. } else if (value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') {
  669. index = serializeObjectId(buffer, key, value, index, true);
  670. } else if (Buffer.isBuffer(value)) {
  671. index = serializeBuffer(buffer, key, value, index, true);
  672. } else if (value instanceof RegExp || isRegExp(value)) {
  673. index = serializeRegExp(buffer, key, value, index, true);
  674. } else if (type === 'object' && value['_bsontype'] == null) {
  675. index = serializeObject(
  676. buffer,
  677. key,
  678. value,
  679. index,
  680. checkKeys,
  681. depth,
  682. serializeFunctions,
  683. ignoreUndefined,
  684. true,
  685. path
  686. );
  687. } else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
  688. index = serializeDecimal128(buffer, key, value, index, true);
  689. } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
  690. index = serializeLong(buffer, key, value, index, true);
  691. } else if (value['_bsontype'] === 'Double') {
  692. index = serializeDouble(buffer, key, value, index, true);
  693. } else if (typeof value === 'function' && serializeFunctions) {
  694. index = serializeFunction(
  695. buffer,
  696. key,
  697. value,
  698. index,
  699. checkKeys,
  700. depth,
  701. serializeFunctions,
  702. true
  703. );
  704. } else if (value['_bsontype'] === 'Code') {
  705. index = serializeCode(
  706. buffer,
  707. key,
  708. value,
  709. index,
  710. checkKeys,
  711. depth,
  712. serializeFunctions,
  713. ignoreUndefined,
  714. true
  715. );
  716. } else if (value['_bsontype'] === 'Binary') {
  717. index = serializeBinary(buffer, key, value, index, true);
  718. } else if (value['_bsontype'] === 'Symbol') {
  719. index = serializeSymbol(buffer, key, value, index, true);
  720. } else if (value['_bsontype'] === 'DBRef') {
  721. index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, true);
  722. } else if (value['_bsontype'] === 'BSONRegExp') {
  723. index = serializeBSONRegExp(buffer, key, value, index, true);
  724. } else if (value['_bsontype'] === 'Int32') {
  725. index = serializeInt32(buffer, key, value, index, true);
  726. } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
  727. index = serializeMinMax(buffer, key, value, index, true);
  728. } else if (typeof value['_bsontype'] !== 'undefined') {
  729. throw new TypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
  730. }
  731. }
  732. } else if (object instanceof Map) {
  733. var iterator = object.entries();
  734. var done = false;
  735. while (!done) {
  736. // Unpack the next entry
  737. var entry = iterator.next();
  738. done = entry.done;
  739. // Are we done, then skip and terminate
  740. if (done) continue;
  741. // Get the entry values
  742. key = entry.value[0];
  743. value = entry.value[1];
  744. // Check the type of the value
  745. type = typeof value;
  746. // Check the key and throw error if it's illegal
  747. if (typeof key === 'string' && ignoreKeys.indexOf(key) === -1) {
  748. if (key.match(regexp) != null) {
  749. // The BSON spec doesn't allow keys with null bytes because keys are
  750. // null-terminated.
  751. throw Error('key ' + key + ' must not contain null bytes');
  752. }
  753. if (checkKeys) {
  754. if ('$' === key[0]) {
  755. throw Error('key ' + key + " must not start with '$'");
  756. } else if (~key.indexOf('.')) {
  757. throw Error('key ' + key + " must not contain '.'");
  758. }
  759. }
  760. }
  761. if (type === 'string') {
  762. index = serializeString(buffer, key, value, index);
  763. } else if (type === 'number') {
  764. index = serializeNumber(buffer, key, value, index);
  765. } else if(type === 'bigint') {
  766. throw new TypeError('Unsupported type BigInt, please use Decimal128');
  767. } else if (type === 'boolean') {
  768. index = serializeBoolean(buffer, key, value, index);
  769. } else if (value instanceof Date || isDate(value)) {
  770. index = serializeDate(buffer, key, value, index);
  771. // } else if (value === undefined && ignoreUndefined === true) {
  772. } else if (value === null || (value === undefined && ignoreUndefined === false)) {
  773. index = serializeNull(buffer, key, value, index);
  774. } else if (value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') {
  775. index = serializeObjectId(buffer, key, value, index);
  776. } else if (Buffer.isBuffer(value)) {
  777. index = serializeBuffer(buffer, key, value, index);
  778. } else if (value instanceof RegExp || isRegExp(value)) {
  779. index = serializeRegExp(buffer, key, value, index);
  780. } else if (type === 'object' && value['_bsontype'] == null) {
  781. index = serializeObject(
  782. buffer,
  783. key,
  784. value,
  785. index,
  786. checkKeys,
  787. depth,
  788. serializeFunctions,
  789. ignoreUndefined,
  790. false,
  791. path
  792. );
  793. } else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
  794. index = serializeDecimal128(buffer, key, value, index);
  795. } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
  796. index = serializeLong(buffer, key, value, index);
  797. } else if (value['_bsontype'] === 'Double') {
  798. index = serializeDouble(buffer, key, value, index);
  799. } else if (value['_bsontype'] === 'Code') {
  800. index = serializeCode(
  801. buffer,
  802. key,
  803. value,
  804. index,
  805. checkKeys,
  806. depth,
  807. serializeFunctions,
  808. ignoreUndefined
  809. );
  810. } else if (typeof value === 'function' && serializeFunctions) {
  811. index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
  812. } else if (value['_bsontype'] === 'Binary') {
  813. index = serializeBinary(buffer, key, value, index);
  814. } else if (value['_bsontype'] === 'Symbol') {
  815. index = serializeSymbol(buffer, key, value, index);
  816. } else if (value['_bsontype'] === 'DBRef') {
  817. index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
  818. } else if (value['_bsontype'] === 'BSONRegExp') {
  819. index = serializeBSONRegExp(buffer, key, value, index);
  820. } else if (value['_bsontype'] === 'Int32') {
  821. index = serializeInt32(buffer, key, value, index);
  822. } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
  823. index = serializeMinMax(buffer, key, value, index);
  824. } else if (typeof value['_bsontype'] !== 'undefined') {
  825. throw new TypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
  826. }
  827. }
  828. } else {
  829. // Did we provide a custom serialization method
  830. if (object.toBSON) {
  831. if (typeof object.toBSON !== 'function') throw new Error('toBSON is not a function');
  832. object = object.toBSON();
  833. if (object != null && typeof object !== 'object')
  834. throw new Error('toBSON function did not return an object');
  835. }
  836. // Iterate over all the keys
  837. for (key in object) {
  838. value = object[key];
  839. // Is there an override value
  840. if (value && value.toBSON) {
  841. if (typeof value.toBSON !== 'function') throw new Error('toBSON is not a function');
  842. value = value.toBSON();
  843. }
  844. // Check the type of the value
  845. type = typeof value;
  846. // Check the key and throw error if it's illegal
  847. if (typeof key === 'string' && ignoreKeys.indexOf(key) === -1) {
  848. if (key.match(regexp) != null) {
  849. // The BSON spec doesn't allow keys with null bytes because keys are
  850. // null-terminated.
  851. throw Error('key ' + key + ' must not contain null bytes');
  852. }
  853. if (checkKeys) {
  854. if ('$' === key[0]) {
  855. throw Error('key ' + key + " must not start with '$'");
  856. } else if (~key.indexOf('.')) {
  857. throw Error('key ' + key + " must not contain '.'");
  858. }
  859. }
  860. }
  861. if (type === 'string') {
  862. index = serializeString(buffer, key, value, index);
  863. } else if (type === 'number') {
  864. index = serializeNumber(buffer, key, value, index);
  865. } else if(type === 'bigint') {
  866. throw new TypeError('Unsupported type BigInt, please use Decimal128');
  867. } else if (type === 'boolean') {
  868. index = serializeBoolean(buffer, key, value, index);
  869. } else if (value instanceof Date || isDate(value)) {
  870. index = serializeDate(buffer, key, value, index);
  871. } else if (value === undefined) {
  872. if (ignoreUndefined === false) index = serializeNull(buffer, key, value, index);
  873. } else if (value === null) {
  874. index = serializeNull(buffer, key, value, index);
  875. } else if (value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') {
  876. index = serializeObjectId(buffer, key, value, index);
  877. } else if (Buffer.isBuffer(value)) {
  878. index = serializeBuffer(buffer, key, value, index);
  879. } else if (value instanceof RegExp || isRegExp(value)) {
  880. index = serializeRegExp(buffer, key, value, index);
  881. } else if (type === 'object' && value['_bsontype'] == null) {
  882. index = serializeObject(
  883. buffer,
  884. key,
  885. value,
  886. index,
  887. checkKeys,
  888. depth,
  889. serializeFunctions,
  890. ignoreUndefined,
  891. false,
  892. path
  893. );
  894. } else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
  895. index = serializeDecimal128(buffer, key, value, index);
  896. } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
  897. index = serializeLong(buffer, key, value, index);
  898. } else if (value['_bsontype'] === 'Double') {
  899. index = serializeDouble(buffer, key, value, index);
  900. } else if (value['_bsontype'] === 'Code') {
  901. index = serializeCode(
  902. buffer,
  903. key,
  904. value,
  905. index,
  906. checkKeys,
  907. depth,
  908. serializeFunctions,
  909. ignoreUndefined
  910. );
  911. } else if (typeof value === 'function' && serializeFunctions) {
  912. index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
  913. } else if (value['_bsontype'] === 'Binary') {
  914. index = serializeBinary(buffer, key, value, index);
  915. } else if (value['_bsontype'] === 'Symbol') {
  916. index = serializeSymbol(buffer, key, value, index);
  917. } else if (value['_bsontype'] === 'DBRef') {
  918. index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
  919. } else if (value['_bsontype'] === 'BSONRegExp') {
  920. index = serializeBSONRegExp(buffer, key, value, index);
  921. } else if (value['_bsontype'] === 'Int32') {
  922. index = serializeInt32(buffer, key, value, index);
  923. } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
  924. index = serializeMinMax(buffer, key, value, index);
  925. } else if (typeof value['_bsontype'] !== 'undefined') {
  926. throw new TypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
  927. }
  928. }
  929. }
  930. // Remove the path
  931. path.pop();
  932. // Final padding byte for object
  933. buffer[index++] = 0x00;
  934. // Final size
  935. var size = index - startingIndex;
  936. // Write the size of the object
  937. buffer[startingIndex++] = size & 0xff;
  938. buffer[startingIndex++] = (size >> 8) & 0xff;
  939. buffer[startingIndex++] = (size >> 16) & 0xff;
  940. buffer[startingIndex++] = (size >> 24) & 0xff;
  941. return index;
  942. };
  943. var BSON = {};
  944. /**
  945. * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5
  946. *
  947. * @ignore
  948. * @api private
  949. */
  950. // var functionCache = (BSON.functionCache = {});
  951. /**
  952. * Number BSON Type
  953. *
  954. * @classconstant BSON_DATA_NUMBER
  955. **/
  956. BSON.BSON_DATA_NUMBER = 1;
  957. /**
  958. * String BSON Type
  959. *
  960. * @classconstant BSON_DATA_STRING
  961. **/
  962. BSON.BSON_DATA_STRING = 2;
  963. /**
  964. * Object BSON Type
  965. *
  966. * @classconstant BSON_DATA_OBJECT
  967. **/
  968. BSON.BSON_DATA_OBJECT = 3;
  969. /**
  970. * Array BSON Type
  971. *
  972. * @classconstant BSON_DATA_ARRAY
  973. **/
  974. BSON.BSON_DATA_ARRAY = 4;
  975. /**
  976. * Binary BSON Type
  977. *
  978. * @classconstant BSON_DATA_BINARY
  979. **/
  980. BSON.BSON_DATA_BINARY = 5;
  981. /**
  982. * ObjectID BSON Type, deprecated
  983. *
  984. * @classconstant BSON_DATA_UNDEFINED
  985. **/
  986. BSON.BSON_DATA_UNDEFINED = 6;
  987. /**
  988. * ObjectID BSON Type
  989. *
  990. * @classconstant BSON_DATA_OID
  991. **/
  992. BSON.BSON_DATA_OID = 7;
  993. /**
  994. * Boolean BSON Type
  995. *
  996. * @classconstant BSON_DATA_BOOLEAN
  997. **/
  998. BSON.BSON_DATA_BOOLEAN = 8;
  999. /**
  1000. * Date BSON Type
  1001. *
  1002. * @classconstant BSON_DATA_DATE
  1003. **/
  1004. BSON.BSON_DATA_DATE = 9;
  1005. /**
  1006. * null BSON Type
  1007. *
  1008. * @classconstant BSON_DATA_NULL
  1009. **/
  1010. BSON.BSON_DATA_NULL = 10;
  1011. /**
  1012. * RegExp BSON Type
  1013. *
  1014. * @classconstant BSON_DATA_REGEXP
  1015. **/
  1016. BSON.BSON_DATA_REGEXP = 11;
  1017. /**
  1018. * Code BSON Type
  1019. *
  1020. * @classconstant BSON_DATA_CODE
  1021. **/
  1022. BSON.BSON_DATA_CODE = 13;
  1023. /**
  1024. * Symbol BSON Type
  1025. *
  1026. * @classconstant BSON_DATA_SYMBOL
  1027. **/
  1028. BSON.BSON_DATA_SYMBOL = 14;
  1029. /**
  1030. * Code with Scope BSON Type
  1031. *
  1032. * @classconstant BSON_DATA_CODE_W_SCOPE
  1033. **/
  1034. BSON.BSON_DATA_CODE_W_SCOPE = 15;
  1035. /**
  1036. * 32 bit Integer BSON Type
  1037. *
  1038. * @classconstant BSON_DATA_INT
  1039. **/
  1040. BSON.BSON_DATA_INT = 16;
  1041. /**
  1042. * Timestamp BSON Type
  1043. *
  1044. * @classconstant BSON_DATA_TIMESTAMP
  1045. **/
  1046. BSON.BSON_DATA_TIMESTAMP = 17;
  1047. /**
  1048. * Long BSON Type
  1049. *
  1050. * @classconstant BSON_DATA_LONG
  1051. **/
  1052. BSON.BSON_DATA_LONG = 18;
  1053. /**
  1054. * Long BSON Type
  1055. *
  1056. * @classconstant BSON_DATA_DECIMAL128
  1057. **/
  1058. BSON.BSON_DATA_DECIMAL128 = 19;
  1059. /**
  1060. * MinKey BSON Type
  1061. *
  1062. * @classconstant BSON_DATA_MIN_KEY
  1063. **/
  1064. BSON.BSON_DATA_MIN_KEY = 0xff;
  1065. /**
  1066. * MaxKey BSON Type
  1067. *
  1068. * @classconstant BSON_DATA_MAX_KEY
  1069. **/
  1070. BSON.BSON_DATA_MAX_KEY = 0x7f;
  1071. /**
  1072. * Binary Default Type
  1073. *
  1074. * @classconstant BSON_BINARY_SUBTYPE_DEFAULT
  1075. **/
  1076. BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0;
  1077. /**
  1078. * Binary Function Type
  1079. *
  1080. * @classconstant BSON_BINARY_SUBTYPE_FUNCTION
  1081. **/
  1082. BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1;
  1083. /**
  1084. * Binary Byte Array Type
  1085. *
  1086. * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY
  1087. **/
  1088. BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2;
  1089. /**
  1090. * Binary UUID Type
  1091. *
  1092. * @classconstant BSON_BINARY_SUBTYPE_UUID
  1093. **/
  1094. BSON.BSON_BINARY_SUBTYPE_UUID = 3;
  1095. /**
  1096. * Binary MD5 Type
  1097. *
  1098. * @classconstant BSON_BINARY_SUBTYPE_MD5
  1099. **/
  1100. BSON.BSON_BINARY_SUBTYPE_MD5 = 4;
  1101. /**
  1102. * Binary User Defined Type
  1103. *
  1104. * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED
  1105. **/
  1106. BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
  1107. // BSON MAX VALUES
  1108. BSON.BSON_INT32_MAX = 0x7fffffff;
  1109. BSON.BSON_INT32_MIN = -0x80000000;
  1110. BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1;
  1111. BSON.BSON_INT64_MIN = -Math.pow(2, 63);
  1112. // JS MAX PRECISE VALUES
  1113. BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double.
  1114. BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double.
  1115. // Internal long versions
  1116. // var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double.
  1117. // var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double.
  1118. module.exports = serializeInto;