objectSorter.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // / <reference types="node" />
  2. 'use strict';
  3. /**
  4. * Guesses object's type
  5. * @memberOf module:node-object-hash/objectSorter
  6. * @inner
  7. * @private
  8. * @param {Object} obj Object to guess type
  9. * @return {string} Object type
  10. * @example
  11. * var a = [];
  12. * _guessObjectType(a) === 'array'; // true
  13. */
  14. function _guessObjectType(obj) {
  15. if (obj === null) {
  16. return 'null';
  17. }
  18. switch (obj.constructor && obj.constructor.name) {
  19. case 'Array':
  20. case 'Int8Array':
  21. case 'Uint8Array':
  22. case 'Uint8ClampedArray':
  23. case 'Int16Array':
  24. case 'Uint16Array':
  25. case 'Int32Array':
  26. case 'Uint32Array':
  27. case 'Float32Array':
  28. case 'Float64Array':
  29. case 'Buffer':
  30. return 'array';
  31. case 'Map':
  32. return 'map';
  33. case 'Set':
  34. return 'set';
  35. case 'Date':
  36. return 'date';
  37. case 'String':
  38. return 'string';
  39. case 'Number':
  40. return 'number';
  41. case 'Boolean':
  42. return 'boolean';
  43. case 'Object':
  44. return 'object';
  45. default:
  46. return 'unknown';
  47. }
  48. }
  49. /**
  50. * Guesses variable type
  51. * @memberOf module:node-object-hash/objectSorter
  52. * @inner
  53. * @private
  54. * @param {*} obj Variable to guess type
  55. * @return {string} Variable type
  56. * @example
  57. * var a = '';
  58. * _guessType(a) === 'string'; // true
  59. */
  60. function _guessType(obj) {
  61. var type = typeof obj;
  62. return type !== 'object' ? type : _guessObjectType(obj);
  63. }
  64. /**
  65. * Creates object sorter function
  66. * @memberOf module:node-object-hash/objectSorter
  67. * @inner
  68. * @private
  69. * @param {Object} [options] Sorter options
  70. * @param {boolean} [options.coerce=true] Performs type coercion
  71. * @param {boolean} [options.sort=true] Performs array, object, etc. sorting
  72. * @return {module:node-object-hash/objectSorter~makeObjectSorter~objectToString}
  73. * Object sorting function
  74. * @example
  75. * // with coercion
  76. * var sorter = makeObjectSorter({coerce: true, sort: false});
  77. * sorter(1) === "1"; // true
  78. * // with sort
  79. * var sorter = makeObjectSorter({coerce: false, sort: true});
  80. * sorter([2, 3, 1]) === [1, 2, 3]; // true
  81. */
  82. function makeObjectSorter(options) {
  83. options = options || {};
  84. var coerce = typeof options.coerce === 'undefined' ? true : options.coerce;
  85. var sort = typeof options.sort === 'undefined' ? true : options.sort;
  86. var stringifier = {};
  87. stringifier.string = function sortString(obj) {
  88. if (coerce) {
  89. return obj;
  90. }
  91. return '<:s>:' + obj;
  92. };
  93. stringifier.number = function sortNumber(obj) {
  94. if (coerce) {
  95. return obj.toString();
  96. }
  97. return '<:n>:' + obj;
  98. };
  99. stringifier.boolean = function sortBoolean(obj) {
  100. if (coerce) {
  101. return obj.valueOf() ? '1' : '0';
  102. }
  103. return obj.valueOf() ? '<:b>:true' : '<:b>:false';
  104. };
  105. stringifier.symbol = function sortSymbol() {
  106. return '<:smbl>';
  107. };
  108. stringifier.undefined = function sortUndefined() {
  109. if (coerce) {
  110. return '';
  111. }
  112. return '<:undf>';
  113. };
  114. stringifier.null = function sortNull() {
  115. if (coerce) {
  116. return '';
  117. }
  118. return '<:null>';
  119. };
  120. stringifier.function = function sortFunction(obj) {
  121. if (coerce) {
  122. return obj.name + '=>' + obj.toString();
  123. }
  124. return '<:func>:' + obj.name + '=>' + obj.toString();
  125. };
  126. stringifier.array = function sortArray(obj) {
  127. var item;
  128. var itemType;
  129. var result = [];
  130. for (var i = 0; i < obj.length; i++) {
  131. item = obj[i];
  132. itemType = _guessType(item);
  133. result.push(stringifier[itemType](item));
  134. }
  135. return sort ? '[' + result.sort().toString() + ']' : '[' + result.toString() + ']';
  136. };
  137. stringifier.set = function sortSet(obj) {
  138. return stringifier.array(Array.from(obj));
  139. };
  140. stringifier.date = function sortDate(obj) {
  141. var dateStr = obj.toISOString();
  142. if (coerce) {
  143. return dateStr;
  144. }
  145. return '<:date>:' + dateStr;
  146. };
  147. stringifier.object = function sortObject(obj) {
  148. var keys = sort ? Object.keys(obj).sort() : Object.keys(obj);
  149. var objArray = [];
  150. var key;
  151. var value;
  152. var valueType;
  153. var i;
  154. for (i = 0; i < keys.length; i++) {
  155. key = keys[i];
  156. value = obj[key];
  157. valueType = _guessType(value);
  158. objArray.push(key + ':' + stringifier[valueType](value));
  159. }
  160. return '{' + objArray.toString() + '}';
  161. };
  162. stringifier.map = function sortMap(obj) {
  163. var arr = Array.from(obj);
  164. var key;
  165. var value;
  166. var item;
  167. var i;
  168. for (i = 0; i < arr.length; i++) {
  169. item = arr[i];
  170. key = item[0];
  171. value = item[1];
  172. item = [stringifier[_guessType(key)](key), stringifier[_guessType(value)](value)];
  173. arr[i] = item;
  174. }
  175. return sort ? '[' + arr.sort().join(';') + ']' : '[' + arr.join(';') + ']';
  176. };
  177. stringifier.unknown = function unknownToString(obj) {
  178. var constructorName = obj.constructor ? obj.constructor.name : 'unknonw';
  179. var objectName = typeof obj.toString === 'function' ? obj.toString() : 'unknown';
  180. return '<:' + constructorName + '>:' + objectName;
  181. };
  182. /**
  183. * Object sorting function
  184. * @private
  185. * @param {Object} obj Object to sort
  186. * @return {string} Sorted string
  187. */
  188. function objectToString(obj) {
  189. return stringifier[_guessType(obj)](obj);
  190. }
  191. return objectToString;
  192. }
  193. /**
  194. * Object sorter module.
  195. * It provides object sorter function constructor.
  196. * @module node-object-hash/objectSorter
  197. * @type {module:node-object-hash/objectSorter~makeObjectSorter~objectToString}
  198. */
  199. module.exports = makeObjectSorter;