@ragestudio/scylla-odm 0.22.2 → 0.22.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/batch/index.d.ts +3 -3
  2. package/batch/index.d.ts.map +1 -1
  3. package/client.d.ts +6 -5
  4. package/client.d.ts.map +1 -1
  5. package/client.js +7 -7
  6. package/client.js.map +1 -1
  7. package/cql_gen/create_table.d.ts +1 -1
  8. package/cql_gen/create_table.d.ts.map +1 -1
  9. package/document/index.d.ts +3 -3
  10. package/document/index.d.ts.map +1 -1
  11. package/driver/LICENSE.txt +177 -0
  12. package/driver/NOTICE.txt +67 -0
  13. package/driver/auth/index.d.ts +37 -0
  14. package/driver/auth/index.js +37 -0
  15. package/driver/auth/no-auth-provider.js +73 -0
  16. package/driver/auth/plain-text-auth-provider.js +81 -0
  17. package/driver/auth/provider.js +77 -0
  18. package/driver/client-options.js +442 -0
  19. package/driver/client.js +1267 -0
  20. package/driver/concurrent/index.d.ts +49 -0
  21. package/driver/concurrent/index.js +366 -0
  22. package/driver/connection.js +1034 -0
  23. package/driver/control-connection.js +1282 -0
  24. package/driver/encoder.js +2316 -0
  25. package/driver/errors.js +223 -0
  26. package/driver/execution-options.js +612 -0
  27. package/driver/execution-profile.js +274 -0
  28. package/driver/host-connection-pool.js +587 -0
  29. package/driver/host.js +699 -0
  30. package/driver/index.d.ts +387 -0
  31. package/driver/index.js +81 -0
  32. package/driver/mapping/cache.js +214 -0
  33. package/driver/mapping/doc-info-adapter.js +171 -0
  34. package/driver/mapping/index.d.ts +219 -0
  35. package/driver/mapping/index.js +57 -0
  36. package/driver/mapping/mapper.js +225 -0
  37. package/driver/mapping/mapping-handler.js +641 -0
  38. package/driver/mapping/model-batch-item.js +215 -0
  39. package/driver/mapping/model-batch-mapper.js +141 -0
  40. package/driver/mapping/model-mapper.js +315 -0
  41. package/driver/mapping/model-mapping-info.js +225 -0
  42. package/driver/mapping/object-selector.js +417 -0
  43. package/driver/mapping/q.js +156 -0
  44. package/driver/mapping/query-generator.js +556 -0
  45. package/driver/mapping/result-mapper.js +123 -0
  46. package/driver/mapping/result.js +139 -0
  47. package/driver/mapping/table-mappings.js +133 -0
  48. package/driver/mapping/tree.js +160 -0
  49. package/driver/metadata/aggregate.js +79 -0
  50. package/driver/metadata/client-state.js +119 -0
  51. package/driver/metadata/data-collection.js +182 -0
  52. package/driver/metadata/event-debouncer.js +174 -0
  53. package/driver/metadata/index.d.ts +276 -0
  54. package/driver/metadata/index.js +1156 -0
  55. package/driver/metadata/materialized-view.js +49 -0
  56. package/driver/metadata/schema-function.js +98 -0
  57. package/driver/metadata/schema-index.js +166 -0
  58. package/driver/metadata/schema-parser.js +1399 -0
  59. package/driver/metadata/table-metadata.js +77 -0
  60. package/driver/operation-state.js +206 -0
  61. package/driver/policies/address-resolution.js +145 -0
  62. package/driver/policies/index.d.ts +241 -0
  63. package/driver/policies/index.js +110 -0
  64. package/driver/policies/load-balancing.js +970 -0
  65. package/driver/policies/reconnection.js +166 -0
  66. package/driver/policies/retry.js +326 -0
  67. package/driver/policies/speculative-execution.js +150 -0
  68. package/driver/policies/timestamp-generation.js +176 -0
  69. package/driver/prepare-handler.js +347 -0
  70. package/driver/promise-utils.js +191 -0
  71. package/driver/readers.js +624 -0
  72. package/driver/request-execution.js +644 -0
  73. package/driver/request-handler.js +332 -0
  74. package/driver/requests.js +618 -0
  75. package/driver/stream-id-stack.js +209 -0
  76. package/driver/streams.js +745 -0
  77. package/driver/token.js +325 -0
  78. package/driver/tokenizer.js +631 -0
  79. package/driver/types/big-decimal.js +282 -0
  80. package/driver/types/duration.js +576 -0
  81. package/driver/types/index.d.ts +486 -0
  82. package/driver/types/index.js +733 -0
  83. package/driver/types/inet-address.js +262 -0
  84. package/driver/types/integer.js +818 -0
  85. package/driver/types/local-date.js +280 -0
  86. package/driver/types/local-time.js +299 -0
  87. package/driver/types/mutable-long.js +385 -0
  88. package/driver/types/protocol-version.js +391 -0
  89. package/driver/types/result-set.js +287 -0
  90. package/driver/types/result-stream.js +164 -0
  91. package/driver/types/row.js +85 -0
  92. package/driver/types/time-uuid.js +414 -0
  93. package/driver/types/tuple.js +103 -0
  94. package/driver/types/uuid.js +160 -0
  95. package/driver/types/vector.js +130 -0
  96. package/driver/types/version-number.js +153 -0
  97. package/driver/utils.js +1485 -0
  98. package/driver/writers.js +350 -0
  99. package/global.d.ts +1 -1
  100. package/global.d.ts.map +1 -1
  101. package/index.d.ts +6 -6
  102. package/index.d.ts.map +1 -1
  103. package/index.js +6 -6
  104. package/index.js.map +1 -1
  105. package/migrate/index.d.ts +1 -1
  106. package/migrate/index.d.ts.map +1 -1
  107. package/migrate/index.js +1 -1
  108. package/migrate/index.js.map +1 -1
  109. package/model/index.d.ts +6 -6
  110. package/model/index.d.ts.map +1 -1
  111. package/model/index.js +10 -10
  112. package/model/index.js.map +1 -1
  113. package/operations/countAll.d.ts +1 -1
  114. package/operations/countAll.d.ts.map +1 -1
  115. package/operations/delete.d.ts +3 -4
  116. package/operations/delete.d.ts.map +1 -1
  117. package/operations/delete.js +1 -1
  118. package/operations/delete.js.map +1 -1
  119. package/operations/find.d.ts +2 -2
  120. package/operations/find.d.ts.map +1 -1
  121. package/operations/find.js +1 -1
  122. package/operations/find.js.map +1 -1
  123. package/operations/findOne.d.ts +2 -2
  124. package/operations/findOne.d.ts.map +1 -1
  125. package/operations/findOne.js +1 -1
  126. package/operations/findOne.js.map +1 -1
  127. package/operations/insert.d.ts +3 -3
  128. package/operations/insert.d.ts.map +1 -1
  129. package/operations/insert.js +2 -2
  130. package/operations/insert.js.map +1 -1
  131. package/operations/sync.d.ts +1 -1
  132. package/operations/sync.d.ts.map +1 -1
  133. package/operations/sync.js +1 -1
  134. package/operations/sync.js.map +1 -1
  135. package/operations/tableExists.d.ts +1 -1
  136. package/operations/tableExists.d.ts.map +1 -1
  137. package/operations/update.d.ts +3 -3
  138. package/operations/update.d.ts.map +1 -1
  139. package/operations/update.js +2 -2
  140. package/operations/update.js.map +1 -1
  141. package/package.json +4 -12
  142. package/schema/index.d.ts +1 -1
  143. package/schema/index.d.ts.map +1 -1
  144. package/types.d.ts +4 -4
  145. package/types.d.ts.map +1 -1
  146. package/utils/queryParser.d.ts +1 -1
  147. package/utils/queryParser.d.ts.map +1 -1
  148. package/utils/queryParser.js +1 -1
  149. package/utils/queryParser.js.map +1 -1
  150. package/utils/typeChecker.d.ts +1 -1
  151. package/utils/typeChecker.d.ts.map +1 -1
  152. package/utils/typeChecker.js +1 -1
  153. package/utils/typeChecker.js.map +1 -1
@@ -0,0 +1,631 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ import types from "./types/index.js"
19
+ import token from "./token.js"
20
+ import utils from "./utils.js"
21
+ import MutableLong from "./types/mutable-long.js"
22
+ import crypto from "crypto"
23
+ const { Integer } = types
24
+
25
+ // Murmur3 constants
26
+ //-0x783C846EEEBDAC2B
27
+ const mconst1 = new MutableLong(0x53d5, 0x1142, 0x7b91, 0x87c3)
28
+ //0x4cf5ad432745937f
29
+ const mconst2 = new MutableLong(0x937f, 0x2745, 0xad43, 0x4cf5)
30
+ const mlongFive = MutableLong.fromNumber(5)
31
+ //0xff51afd7ed558ccd
32
+ const mconst3 = new MutableLong(0x8ccd, 0xed55, 0xafd7, 0xff51)
33
+ //0xc4ceb9fe1a85ec53
34
+ const mconst4 = new MutableLong(0xec53, 0x1a85, 0xb9fe, 0xc4ce)
35
+ const mconst5 = MutableLong.fromNumber(0x52dce729)
36
+ const mconst6 = MutableLong.fromNumber(0x38495ab5)
37
+
38
+ /**
39
+ * Represents a set of methods that are able to generate and parse tokens for the C* partitioner.
40
+ * @abstract
41
+ */
42
+ class Tokenizer {
43
+ constructor() {}
44
+
45
+ /**
46
+ * Creates a token based on the Buffer value provided
47
+ * @abstract
48
+ * @param {Buffer|Array} value
49
+ * @returns {Token} Computed token
50
+ */
51
+ hash(value) {
52
+ throw new Error("You must implement a hash function for the tokenizer")
53
+ }
54
+
55
+ /**
56
+ * Parses a token string and returns a representation of the token
57
+ * @abstract
58
+ * @param {String} value
59
+ */
60
+ parse(value) {
61
+ throw new Error("You must implement a parse function for the tokenizer")
62
+ }
63
+
64
+ minToken() {
65
+ throw new Error(
66
+ "You must implement a minToken function for the tokenizer",
67
+ )
68
+ }
69
+
70
+ /**
71
+ * Splits the range specified by start and end into numberOfSplits equal parts.
72
+ * @param {Token} start Starting token
73
+ * @param {Token} end End token
74
+ * @param {Number} numberOfSplits Number of splits to make.
75
+ */
76
+ split(start, end, numberOfSplits) {
77
+ throw new Error("You must implement a split function for the tokenizer")
78
+ }
79
+
80
+ /**
81
+ * Common implementation for splitting token ranges when start is in
82
+ * a shared Integer format.
83
+ *
84
+ * @param {Integer} start Starting token
85
+ * @param {Integer} range How large the range of the split is
86
+ * @param {Integer} ringEnd The end point of the ring so we know where to wrap
87
+ * @param {Integer} ringLength The total size of the ring
88
+ * @param {Number} numberOfSplits The number of splits to make
89
+ * @returns {Array<Integer>} The evenly-split points on the range
90
+ */
91
+ splitBase(start, range, ringEnd, ringLength, numberOfSplits) {
92
+ const numberOfSplitsInt = Integer.fromInt(numberOfSplits)
93
+ const divider = range.divide(numberOfSplitsInt)
94
+ let remainder = range.modulo(numberOfSplitsInt)
95
+
96
+ const results = []
97
+ let current = start
98
+ const dividerPlusOne = divider.add(Integer.ONE)
99
+
100
+ for (let i = 1; i < numberOfSplits; i++) {
101
+ if (remainder.greaterThan(Integer.ZERO)) {
102
+ current = current.add(dividerPlusOne)
103
+ } else {
104
+ current = current.add(divider)
105
+ }
106
+ if (ringLength && current.greaterThan(ringEnd)) {
107
+ current = current.subtract(ringLength)
108
+ }
109
+ results.push(current)
110
+ remainder = remainder.subtract(Integer.ONE)
111
+ }
112
+ return results
113
+ }
114
+
115
+ /**
116
+ * Return internal string based representation of a Token.
117
+ * @param {Token} token
118
+ */
119
+ stringify(token) {
120
+ return token.getValue().toString()
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Uniformly distributes data across the cluster based on Cassandra flavored Murmur3 hashed values.
126
+ */
127
+ class Murmur3Tokenizer extends Tokenizer {
128
+ constructor() {
129
+ super()
130
+ }
131
+
132
+ /**
133
+ * @param {Buffer} value
134
+ * @return {Murmur3Token}
135
+ */
136
+ hash(value) {
137
+ // This is an adapted version of the MurmurHash.hash3_x64_128 from Cassandra used
138
+ // for M3P. Compared to that methods, there's a few inlining of arguments and we
139
+ // only return the first 64-bits of the result since that's all M3 partitioner uses.
140
+
141
+ const data = value
142
+ let offset = 0
143
+ const length = data.length
144
+
145
+ const nblocks = length >> 4 // Process as 128-bit blocks.
146
+
147
+ const h1 = new MutableLong()
148
+ const h2 = new MutableLong()
149
+ let k1 = new MutableLong()
150
+ let k2 = new MutableLong()
151
+
152
+ for (let i = 0; i < nblocks; i++) {
153
+ k1 = this.getBlock(data, offset, i * 2)
154
+ k2 = this.getBlock(data, offset, i * 2 + 1)
155
+
156
+ k1.multiply(mconst1)
157
+ this.rotl64(k1, 31)
158
+ k1.multiply(mconst2)
159
+
160
+ h1.xor(k1)
161
+ this.rotl64(h1, 27)
162
+ h1.add(h2)
163
+ h1.multiply(mlongFive).add(mconst5)
164
+
165
+ k2.multiply(mconst2)
166
+ this.rotl64(k2, 33)
167
+ k2.multiply(mconst1)
168
+ h2.xor(k2)
169
+ this.rotl64(h2, 31)
170
+ h2.add(h1)
171
+ h2.multiply(mlongFive).add(mconst6)
172
+ }
173
+ //----------
174
+ // tail
175
+
176
+ // Advance offset to the unprocessed tail of the data.
177
+ offset += nblocks * 16
178
+
179
+ k1 = new MutableLong()
180
+ k2 = new MutableLong()
181
+
182
+ /* eslint-disable no-fallthrough */
183
+ switch (length & 15) {
184
+ case 15:
185
+ k2.xor(fromSignedByte(data[offset + 14]).shiftLeft(48))
186
+ case 14:
187
+ k2.xor(fromSignedByte(data[offset + 13]).shiftLeft(40))
188
+ case 13:
189
+ k2.xor(fromSignedByte(data[offset + 12]).shiftLeft(32))
190
+ case 12:
191
+ k2.xor(fromSignedByte(data[offset + 11]).shiftLeft(24))
192
+ case 11:
193
+ k2.xor(fromSignedByte(data[offset + 10]).shiftLeft(16))
194
+ case 10:
195
+ k2.xor(fromSignedByte(data[offset + 9]).shiftLeft(8))
196
+ case 9:
197
+ k2.xor(fromSignedByte(data[offset + 8]))
198
+ k2.multiply(mconst2)
199
+ this.rotl64(k2, 33)
200
+ k2.multiply(mconst1)
201
+ h2.xor(k2)
202
+ case 8:
203
+ k1.xor(fromSignedByte(data[offset + 7]).shiftLeft(56))
204
+ case 7:
205
+ k1.xor(fromSignedByte(data[offset + 6]).shiftLeft(48))
206
+ case 6:
207
+ k1.xor(fromSignedByte(data[offset + 5]).shiftLeft(40))
208
+ case 5:
209
+ k1.xor(fromSignedByte(data[offset + 4]).shiftLeft(32))
210
+ case 4:
211
+ k1.xor(fromSignedByte(data[offset + 3]).shiftLeft(24))
212
+ case 3:
213
+ k1.xor(fromSignedByte(data[offset + 2]).shiftLeft(16))
214
+ case 2:
215
+ k1.xor(fromSignedByte(data[offset + 1]).shiftLeft(8))
216
+ case 1:
217
+ k1.xor(fromSignedByte(data[offset]))
218
+ k1.multiply(mconst1)
219
+ this.rotl64(k1, 31)
220
+ k1.multiply(mconst2)
221
+ h1.xor(k1)
222
+ }
223
+ /* eslint-enable no-fallthrough */
224
+
225
+ h1.xor(MutableLong.fromNumber(length))
226
+ h2.xor(MutableLong.fromNumber(length))
227
+
228
+ h1.add(h2)
229
+ h2.add(h1)
230
+
231
+ this.fmix(h1)
232
+ this.fmix(h2)
233
+
234
+ h1.add(h2)
235
+
236
+ return new token.Murmur3Token(h1)
237
+ }
238
+
239
+ /**
240
+ *
241
+ * @param {Array<Number>} key
242
+ * @param {Number} offset
243
+ * @param {Number} index
244
+ * @return {MutableLong}
245
+ */
246
+ getBlock(key, offset, index) {
247
+ const i8 = index << 3
248
+ const blockOffset = offset + i8
249
+ return new MutableLong(
250
+ key[blockOffset] | (key[blockOffset + 1] << 8),
251
+ key[blockOffset + 2] | (key[blockOffset + 3] << 8),
252
+ key[blockOffset + 4] | (key[blockOffset + 5] << 8),
253
+ key[blockOffset + 6] | (key[blockOffset + 7] << 8),
254
+ )
255
+ }
256
+
257
+ /**
258
+ * @param {MutableLong} v
259
+ * @param {Number} n
260
+ */
261
+ rotl64(v, n) {
262
+ const left = v.clone().shiftLeft(n)
263
+ v.shiftRightUnsigned(64 - n).or(left)
264
+ }
265
+
266
+ /** @param {MutableLong} k */
267
+ fmix(k) {
268
+ k.xor(
269
+ new MutableLong(
270
+ (k.getUint16(2) >>> 1) | ((k.getUint16(3) << 15) & 0xffff),
271
+ k.getUint16(3) >>> 1,
272
+ 0,
273
+ 0,
274
+ ),
275
+ )
276
+ k.multiply(mconst3)
277
+ const other = new MutableLong(
278
+ (k.getUint16(2) >>> 1) | ((k.getUint16(3) << 15) & 0xffff),
279
+ k.getUint16(3) >>> 1,
280
+ 0,
281
+ 0,
282
+ )
283
+ k.xor(other)
284
+ k.multiply(mconst4)
285
+ k.xor(
286
+ new MutableLong(
287
+ (k.getUint16(2) >>> 1) | ((k.getUint16(3) << 15) & 0xffff),
288
+ k.getUint16(3) >>> 1,
289
+ 0,
290
+ 0,
291
+ ),
292
+ )
293
+ }
294
+
295
+ /**
296
+ * Parses a int64 decimal string representation into a MutableLong.
297
+ * @param {String} value
298
+ * @returns {Murmur3Token}
299
+ */
300
+ parse(value) {
301
+ return new token.Murmur3Token(MutableLong.fromString(value))
302
+ }
303
+
304
+ minToken() {
305
+ if (!this._minToken) {
306
+ // minimum long value.
307
+ this._minToken = this.parse("-9223372036854775808")
308
+ }
309
+ return this._minToken
310
+ }
311
+
312
+ maxToken() {
313
+ if (!this._maxToken) {
314
+ this._maxToken = this.parse("9223372036854775807")
315
+ }
316
+ return this._maxToken
317
+ }
318
+
319
+ maxValue() {
320
+ if (!this._maxValue) {
321
+ this._maxValue = Integer.fromString("9223372036854775807")
322
+ }
323
+ return this._maxValue
324
+ }
325
+
326
+ minValue() {
327
+ if (!this._minValue) {
328
+ this._minValue = Integer.fromString("-9223372036854775808")
329
+ }
330
+ return this._minValue
331
+ }
332
+
333
+ ringLength() {
334
+ if (!this._ringLength) {
335
+ this._ringLength = this.maxValue().subtract(this.minValue())
336
+ }
337
+ return this._ringLength
338
+ }
339
+
340
+ split(start, end, numberOfSplits) {
341
+ // ]min, min] means the whole ring.
342
+ if (start.equals(end) && start.equals(this.minToken())) {
343
+ end = this.maxToken()
344
+ }
345
+
346
+ const startVal = Integer.fromString(start.getValue().toString())
347
+ const endVal = Integer.fromString(end.getValue().toString())
348
+
349
+ let range = endVal.subtract(startVal)
350
+ if (range.isNegative()) {
351
+ range = range.add(this.ringLength())
352
+ }
353
+
354
+ const values = this.splitBase(
355
+ startVal,
356
+ range,
357
+ this.maxValue(),
358
+ this.ringLength(),
359
+ numberOfSplits,
360
+ )
361
+ return values.map((v) => this.parse(v.toString()))
362
+ }
363
+
364
+ stringify(token) {
365
+ // Get the underlying MutableLong
366
+ const value = token.getValue()
367
+ // We need a way to uniquely represent a token, it doesn't have to be the decimal string representation
368
+ // Using the uint16 avoids divisions and other expensive operations on the longs
369
+ return (
370
+ value.getUint16(0) +
371
+ "," +
372
+ value.getUint16(1) +
373
+ "," +
374
+ value.getUint16(2) +
375
+ "," +
376
+ value.getUint16(3)
377
+ )
378
+ }
379
+ }
380
+
381
+ /**
382
+ * Uniformly distributes data across the cluster based on MD5 hash values.
383
+ */
384
+ class RandomTokenizer extends Tokenizer {
385
+ constructor() {
386
+ super()
387
+ this._crypto = crypto
388
+ }
389
+
390
+ /**
391
+ * @param {Buffer|Array} value
392
+ * @returns {RandomToken}
393
+ */
394
+ hash(value) {
395
+ if (Array.isArray(value)) {
396
+ value = utils.allocBufferFromArray(value)
397
+ }
398
+ const hashedValue = this._crypto
399
+ .createHash("md5")
400
+ .update(value)
401
+ .digest()
402
+ return new token.RandomToken(Integer.fromBuffer(hashedValue).abs())
403
+ }
404
+
405
+ /**
406
+ * @returns {Token}
407
+ */
408
+ parse(value) {
409
+ return new token.RandomToken(Integer.fromString(value))
410
+ }
411
+
412
+ minToken() {
413
+ if (!this._minToken) {
414
+ this._minToken = this.parse("-1")
415
+ }
416
+ return this._minToken
417
+ }
418
+
419
+ maxValue() {
420
+ if (!this._maxValue) {
421
+ this._maxValue = Integer.fromNumber(Math.pow(2, 127))
422
+ }
423
+ return this._maxValue
424
+ }
425
+
426
+ maxToken() {
427
+ if (!this._maxToken) {
428
+ this._maxToken = new token.RandomToken(this.maxValue())
429
+ }
430
+ return this._maxToken
431
+ }
432
+
433
+ ringLength() {
434
+ if (!this._ringLength) {
435
+ this._ringLength = this.maxValue().add(Integer.ONE)
436
+ }
437
+ return this._ringLength
438
+ }
439
+
440
+ split(start, end, numberOfSplits) {
441
+ // ]min, min] means the whole ring.
442
+ if (start.equals(end) && start.equals(this.minToken())) {
443
+ end = this.maxToken()
444
+ }
445
+
446
+ const startVal = start.getValue()
447
+ const endVal = end.getValue()
448
+
449
+ let range = endVal.subtract(startVal)
450
+ if (range.lessThan(Integer.ZERO)) {
451
+ range = range.add(this.ringLength())
452
+ }
453
+
454
+ const values = this.splitBase(
455
+ startVal,
456
+ range,
457
+ this.maxValue(),
458
+ this.ringLength(),
459
+ numberOfSplits,
460
+ )
461
+ return values.map((v) => new token.RandomToken(v))
462
+ }
463
+ }
464
+
465
+ class ByteOrderedTokenizer extends Tokenizer {
466
+ constructor() {
467
+ super()
468
+ }
469
+
470
+ /**
471
+ * @param {Buffer} value
472
+ * @returns {ByteOrderedToken}
473
+ */
474
+ hash(value) {
475
+ // strip any trailing zeros as tokens with trailing zeros are equivalent
476
+ // to those who don't have them.
477
+ if (Array.isArray(value)) {
478
+ value = utils.allocBufferFromArray(value)
479
+ }
480
+ let zeroIndex = value.length
481
+ for (let i = value.length - 1; i > 0; i--) {
482
+ if (value[i] === 0) {
483
+ zeroIndex = i
484
+ } else {
485
+ break
486
+ }
487
+ }
488
+ return new token.ByteOrderedToken(value.slice(0, zeroIndex))
489
+ }
490
+
491
+ stringify(token) {
492
+ return token.getValue().toString("hex")
493
+ }
494
+
495
+ parse(value) {
496
+ return this.hash(utils.allocBufferFromString(value, "hex"))
497
+ }
498
+
499
+ minToken() {
500
+ if (!this._minToken) {
501
+ this._minToken = this.hash([])
502
+ }
503
+ return this._minToken
504
+ }
505
+
506
+ _toNumber(buffer, significantBytes) {
507
+ // Convert a token's byte array to a number in order to perform computations.
508
+ // This depends on the number of significant bytes that is used to normalize all tokens
509
+ // to the same size. For example if the token is 0x01 but significant bytes is 2, the
510
+ // result is 0x0100.
511
+ let target = buffer
512
+ if (buffer.length !== significantBytes) {
513
+ target = Buffer.alloc(significantBytes)
514
+ buffer.copy(target)
515
+ }
516
+
517
+ // similar to Integer.fromBuffer except we force the sign to 0.
518
+ const bits = new Array(Math.ceil(target.length / 4))
519
+ for (let i = 0; i < bits.length; i++) {
520
+ let offset = target.length - (i + 1) * 4
521
+ let value
522
+ if (offset < 0) {
523
+ //The buffer length is not multiple of 4
524
+ offset = offset + 4
525
+ value = 0
526
+ for (let j = 0; j < offset; j++) {
527
+ const byte = target[j]
528
+ value = value | (byte << ((offset - j - 1) * 8))
529
+ }
530
+ } else {
531
+ value = target.readInt32BE(offset)
532
+ }
533
+ bits[i] = value
534
+ }
535
+ return new Integer(bits, 0)
536
+ }
537
+
538
+ _toBuffer(number, significantBytes) {
539
+ // Convert numeric representation back to a buffer.
540
+ const buffer = Integer.toBuffer(number)
541
+ if (buffer.length === significantBytes) {
542
+ return buffer
543
+ }
544
+
545
+ // if first byte is a sign byte, skip it.
546
+ let start, length
547
+ if (buffer[0] === 0) {
548
+ start = 1
549
+ length = buffer.length - 1
550
+ } else {
551
+ start = 0
552
+ length = buffer.length
553
+ }
554
+
555
+ const target = Buffer.alloc(significantBytes)
556
+ buffer.copy(target, significantBytes - length, start, length + start)
557
+ return target
558
+ }
559
+
560
+ split(start, end, numberOfSplits) {
561
+ const tokenOrder = start.compare(end)
562
+
563
+ if (tokenOrder === 0 && start.equals(this.minToken())) {
564
+ throw new Error("Cannot split whole ring with ordered partitioner")
565
+ }
566
+
567
+ let startVal, endVal, range, ringLength, ringEnd
568
+ const intNumberOfSplits = Integer.fromNumber(numberOfSplits)
569
+ // Since tokens are compared lexicographically, convert to numbers using the
570
+ // largest length (i.e. given 0x0A and 0x0BCD, switch to 0x0A00 and 0x0BCD)
571
+ let significantBytes = Math.max(
572
+ start.getValue().length,
573
+ end.getValue().length,
574
+ )
575
+ if (tokenOrder < 0) {
576
+ let addedBytes = 0
577
+ while (true) {
578
+ startVal = this._toNumber(start.getValue(), significantBytes)
579
+ endVal = this._toNumber(end.getValue(), significantBytes)
580
+ range = endVal.subtract(startVal)
581
+ if (addedBytes === 4 || range.compare(intNumberOfSplits) >= 0) {
582
+ break
583
+ }
584
+ significantBytes += 1
585
+ addedBytes += 1
586
+ }
587
+ } else {
588
+ let addedBytes = 0
589
+ while (true) {
590
+ startVal = this._toNumber(start.getValue(), significantBytes)
591
+ endVal = this._toNumber(end.getValue(), significantBytes)
592
+ ringLength = Integer.fromNumber(
593
+ Math.pow(2, significantBytes * 8),
594
+ )
595
+ ringEnd = ringLength.subtract(Integer.ONE)
596
+ range = endVal.subtract(startVal).add(ringLength)
597
+ if (addedBytes === 4 || range.compare(intNumberOfSplits) >= 0) {
598
+ break
599
+ }
600
+ significantBytes += 1
601
+ addedBytes += 1
602
+ }
603
+ }
604
+
605
+ const values = this.splitBase(
606
+ startVal,
607
+ range,
608
+ ringEnd,
609
+ ringLength,
610
+ numberOfSplits,
611
+ )
612
+ return values.map(
613
+ (v) =>
614
+ new token.ByteOrderedToken(this._toBuffer(v, significantBytes)),
615
+ )
616
+ }
617
+ }
618
+
619
+ /**
620
+ * @param {Number} value
621
+ * @return {MutableLong}
622
+ */
623
+ function fromSignedByte(value) {
624
+ if (value < 128) {
625
+ return new MutableLong(value, 0, 0, 0)
626
+ }
627
+ return new MutableLong((value - 256) & 0xffff, 0xffff, 0xffff, 0xffff)
628
+ }
629
+
630
+ export { Murmur3Tokenizer, RandomTokenizer, ByteOrderedTokenizer }
631
+ export default { Murmur3Tokenizer, RandomTokenizer, ByteOrderedTokenizer }