File size: 4,908 Bytes
4888678
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import { BSONError } from './error';
import type { Int32 } from './int_32';
import { Long } from './long';

/** @public */
export type TimestampOverrides = '_bsontype' | 'toExtendedJSON' | 'fromExtendedJSON' | 'inspect';
/** @public */
export type LongWithoutOverrides = new (
  low: unknown,
  high?: number | boolean,
  unsigned?: boolean
) => {
  [P in Exclude<keyof Long, TimestampOverrides>]: Long[P];
};
/** @public */
export const LongWithoutOverridesClass: LongWithoutOverrides =
  Long as unknown as LongWithoutOverrides;

/** @public */
export interface TimestampExtended {
  $timestamp: {
    t: number;
    i: number;
  };
}

/**
 * @public
 * @category BSONType
 */
export class Timestamp extends LongWithoutOverridesClass {
  get _bsontype(): 'Timestamp' {
    return 'Timestamp';
  }

  static readonly MAX_VALUE = Long.MAX_UNSIGNED_VALUE;

  /**
   * @param int - A 64-bit bigint representing the Timestamp.
   */
  constructor(int: bigint);
  /**
   * @param long - A 64-bit Long representing the Timestamp.
   */
  constructor(long: Long);
  /**
   * @param value - A pair of two values indicating timestamp and increment.
   */
  constructor(value: { t: number; i: number });
  constructor(low?: bigint | Long | { t: number | Int32; i: number | Int32 }) {
    if (low == null) {
      super(0, 0, true);
    } else if (typeof low === 'bigint') {
      super(low, true);
    } else if (Long.isLong(low)) {
      super(low.low, low.high, true);
    } else if (typeof low === 'object' && 't' in low && 'i' in low) {
      if (typeof low.t !== 'number' && (typeof low.t !== 'object' || low.t._bsontype !== 'Int32')) {
        throw new BSONError('Timestamp constructed from { t, i } must provide t as a number');
      }
      if (typeof low.i !== 'number' && (typeof low.i !== 'object' || low.i._bsontype !== 'Int32')) {
        throw new BSONError('Timestamp constructed from { t, i } must provide i as a number');
      }
      const t = Number(low.t);
      const i = Number(low.i);
      if (t < 0 || Number.isNaN(t)) {
        throw new BSONError('Timestamp constructed from { t, i } must provide a positive t');
      }
      if (i < 0 || Number.isNaN(i)) {
        throw new BSONError('Timestamp constructed from { t, i } must provide a positive i');
      }
      if (t > 0xffff_ffff) {
        throw new BSONError(
          'Timestamp constructed from { t, i } must provide t equal or less than uint32 max'
        );
      }
      if (i > 0xffff_ffff) {
        throw new BSONError(
          'Timestamp constructed from { t, i } must provide i equal or less than uint32 max'
        );
      }

      super(i, t, true);
    } else {
      throw new BSONError(
        'A Timestamp can only be constructed with: bigint, Long, or { t: number; i: number }'
      );
    }
  }

  toJSON(): { $timestamp: string } {
    return {
      $timestamp: this.toString()
    };
  }

  /** Returns a Timestamp represented by the given (32-bit) integer value. */
  static fromInt(value: number): Timestamp {
    return new Timestamp(Long.fromInt(value, true));
  }

  /** Returns a Timestamp representing the given number value, provided that it is a finite number. Otherwise, zero is returned. */
  static fromNumber(value: number): Timestamp {
    return new Timestamp(Long.fromNumber(value, true));
  }

  /**
   * Returns a Timestamp for the given high and low bits. Each is assumed to use 32 bits.
   *
   * @param lowBits - the low 32-bits.
   * @param highBits - the high 32-bits.
   */
  static fromBits(lowBits: number, highBits: number): Timestamp {
    return new Timestamp({ i: lowBits, t: highBits });
  }

  /**
   * Returns a Timestamp from the given string, optionally using the given radix.
   *
   * @param str - the textual representation of the Timestamp.
   * @param optRadix - the radix in which the text is written.
   */
  static fromString(str: string, optRadix: number): Timestamp {
    return new Timestamp(Long.fromString(str, true, optRadix));
  }

  /** @internal */
  toExtendedJSON(): TimestampExtended {
    return { $timestamp: { t: this.high >>> 0, i: this.low >>> 0 } };
  }

  /** @internal */
  static fromExtendedJSON(doc: TimestampExtended): Timestamp {
    // The Long check is necessary because extended JSON has different behavior given the size of the input number
    const i = Long.isLong(doc.$timestamp.i)
      ? doc.$timestamp.i.getLowBitsUnsigned() // Need to fetch the least significant 32 bits
      : doc.$timestamp.i;
    const t = Long.isLong(doc.$timestamp.t)
      ? doc.$timestamp.t.getLowBitsUnsigned() // Need to fetch the least significant 32 bits
      : doc.$timestamp.t;
    return new Timestamp({ t, i });
  }

  /** @internal */
  [Symbol.for('nodejs.util.inspect.custom')](): string {
    return this.inspect();
  }

  inspect(): string {
    return `new Timestamp({ t: ${this.getHighBits()}, i: ${this.getLowBits()} })`;
  }
}