range.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. 'use strict';
  2. const _ = require('lodash');
  3. function stringifyRangeBound(bound) {
  4. if (bound === null) {
  5. return '' ;
  6. }
  7. if (bound === Infinity || bound === -Infinity) {
  8. return bound.toString().toLowerCase();
  9. }
  10. return JSON.stringify(bound);
  11. }
  12. function parseRangeBound(bound, parseType) {
  13. if (!bound) {
  14. return null;
  15. }
  16. if (bound === 'infinity') {
  17. return Infinity;
  18. }
  19. if (bound === '-infinity') {
  20. return -Infinity;
  21. }
  22. return parseType(bound);
  23. }
  24. function stringify(data) {
  25. if (data === null) return null;
  26. if (!Array.isArray(data)) throw new Error('range must be an array');
  27. if (!data.length) return 'empty';
  28. if (data.length !== 2) throw new Error('range array length must be 0 (empty) or 2 (lower and upper bounds)');
  29. if (Object.prototype.hasOwnProperty.call(data, 'inclusive')) {
  30. if (data.inclusive === false) data.inclusive = [false, false];
  31. else if (!data.inclusive) data.inclusive = [true, false];
  32. else if (data.inclusive === true) data.inclusive = [true, true];
  33. } else {
  34. data.inclusive = [true, false];
  35. }
  36. _.each(data, (value, index) => {
  37. if (_.isObject(value)) {
  38. if (Object.prototype.hasOwnProperty.call(value, 'inclusive')) data.inclusive[index] = !!value.inclusive;
  39. if (Object.prototype.hasOwnProperty.call(value, 'value')) data[index] = value.value;
  40. }
  41. });
  42. const lowerBound = stringifyRangeBound(data[0]);
  43. const upperBound = stringifyRangeBound(data[1]);
  44. return `${(data.inclusive[0] ? '[' : '(') + lowerBound},${upperBound}${data.inclusive[1] ? ']' : ')'}`;
  45. }
  46. exports.stringify = stringify;
  47. function parse(value, parser) {
  48. if (value === null) return null;
  49. if (value === 'empty') {
  50. return [];
  51. }
  52. let result = value
  53. .substring(1, value.length - 1)
  54. .split(',', 2);
  55. if (result.length !== 2) return value;
  56. result = result.map((item, index) => {
  57. return {
  58. value: parseRangeBound(item, parser),
  59. inclusive: index === 0 ? value[0] === '[' : value[value.length - 1] === ']'
  60. };
  61. });
  62. return result;
  63. }
  64. exports.parse = parse;