double.ts 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import type { EJSONOptions } from './extended_json';
  2. /** @public */
  3. export interface DoubleExtended {
  4. $numberDouble: string;
  5. }
  6. /**
  7. * A class representation of the BSON Double type.
  8. * @public
  9. * @category BSONType
  10. */
  11. export class Double {
  12. _bsontype!: 'Double';
  13. value!: number;
  14. /**
  15. * Create a Double type
  16. *
  17. * @param value - the number we want to represent as a double.
  18. */
  19. constructor(value: number) {
  20. if (!(this instanceof Double)) return new Double(value);
  21. if ((value as unknown) instanceof Number) {
  22. value = value.valueOf();
  23. }
  24. this.value = +value;
  25. }
  26. /**
  27. * Access the number value.
  28. *
  29. * @returns returns the wrapped double number.
  30. */
  31. valueOf(): number {
  32. return this.value;
  33. }
  34. toJSON(): number {
  35. return this.value;
  36. }
  37. toString(radix?: number): string {
  38. return this.value.toString(radix);
  39. }
  40. /** @internal */
  41. toExtendedJSON(options?: EJSONOptions): number | DoubleExtended {
  42. if (options && (options.legacy || (options.relaxed && isFinite(this.value)))) {
  43. return this.value;
  44. }
  45. if (Object.is(Math.sign(this.value), -0)) {
  46. // NOTE: JavaScript has +0 and -0, apparently to model limit calculations. If a user
  47. // explicitly provided `-0` then we need to ensure the sign makes it into the output
  48. return { $numberDouble: `-${this.value.toFixed(1)}` };
  49. }
  50. return {
  51. $numberDouble: Number.isInteger(this.value) ? this.value.toFixed(1) : this.value.toString()
  52. };
  53. }
  54. /** @internal */
  55. static fromExtendedJSON(doc: DoubleExtended, options?: EJSONOptions): number | Double {
  56. const doubleValue = parseFloat(doc.$numberDouble);
  57. return options && options.relaxed ? doubleValue : new Double(doubleValue);
  58. }
  59. /** @internal */
  60. [Symbol.for('nodejs.util.inspect.custom')](): string {
  61. return this.inspect();
  62. }
  63. inspect(): string {
  64. const eJSON = this.toExtendedJSON() as DoubleExtended;
  65. return `new Double(${eJSON.$numberDouble})`;
  66. }
  67. }
  68. Object.defineProperty(Double.prototype, '_bsontype', { value: 'Double' });