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

serializer.js 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  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 === 'boolean') {
  659. index = serializeBoolean(buffer, key, value, index, true);
  660. } else if (value instanceof Date || isDate(value)) {
  661. index = serializeDate(buffer, key, value, index, true);
  662. } else if (value === undefined) {
  663. index = serializeNull(buffer, key, value, index, true);
  664. } else if (value === null) {
  665. index = serializeNull(buffer, key, value, index, true);
  666. } else if (value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') {
  667. index = serializeObjectId(buffer, key, value, index, true);
  668. } else if (Buffer.isBuffer(value)) {
  669. index = serializeBuffer(buffer, key, value, index, true);
  670. } else if (value instanceof RegExp || isRegExp(value)) {
  671. index = serializeRegExp(buffer, key, value, index, true);
  672. } else if (type === 'object' && value['_bsontype'] == null) {
  673. index = serializeObject(
  674. buffer,
  675. key,
  676. value,
  677. index,
  678. checkKeys,
  679. depth,
  680. serializeFunctions,
  681. ignoreUndefined,
  682. true,
  683. path
  684. );
  685. } else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
  686. index = serializeDecimal128(buffer, key, value, index, true);
  687. } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
  688. index = serializeLong(buffer, key, value, index, true);
  689. } else if (value['_bsontype'] === 'Double') {
  690. index = serializeDouble(buffer, key, value, index, true);
  691. } else if (typeof value === 'function' && serializeFunctions) {
  692. index = serializeFunction(
  693. buffer,
  694. key,
  695. value,
  696. index,
  697. checkKeys,
  698. depth,
  699. serializeFunctions,
  700. true
  701. );
  702. } else if (value['_bsontype'] === 'Code') {
  703. index = serializeCode(
  704. buffer,
  705. key,
  706. value,
  707. index,
  708. checkKeys,
  709. depth,
  710. serializeFunctions,
  711. ignoreUndefined,
  712. true
  713. );
  714. } else if (value['_bsontype'] === 'Binary') {
  715. index = serializeBinary(buffer, key, value, index, true);
  716. } else if (value['_bsontype'] === 'Symbol') {
  717. index = serializeSymbol(buffer, key, value, index, true);
  718. } else if (value['_bsontype'] === 'DBRef') {
  719. index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, true);
  720. } else if (value['_bsontype'] === 'BSONRegExp') {
  721. index = serializeBSONRegExp(buffer, key, value, index, true);
  722. } else if (value['_bsontype'] === 'Int32') {
  723. index = serializeInt32(buffer, key, value, index, true);
  724. } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
  725. index = serializeMinMax(buffer, key, value, index, true);
  726. }
  727. }
  728. } else if (object instanceof Map) {
  729. var iterator = object.entries();
  730. var done = false;
  731. while (!done) {
  732. // Unpack the next entry
  733. var entry = iterator.next();
  734. done = entry.done;
  735. // Are we done, then skip and terminate
  736. if (done) continue;
  737. // Get the entry values
  738. key = entry.value[0];
  739. value = entry.value[1];
  740. // Check the type of the value
  741. type = typeof value;
  742. // Check the key and throw error if it's illegal
  743. if (typeof key === 'string' && ignoreKeys.indexOf(key) === -1) {
  744. if (key.match(regexp) != null) {
  745. // The BSON spec doesn't allow keys with null bytes because keys are
  746. // null-terminated.
  747. throw Error('key ' + key + ' must not contain null bytes');
  748. }
  749. if (checkKeys) {
  750. if ('$' === key[0]) {
  751. throw Error('key ' + key + " must not start with '$'");
  752. } else if (~key.indexOf('.')) {
  753. throw Error('key ' + key + " must not contain '.'");
  754. }
  755. }
  756. }
  757. if (type === 'string') {
  758. index = serializeString(buffer, key, value, index);
  759. } else if (type === 'number') {
  760. index = serializeNumber(buffer, key, value, index);
  761. } else if (type === 'boolean') {
  762. index = serializeBoolean(buffer, key, value, index);
  763. } else if (value instanceof Date || isDate(value)) {
  764. index = serializeDate(buffer, key, value, index);
  765. // } else if (value === undefined && ignoreUndefined === true) {
  766. } else if (value === null || (value === undefined && ignoreUndefined === false)) {
  767. index = serializeNull(buffer, key, value, index);
  768. } else if (value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') {
  769. index = serializeObjectId(buffer, key, value, index);
  770. } else if (Buffer.isBuffer(value)) {
  771. index = serializeBuffer(buffer, key, value, index);
  772. } else if (value instanceof RegExp || isRegExp(value)) {
  773. index = serializeRegExp(buffer, key, value, index);
  774. } else if (type === 'object' && value['_bsontype'] == null) {
  775. index = serializeObject(
  776. buffer,
  777. key,
  778. value,
  779. index,
  780. checkKeys,
  781. depth,
  782. serializeFunctions,
  783. ignoreUndefined,
  784. false,
  785. path
  786. );
  787. } else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
  788. index = serializeDecimal128(buffer, key, value, index);
  789. } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
  790. index = serializeLong(buffer, key, value, index);
  791. } else if (value['_bsontype'] === 'Double') {
  792. index = serializeDouble(buffer, key, value, index);
  793. } else if (value['_bsontype'] === 'Code') {
  794. index = serializeCode(
  795. buffer,
  796. key,
  797. value,
  798. index,
  799. checkKeys,
  800. depth,
  801. serializeFunctions,
  802. ignoreUndefined
  803. );
  804. } else if (typeof value === 'function' && serializeFunctions) {
  805. index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
  806. } else if (value['_bsontype'] === 'Binary') {
  807. index = serializeBinary(buffer, key, value, index);
  808. } else if (value['_bsontype'] === 'Symbol') {
  809. index = serializeSymbol(buffer, key, value, index);
  810. } else if (value['_bsontype'] === 'DBRef') {
  811. index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
  812. } else if (value['_bsontype'] === 'BSONRegExp') {
  813. index = serializeBSONRegExp(buffer, key, value, index);
  814. } else if (value['_bsontype'] === 'Int32') {
  815. index = serializeInt32(buffer, key, value, index);
  816. } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
  817. index = serializeMinMax(buffer, key, value, index);
  818. }
  819. }
  820. } else {
  821. // Did we provide a custom serialization method
  822. if (object.toBSON) {
  823. if (typeof object.toBSON !== 'function') throw new Error('toBSON is not a function');
  824. object = object.toBSON();
  825. if (object != null && typeof object !== 'object')
  826. throw new Error('toBSON function did not return an object');
  827. }
  828. // Iterate over all the keys
  829. for (key in object) {
  830. value = object[key];
  831. // Is there an override value
  832. if (value && value.toBSON) {
  833. if (typeof value.toBSON !== 'function') throw new Error('toBSON is not a function');
  834. value = value.toBSON();
  835. }
  836. // Check the type of the value
  837. type = typeof value;
  838. // Check the key and throw error if it's illegal
  839. if (typeof key === 'string' && ignoreKeys.indexOf(key) === -1) {
  840. if (key.match(regexp) != null) {
  841. // The BSON spec doesn't allow keys with null bytes because keys are
  842. // null-terminated.
  843. throw Error('key ' + key + ' must not contain null bytes');
  844. }
  845. if (checkKeys) {
  846. if ('$' === key[0]) {
  847. throw Error('key ' + key + " must not start with '$'");
  848. } else if (~key.indexOf('.')) {
  849. throw Error('key ' + key + " must not contain '.'");
  850. }
  851. }
  852. }
  853. if (type === 'string') {
  854. index = serializeString(buffer, key, value, index);
  855. } else if (type === 'number') {
  856. index = serializeNumber(buffer, key, value, index);
  857. } else if (type === 'boolean') {
  858. index = serializeBoolean(buffer, key, value, index);
  859. } else if (value instanceof Date || isDate(value)) {
  860. index = serializeDate(buffer, key, value, index);
  861. } else if (value === undefined) {
  862. if (ignoreUndefined === false) index = serializeNull(buffer, key, value, index);
  863. } else if (value === null) {
  864. index = serializeNull(buffer, key, value, index);
  865. } else if (value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') {
  866. index = serializeObjectId(buffer, key, value, index);
  867. } else if (Buffer.isBuffer(value)) {
  868. index = serializeBuffer(buffer, key, value, index);
  869. } else if (value instanceof RegExp || isRegExp(value)) {
  870. index = serializeRegExp(buffer, key, value, index);
  871. } else if (type === 'object' && value['_bsontype'] == null) {
  872. index = serializeObject(
  873. buffer,
  874. key,
  875. value,
  876. index,
  877. checkKeys,
  878. depth,
  879. serializeFunctions,
  880. ignoreUndefined,
  881. false,
  882. path
  883. );
  884. } else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
  885. index = serializeDecimal128(buffer, key, value, index);
  886. } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
  887. index = serializeLong(buffer, key, value, index);
  888. } else if (value['_bsontype'] === 'Double') {
  889. index = serializeDouble(buffer, key, value, index);
  890. } else if (value['_bsontype'] === 'Code') {
  891. index = serializeCode(
  892. buffer,
  893. key,
  894. value,
  895. index,
  896. checkKeys,
  897. depth,
  898. serializeFunctions,
  899. ignoreUndefined
  900. );
  901. } else if (typeof value === 'function' && serializeFunctions) {
  902. index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
  903. } else if (value['_bsontype'] === 'Binary') {
  904. index = serializeBinary(buffer, key, value, index);
  905. } else if (value['_bsontype'] === 'Symbol') {
  906. index = serializeSymbol(buffer, key, value, index);
  907. } else if (value['_bsontype'] === 'DBRef') {
  908. index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
  909. } else if (value['_bsontype'] === 'BSONRegExp') {
  910. index = serializeBSONRegExp(buffer, key, value, index);
  911. } else if (value['_bsontype'] === 'Int32') {
  912. index = serializeInt32(buffer, key, value, index);
  913. } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
  914. index = serializeMinMax(buffer, key, value, index);
  915. }
  916. }
  917. }
  918. // Remove the path
  919. path.pop();
  920. // Final padding byte for object
  921. buffer[index++] = 0x00;
  922. // Final size
  923. var size = index - startingIndex;
  924. // Write the size of the object
  925. buffer[startingIndex++] = size & 0xff;
  926. buffer[startingIndex++] = (size >> 8) & 0xff;
  927. buffer[startingIndex++] = (size >> 16) & 0xff;
  928. buffer[startingIndex++] = (size >> 24) & 0xff;
  929. return index;
  930. };
  931. var BSON = {};
  932. /**
  933. * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5
  934. *
  935. * @ignore
  936. * @api private
  937. */
  938. // var functionCache = (BSON.functionCache = {});
  939. /**
  940. * Number BSON Type
  941. *
  942. * @classconstant BSON_DATA_NUMBER
  943. **/
  944. BSON.BSON_DATA_NUMBER = 1;
  945. /**
  946. * String BSON Type
  947. *
  948. * @classconstant BSON_DATA_STRING
  949. **/
  950. BSON.BSON_DATA_STRING = 2;
  951. /**
  952. * Object BSON Type
  953. *
  954. * @classconstant BSON_DATA_OBJECT
  955. **/
  956. BSON.BSON_DATA_OBJECT = 3;
  957. /**
  958. * Array BSON Type
  959. *
  960. * @classconstant BSON_DATA_ARRAY
  961. **/
  962. BSON.BSON_DATA_ARRAY = 4;
  963. /**
  964. * Binary BSON Type
  965. *
  966. * @classconstant BSON_DATA_BINARY
  967. **/
  968. BSON.BSON_DATA_BINARY = 5;
  969. /**
  970. * ObjectID BSON Type, deprecated
  971. *
  972. * @classconstant BSON_DATA_UNDEFINED
  973. **/
  974. BSON.BSON_DATA_UNDEFINED = 6;
  975. /**
  976. * ObjectID BSON Type
  977. *
  978. * @classconstant BSON_DATA_OID
  979. **/
  980. BSON.BSON_DATA_OID = 7;
  981. /**
  982. * Boolean BSON Type
  983. *
  984. * @classconstant BSON_DATA_BOOLEAN
  985. **/
  986. BSON.BSON_DATA_BOOLEAN = 8;
  987. /**
  988. * Date BSON Type
  989. *
  990. * @classconstant BSON_DATA_DATE
  991. **/
  992. BSON.BSON_DATA_DATE = 9;
  993. /**
  994. * null BSON Type
  995. *
  996. * @classconstant BSON_DATA_NULL
  997. **/
  998. BSON.BSON_DATA_NULL = 10;
  999. /**
  1000. * RegExp BSON Type
  1001. *
  1002. * @classconstant BSON_DATA_REGEXP
  1003. **/
  1004. BSON.BSON_DATA_REGEXP = 11;
  1005. /**
  1006. * Code BSON Type
  1007. *
  1008. * @classconstant BSON_DATA_CODE
  1009. **/
  1010. BSON.BSON_DATA_CODE = 13;
  1011. /**
  1012. * Symbol BSON Type
  1013. *
  1014. * @classconstant BSON_DATA_SYMBOL
  1015. **/
  1016. BSON.BSON_DATA_SYMBOL = 14;
  1017. /**
  1018. * Code with Scope BSON Type
  1019. *
  1020. * @classconstant BSON_DATA_CODE_W_SCOPE
  1021. **/
  1022. BSON.BSON_DATA_CODE_W_SCOPE = 15;
  1023. /**
  1024. * 32 bit Integer BSON Type
  1025. *
  1026. * @classconstant BSON_DATA_INT
  1027. **/
  1028. BSON.BSON_DATA_INT = 16;
  1029. /**
  1030. * Timestamp BSON Type
  1031. *
  1032. * @classconstant BSON_DATA_TIMESTAMP
  1033. **/
  1034. BSON.BSON_DATA_TIMESTAMP = 17;
  1035. /**
  1036. * Long BSON Type
  1037. *
  1038. * @classconstant BSON_DATA_LONG
  1039. **/
  1040. BSON.BSON_DATA_LONG = 18;
  1041. /**
  1042. * Long BSON Type
  1043. *
  1044. * @classconstant BSON_DATA_DECIMAL128
  1045. **/
  1046. BSON.BSON_DATA_DECIMAL128 = 19;
  1047. /**
  1048. * MinKey BSON Type
  1049. *
  1050. * @classconstant BSON_DATA_MIN_KEY
  1051. **/
  1052. BSON.BSON_DATA_MIN_KEY = 0xff;
  1053. /**
  1054. * MaxKey BSON Type
  1055. *
  1056. * @classconstant BSON_DATA_MAX_KEY
  1057. **/
  1058. BSON.BSON_DATA_MAX_KEY = 0x7f;
  1059. /**
  1060. * Binary Default Type
  1061. *
  1062. * @classconstant BSON_BINARY_SUBTYPE_DEFAULT
  1063. **/
  1064. BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0;
  1065. /**
  1066. * Binary Function Type
  1067. *
  1068. * @classconstant BSON_BINARY_SUBTYPE_FUNCTION
  1069. **/
  1070. BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1;
  1071. /**
  1072. * Binary Byte Array Type
  1073. *
  1074. * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY
  1075. **/
  1076. BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2;
  1077. /**
  1078. * Binary UUID Type
  1079. *
  1080. * @classconstant BSON_BINARY_SUBTYPE_UUID
  1081. **/
  1082. BSON.BSON_BINARY_SUBTYPE_UUID = 3;
  1083. /**
  1084. * Binary MD5 Type
  1085. *
  1086. * @classconstant BSON_BINARY_SUBTYPE_MD5
  1087. **/
  1088. BSON.BSON_BINARY_SUBTYPE_MD5 = 4;
  1089. /**
  1090. * Binary User Defined Type
  1091. *
  1092. * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED
  1093. **/
  1094. BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
  1095. // BSON MAX VALUES
  1096. BSON.BSON_INT32_MAX = 0x7fffffff;
  1097. BSON.BSON_INT32_MIN = -0x80000000;
  1098. BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1;
  1099. BSON.BSON_INT64_MIN = -Math.pow(2, 63);
  1100. // JS MAX PRECISE VALUES
  1101. BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double.
  1102. BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double.
  1103. // Internal long versions
  1104. // var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double.
  1105. // var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double.
  1106. module.exports = serializeInto;