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

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