/node_modules/mongoose/node_modules/mongodb/node_modules/mongodb-core/node_modules/bson/lib/bson/parser/calculate_size.js

https://gitlab.com/junxianlim/kokochat · JavaScript · 310 lines · 148 code · 20 blank · 142 comment · 110 complexity · b26e3e9d602b1bce86d11ed404726f12 MD5 · raw file

  1. "use strict"
  2. var writeIEEE754 = require('../float_parser').writeIEEE754
  3. , readIEEE754 = require('../float_parser').readIEEE754
  4. , Long = require('../long').Long
  5. , Double = require('../double').Double
  6. , Timestamp = require('../timestamp').Timestamp
  7. , ObjectID = require('../objectid').ObjectID
  8. , Symbol = require('../symbol').Symbol
  9. , BSONRegExp = require('../regexp').BSONRegExp
  10. , Code = require('../code').Code
  11. , MinKey = require('../min_key').MinKey
  12. , MaxKey = require('../max_key').MaxKey
  13. , DBRef = require('../db_ref').DBRef
  14. , Binary = require('../binary').Binary;
  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 calculateObjectSize = function calculateObjectSize(object, serializeFunctions) {
  20. var totalLength = (4 + 1);
  21. if(Array.isArray(object)) {
  22. for(var i = 0; i < object.length; i++) {
  23. totalLength += calculateElement(i.toString(), object[i], serializeFunctions, true)
  24. }
  25. } else {
  26. // If we have toBSON defined, override the current object
  27. if(object.toBSON) {
  28. object = object.toBSON();
  29. }
  30. // Calculate size
  31. for(var key in object) {
  32. totalLength += calculateElement(key, object[key], serializeFunctions)
  33. }
  34. }
  35. return totalLength;
  36. }
  37. /**
  38. * @ignore
  39. * @api private
  40. */
  41. function calculateElement(name, value, serializeFunctions, isArray) {
  42. // If we have toBSON defined, override the current object
  43. if(value && value.toBSON){
  44. value = value.toBSON();
  45. }
  46. switch(typeof value) {
  47. case 'string':
  48. return 1 + Buffer.byteLength(name, 'utf8') + 1 + 4 + Buffer.byteLength(value, 'utf8') + 1;
  49. case 'number':
  50. if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
  51. if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit
  52. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (4 + 1);
  53. } else {
  54. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (8 + 1);
  55. }
  56. } else { // 64 bit
  57. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (8 + 1);
  58. }
  59. case 'undefined':
  60. if(isArray) return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (1);
  61. return 0;
  62. case 'boolean':
  63. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (1 + 1);
  64. case 'object':
  65. if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') {
  66. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (1);
  67. } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') {
  68. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (12 + 1);
  69. } else if(value instanceof Date || isDate(value)) {
  70. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (8 + 1);
  71. } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
  72. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (1 + 4 + 1) + value.length;
  73. } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp
  74. || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') {
  75. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (8 + 1);
  76. } else if(value instanceof Code || value['_bsontype'] == 'Code') {
  77. // Calculate size depending on the availability of a scope
  78. if(value.scope != null && Object.keys(value.scope).length > 0) {
  79. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + 4 + 4 + Buffer.byteLength(value.code.toString(), 'utf8') + 1 + calculateObjectSize(value.scope, serializeFunctions);
  80. } else {
  81. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + 4 + Buffer.byteLength(value.code.toString(), 'utf8') + 1;
  82. }
  83. } else if(value instanceof Binary || value['_bsontype'] == 'Binary') {
  84. // Check what kind of subtype we have
  85. if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) {
  86. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (value.position + 1 + 4 + 1 + 4);
  87. } else {
  88. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (value.position + 1 + 4 + 1);
  89. }
  90. } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') {
  91. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + Buffer.byteLength(value.value, 'utf8') + 4 + 1 + 1;
  92. } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') {
  93. // Set up correct object for serialization
  94. var ordered_values = {
  95. '$ref': value.namespace
  96. , '$id' : value.oid
  97. };
  98. // Add db reference if it exists
  99. if(null != value.db) {
  100. ordered_values['$db'] = value.db;
  101. }
  102. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + calculateObjectSize(ordered_values, serializeFunctions);
  103. } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') {
  104. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + Buffer.byteLength(value.source, 'utf8') + 1
  105. + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1
  106. } else if(value instanceof BSONRegExp || value['_bsontype'] == 'BSONRegExp') {
  107. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + Buffer.byteLength(value.pattern, 'utf8') + 1
  108. + Buffer.byteLength(value.options, 'utf8') + 1
  109. } else {
  110. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + calculateObjectSize(value, serializeFunctions) + 1;
  111. }
  112. case 'function':
  113. // WTF for 0.4.X where typeof /someregexp/ === 'function'
  114. if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') {
  115. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + Buffer.byteLength(value.source, 'utf8') + 1
  116. + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1
  117. } else {
  118. if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) {
  119. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + 4 + 4 + Buffer.byteLength(value.toString(), 'utf8') + 1 + calculateObjectSize(value.scope, serializeFunctions);
  120. } else if(serializeFunctions) {
  121. return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + 4 + Buffer.byteLength(value.toString(), 'utf8') + 1;
  122. }
  123. }
  124. }
  125. return 0;
  126. }
  127. var BSON = {};
  128. /**
  129. * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5
  130. *
  131. * @ignore
  132. * @api private
  133. */
  134. var functionCache = BSON.functionCache = {};
  135. /**
  136. * Number BSON Type
  137. *
  138. * @classconstant BSON_DATA_NUMBER
  139. **/
  140. BSON.BSON_DATA_NUMBER = 1;
  141. /**
  142. * String BSON Type
  143. *
  144. * @classconstant BSON_DATA_STRING
  145. **/
  146. BSON.BSON_DATA_STRING = 2;
  147. /**
  148. * Object BSON Type
  149. *
  150. * @classconstant BSON_DATA_OBJECT
  151. **/
  152. BSON.BSON_DATA_OBJECT = 3;
  153. /**
  154. * Array BSON Type
  155. *
  156. * @classconstant BSON_DATA_ARRAY
  157. **/
  158. BSON.BSON_DATA_ARRAY = 4;
  159. /**
  160. * Binary BSON Type
  161. *
  162. * @classconstant BSON_DATA_BINARY
  163. **/
  164. BSON.BSON_DATA_BINARY = 5;
  165. /**
  166. * ObjectID BSON Type
  167. *
  168. * @classconstant BSON_DATA_OID
  169. **/
  170. BSON.BSON_DATA_OID = 7;
  171. /**
  172. * Boolean BSON Type
  173. *
  174. * @classconstant BSON_DATA_BOOLEAN
  175. **/
  176. BSON.BSON_DATA_BOOLEAN = 8;
  177. /**
  178. * Date BSON Type
  179. *
  180. * @classconstant BSON_DATA_DATE
  181. **/
  182. BSON.BSON_DATA_DATE = 9;
  183. /**
  184. * null BSON Type
  185. *
  186. * @classconstant BSON_DATA_NULL
  187. **/
  188. BSON.BSON_DATA_NULL = 10;
  189. /**
  190. * RegExp BSON Type
  191. *
  192. * @classconstant BSON_DATA_REGEXP
  193. **/
  194. BSON.BSON_DATA_REGEXP = 11;
  195. /**
  196. * Code BSON Type
  197. *
  198. * @classconstant BSON_DATA_CODE
  199. **/
  200. BSON.BSON_DATA_CODE = 13;
  201. /**
  202. * Symbol BSON Type
  203. *
  204. * @classconstant BSON_DATA_SYMBOL
  205. **/
  206. BSON.BSON_DATA_SYMBOL = 14;
  207. /**
  208. * Code with Scope BSON Type
  209. *
  210. * @classconstant BSON_DATA_CODE_W_SCOPE
  211. **/
  212. BSON.BSON_DATA_CODE_W_SCOPE = 15;
  213. /**
  214. * 32 bit Integer BSON Type
  215. *
  216. * @classconstant BSON_DATA_INT
  217. **/
  218. BSON.BSON_DATA_INT = 16;
  219. /**
  220. * Timestamp BSON Type
  221. *
  222. * @classconstant BSON_DATA_TIMESTAMP
  223. **/
  224. BSON.BSON_DATA_TIMESTAMP = 17;
  225. /**
  226. * Long BSON Type
  227. *
  228. * @classconstant BSON_DATA_LONG
  229. **/
  230. BSON.BSON_DATA_LONG = 18;
  231. /**
  232. * MinKey BSON Type
  233. *
  234. * @classconstant BSON_DATA_MIN_KEY
  235. **/
  236. BSON.BSON_DATA_MIN_KEY = 0xff;
  237. /**
  238. * MaxKey BSON Type
  239. *
  240. * @classconstant BSON_DATA_MAX_KEY
  241. **/
  242. BSON.BSON_DATA_MAX_KEY = 0x7f;
  243. /**
  244. * Binary Default Type
  245. *
  246. * @classconstant BSON_BINARY_SUBTYPE_DEFAULT
  247. **/
  248. BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0;
  249. /**
  250. * Binary Function Type
  251. *
  252. * @classconstant BSON_BINARY_SUBTYPE_FUNCTION
  253. **/
  254. BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1;
  255. /**
  256. * Binary Byte Array Type
  257. *
  258. * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY
  259. **/
  260. BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2;
  261. /**
  262. * Binary UUID Type
  263. *
  264. * @classconstant BSON_BINARY_SUBTYPE_UUID
  265. **/
  266. BSON.BSON_BINARY_SUBTYPE_UUID = 3;
  267. /**
  268. * Binary MD5 Type
  269. *
  270. * @classconstant BSON_BINARY_SUBTYPE_MD5
  271. **/
  272. BSON.BSON_BINARY_SUBTYPE_MD5 = 4;
  273. /**
  274. * Binary User Defined Type
  275. *
  276. * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED
  277. **/
  278. BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
  279. // BSON MAX VALUES
  280. BSON.BSON_INT32_MAX = 0x7FFFFFFF;
  281. BSON.BSON_INT32_MIN = -0x80000000;
  282. BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1;
  283. BSON.BSON_INT64_MIN = -Math.pow(2, 63);
  284. // JS MAX PRECISE VALUES
  285. BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double.
  286. BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double.
  287. // Internal long versions
  288. var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double.
  289. var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double.
  290. module.exports = calculateObjectSize;