@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,2316 @@
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 util from "util"
19
+
20
+ import types from "./types/index.js"
21
+ const dataTypes = types.dataTypes
22
+ const Long = types.Long
23
+ const Integer = types.Integer
24
+ const BigDecimal = types.BigDecimal
25
+ import MutableLong from "./types/mutable-long.js"
26
+ import utils from "./utils.js"
27
+ import token from "./token.js"
28
+ import Vector from "./types/vector.js"
29
+
30
+ const uuidRegex =
31
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
32
+
33
+ const buffers = {
34
+ int16Zero: utils.allocBufferFromArray([0, 0]),
35
+ int32Zero: utils.allocBufferFromArray([0, 0, 0, 0]),
36
+ int8Zero: utils.allocBufferFromArray([0]),
37
+ int8One: utils.allocBufferFromArray([1]),
38
+ int8MaxValue: utils.allocBufferFromArray([0xff]),
39
+ }
40
+
41
+ // BigInt: Avoid using literals (e.g., 32n) as we must be able to compile with older engines
42
+ const isBigIntSupported = typeof BigInt !== "undefined"
43
+ const bigInt32 = isBigIntSupported ? BigInt(32) : null
44
+ const bigInt8 = isBigIntSupported ? BigInt(8) : null
45
+ const bigInt0 = isBigIntSupported ? BigInt(0) : null
46
+ const bigIntMinus1 = isBigIntSupported ? BigInt(-1) : null
47
+ const bigInt32BitsOn = isBigIntSupported ? BigInt(0xffffffff) : null
48
+ const bigInt8BitsOn = isBigIntSupported ? BigInt(0xff) : null
49
+
50
+ const complexTypeNames = Object.freeze({
51
+ list: "org.apache.cassandra.db.marshal.ListType",
52
+ set: "org.apache.cassandra.db.marshal.SetType",
53
+ map: "org.apache.cassandra.db.marshal.MapType",
54
+ udt: "org.apache.cassandra.db.marshal.UserType",
55
+ tuple: "org.apache.cassandra.db.marshal.TupleType",
56
+ frozen: "org.apache.cassandra.db.marshal.FrozenType",
57
+ reversed: "org.apache.cassandra.db.marshal.ReversedType",
58
+ composite: "org.apache.cassandra.db.marshal.CompositeType",
59
+ empty: "org.apache.cassandra.db.marshal.EmptyType",
60
+ collection: "org.apache.cassandra.db.marshal.ColumnToCollectionType",
61
+ })
62
+ const cqlNames = Object.freeze({
63
+ frozen: "frozen",
64
+ list: "list",
65
+ set: "set",
66
+ map: "map",
67
+ tuple: "tuple",
68
+ empty: "empty",
69
+ duration: "duration",
70
+ vector: "vector",
71
+ })
72
+ const singleTypeNames = Object.freeze({
73
+ "org.apache.cassandra.db.marshal.UTF8Type": dataTypes.varchar,
74
+ "org.apache.cassandra.db.marshal.AsciiType": dataTypes.ascii,
75
+ "org.apache.cassandra.db.marshal.UUIDType": dataTypes.uuid,
76
+ "org.apache.cassandra.db.marshal.TimeUUIDType": dataTypes.timeuuid,
77
+ "org.apache.cassandra.db.marshal.Int32Type": dataTypes.int,
78
+ "org.apache.cassandra.db.marshal.BytesType": dataTypes.blob,
79
+ "org.apache.cassandra.db.marshal.FloatType": dataTypes.float,
80
+ "org.apache.cassandra.db.marshal.DoubleType": dataTypes.double,
81
+ "org.apache.cassandra.db.marshal.BooleanType": dataTypes.boolean,
82
+ "org.apache.cassandra.db.marshal.InetAddressType": dataTypes.inet,
83
+ "org.apache.cassandra.db.marshal.SimpleDateType": dataTypes.date,
84
+ "org.apache.cassandra.db.marshal.TimeType": dataTypes.time,
85
+ "org.apache.cassandra.db.marshal.ShortType": dataTypes.smallint,
86
+ "org.apache.cassandra.db.marshal.ByteType": dataTypes.tinyint,
87
+ "org.apache.cassandra.db.marshal.DateType": dataTypes.timestamp,
88
+ "org.apache.cassandra.db.marshal.TimestampType": dataTypes.timestamp,
89
+ "org.apache.cassandra.db.marshal.LongType": dataTypes.bigint,
90
+ "org.apache.cassandra.db.marshal.DecimalType": dataTypes.decimal,
91
+ "org.apache.cassandra.db.marshal.IntegerType": dataTypes.varint,
92
+ "org.apache.cassandra.db.marshal.CounterColumnType": dataTypes.counter,
93
+ })
94
+
95
+ // eslint-disable-next-line no-unused-vars
96
+ const singleTypeNamesByDataType = invertObject(singleTypeNames)
97
+ const singleFqTypeNamesLength = Object.keys(singleTypeNames).reduce(function (
98
+ previous,
99
+ current,
100
+ ) {
101
+ return current.length > previous ? current.length : previous
102
+ }, 0)
103
+
104
+ const customTypeNames = Object.freeze({
105
+ duration: "org.apache.cassandra.db.marshal.DurationType",
106
+ vector: "org.apache.cassandra.db.marshal.VectorType",
107
+ })
108
+
109
+ const nullValueBuffer = utils.allocBufferFromArray([255, 255, 255, 255])
110
+ const unsetValueBuffer = utils.allocBufferFromArray([255, 255, 255, 254])
111
+
112
+ /**
113
+ * For backwards compatibility, empty buffers as text/blob/custom values are supported.
114
+ * In the case of other types, they are going to be decoded as a <code>null</code> value.
115
+ * @private
116
+ * @type {Set}
117
+ */
118
+ const zeroLengthTypesSupported = new Set([
119
+ dataTypes.text,
120
+ dataTypes.ascii,
121
+ dataTypes.varchar,
122
+ dataTypes.custom,
123
+ dataTypes.blob,
124
+ ])
125
+
126
+ /**
127
+ * Serializes and deserializes to and from a CQL type and a Javascript Type.
128
+ * @param {Number} protocolVersion
129
+ * @constructor
130
+ */
131
+ function Encoder(protocolVersion, options) {
132
+ this.encodingOptions = options.encoding || utils.emptyObject
133
+ defineInstanceMembers.call(this)
134
+ this.setProtocolVersion(protocolVersion)
135
+ setEncoders.call(this)
136
+ if (this.encodingOptions.copyBuffer) {
137
+ this.handleBuffer = handleBufferCopy
138
+ } else {
139
+ this.handleBuffer = handleBufferRef
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Declares the privileged instance members.
145
+ * @private
146
+ */
147
+ function defineInstanceMembers() {
148
+ /**
149
+ * Sets the protocol version and the encoding/decoding methods depending on the protocol version
150
+ * @param {Number} value
151
+ * @ignore
152
+ * @internal
153
+ */
154
+ this.setProtocolVersion = function (value) {
155
+ this.protocolVersion = value
156
+ //Set the collection serialization based on the protocol version
157
+ this.decodeCollectionLength = decodeCollectionLengthV3
158
+ this.getLengthBuffer = getLengthBufferV3
159
+ this.collectionLengthSize = 4
160
+ if (
161
+ !types.protocolVersion.uses4BytesCollectionLength(
162
+ this.protocolVersion,
163
+ )
164
+ ) {
165
+ this.decodeCollectionLength = decodeCollectionLengthV2
166
+ this.getLengthBuffer = getLengthBufferV2
167
+ this.collectionLengthSize = 2
168
+ }
169
+ }
170
+
171
+ const customDecoders = {
172
+ [customTypeNames.duration]: decodeDuration,
173
+ }
174
+
175
+ const customEncoders = {
176
+ [customTypeNames.duration]: encodeDuration,
177
+ }
178
+
179
+ // Decoding methods
180
+ this.decodeBlob = function (bytes) {
181
+ return this.handleBuffer(bytes)
182
+ }
183
+
184
+ /**
185
+ *
186
+ * @param {Buffer} bytes
187
+ * @param {OtherCustomColumnInfo | VectorColumnInfo} columnInfo
188
+ */
189
+ this.decodeCustom = function (bytes, columnInfo) {
190
+ // Make sure we actually have something to process in typeName before we go any further
191
+ if (!columnInfo) {
192
+ return this.handleBuffer(bytes)
193
+ }
194
+
195
+ // Special handling for vector custom types (since they have args)
196
+ if (
197
+ "customTypeName" in columnInfo &&
198
+ columnInfo.customTypeName === "vector"
199
+ ) {
200
+ return this.decodeVector(bytes, columnInfo)
201
+ }
202
+
203
+ if (
204
+ typeof columnInfo.info === "string" &&
205
+ columnInfo.info.startsWith(customTypeNames.vector)
206
+ ) {
207
+ const vectorColumnInfo = /** @type {VectorColumnInfo} */ (
208
+ this.parseFqTypeName(columnInfo.info)
209
+ )
210
+ return this.decodeVector(bytes, vectorColumnInfo)
211
+ }
212
+
213
+ const handler = customDecoders[columnInfo.info]
214
+ if (handler) {
215
+ return handler.call(this, bytes)
216
+ }
217
+ return this.handleBuffer(bytes)
218
+ }
219
+
220
+ this.decodeUtf8String = function (bytes) {
221
+ return bytes.toString("utf8")
222
+ }
223
+ this.decodeAsciiString = function (bytes) {
224
+ return bytes.toString("ascii")
225
+ }
226
+ this.decodeBoolean = function (bytes) {
227
+ return !!bytes.readUInt8(0)
228
+ }
229
+ this.decodeDouble = function (bytes) {
230
+ return bytes.readDoubleBE(0)
231
+ }
232
+ this.decodeFloat = function (bytes) {
233
+ return bytes.readFloatBE(0)
234
+ }
235
+ this.decodeInt = function (bytes) {
236
+ return bytes.readInt32BE(0)
237
+ }
238
+ this.decodeSmallint = function (bytes) {
239
+ return bytes.readInt16BE(0)
240
+ }
241
+ this.decodeTinyint = function (bytes) {
242
+ return bytes.readInt8(0)
243
+ }
244
+
245
+ this._decodeCqlLongAsLong = function (bytes) {
246
+ return Long.fromBuffer(bytes)
247
+ }
248
+
249
+ this._decodeCqlLongAsBigInt = function (bytes) {
250
+ return BigInt.asIntN(
251
+ 64,
252
+ (BigInt(bytes.readUInt32BE(0)) << bigInt32) |
253
+ BigInt(bytes.readUInt32BE(4)),
254
+ )
255
+ }
256
+
257
+ this.decodeLong = this.encodingOptions.useBigIntAsLong
258
+ ? this._decodeCqlLongAsBigInt
259
+ : this._decodeCqlLongAsLong
260
+
261
+ this._decodeVarintAsInteger = function (bytes) {
262
+ return Integer.fromBuffer(bytes)
263
+ }
264
+
265
+ this._decodeVarintAsBigInt = function decodeVarintAsBigInt(bytes) {
266
+ let result = bigInt0
267
+ if (bytes[0] <= 0x7f) {
268
+ for (let i = 0; i < bytes.length; i++) {
269
+ const b = BigInt(bytes[bytes.length - 1 - i])
270
+ result = result | (b << BigInt(i * 8))
271
+ }
272
+ } else {
273
+ for (let i = 0; i < bytes.length; i++) {
274
+ const b = BigInt(bytes[bytes.length - 1 - i])
275
+ result = result | ((~b & bigInt8BitsOn) << BigInt(i * 8))
276
+ }
277
+ result = ~result
278
+ }
279
+
280
+ return result
281
+ }
282
+
283
+ this.decodeVarint = this.encodingOptions.useBigIntAsVarint
284
+ ? this._decodeVarintAsBigInt
285
+ : this._decodeVarintAsInteger
286
+
287
+ this.decodeDecimal = function (bytes) {
288
+ return BigDecimal.fromBuffer(bytes)
289
+ }
290
+ this.decodeTimestamp = function (bytes) {
291
+ return new Date(this._decodeCqlLongAsLong(bytes).toNumber())
292
+ }
293
+ this.decodeDate = function (bytes) {
294
+ return types.LocalDate.fromBuffer(bytes)
295
+ }
296
+ this.decodeTime = function (bytes) {
297
+ return types.LocalTime.fromBuffer(bytes)
298
+ }
299
+ /*
300
+ * Reads a list from bytes
301
+ */
302
+ this.decodeList = function (bytes, columnInfo) {
303
+ const subtype = columnInfo.info
304
+ const totalItems = this.decodeCollectionLength(bytes, 0)
305
+ let offset = this.collectionLengthSize
306
+ const list = new Array(totalItems)
307
+ for (let i = 0; i < totalItems; i++) {
308
+ //bytes length of the item
309
+ const length = this.decodeCollectionLength(bytes, offset)
310
+ offset += this.collectionLengthSize
311
+ //slice it
312
+ list[i] = this.decode(bytes.slice(offset, offset + length), subtype)
313
+ offset += length
314
+ }
315
+ return list
316
+ }
317
+ /*
318
+ * Reads a Set from bytes
319
+ */
320
+ this.decodeSet = function (bytes, columnInfo) {
321
+ const arr = this.decodeList(bytes, columnInfo)
322
+ if (this.encodingOptions.set) {
323
+ const setConstructor = this.encodingOptions.set
324
+ return new setConstructor(arr)
325
+ }
326
+ return arr
327
+ }
328
+ /*
329
+ * Reads a map (key / value) from bytes
330
+ */
331
+ this.decodeMap = function (bytes, columnInfo) {
332
+ const subtypes = columnInfo.info
333
+ let map
334
+ const totalItems = this.decodeCollectionLength(bytes, 0)
335
+ let offset = this.collectionLengthSize
336
+ const self = this
337
+ function readValues(callback, thisArg) {
338
+ for (let i = 0; i < totalItems; i++) {
339
+ const keyLength = self.decodeCollectionLength(bytes, offset)
340
+ offset += self.collectionLengthSize
341
+ const key = self.decode(
342
+ bytes.slice(offset, offset + keyLength),
343
+ subtypes[0],
344
+ )
345
+ offset += keyLength
346
+ const valueLength = self.decodeCollectionLength(bytes, offset)
347
+ offset += self.collectionLengthSize
348
+ if (valueLength < 0) {
349
+ callback.call(thisArg, key, null)
350
+ continue
351
+ }
352
+ const value = self.decode(
353
+ bytes.slice(offset, offset + valueLength),
354
+ subtypes[1],
355
+ )
356
+ offset += valueLength
357
+ callback.call(thisArg, key, value)
358
+ }
359
+ }
360
+ if (this.encodingOptions.map) {
361
+ const mapConstructor = this.encodingOptions.map
362
+ map = new mapConstructor()
363
+ readValues(map.set, map)
364
+ } else {
365
+ map = {}
366
+ readValues(function (key, value) {
367
+ map[key] = value
368
+ })
369
+ }
370
+ return map
371
+ }
372
+ this.decodeUuid = function (bytes) {
373
+ return new types.Uuid(this.handleBuffer(bytes))
374
+ }
375
+ this.decodeTimeUuid = function (bytes) {
376
+ return new types.TimeUuid(this.handleBuffer(bytes))
377
+ }
378
+ this.decodeInet = function (bytes) {
379
+ return new types.InetAddress(this.handleBuffer(bytes))
380
+ }
381
+ /**
382
+ * Decodes a user defined type into an object
383
+ * @param {Buffer} bytes
384
+ * @param {UdtColumnInfo} columnInfo
385
+ * @private
386
+ */
387
+ this.decodeUdt = function (bytes, columnInfo) {
388
+ const udtInfo = columnInfo.info
389
+ const result = {}
390
+ let offset = 0
391
+ for (
392
+ let i = 0;
393
+ i < udtInfo.fields.length && offset < bytes.length;
394
+ i++
395
+ ) {
396
+ //bytes length of the field value
397
+ const length = bytes.readInt32BE(offset)
398
+ offset += 4
399
+ //slice it
400
+ const field = udtInfo.fields[i]
401
+ if (length < 0) {
402
+ result[field.name] = null
403
+ continue
404
+ }
405
+ result[field.name] = this.decode(
406
+ bytes.slice(offset, offset + length),
407
+ field.type,
408
+ )
409
+ offset += length
410
+ }
411
+ return result
412
+ }
413
+
414
+ this.decodeTuple = function (bytes, columnInfo) {
415
+ const tupleInfo = columnInfo.info
416
+ const elements = new Array(tupleInfo.length)
417
+ let offset = 0
418
+
419
+ for (let i = 0; i < tupleInfo.length && offset < bytes.length; i++) {
420
+ const length = bytes.readInt32BE(offset)
421
+ offset += 4
422
+
423
+ if (length < 0) {
424
+ elements[i] = null
425
+ continue
426
+ }
427
+
428
+ elements[i] = this.decode(
429
+ bytes.slice(offset, offset + length),
430
+ tupleInfo[i],
431
+ )
432
+ offset += length
433
+ }
434
+
435
+ return types.Tuple.fromArray(elements)
436
+ }
437
+
438
+ //Encoding methods
439
+ this.encodeFloat = function (value) {
440
+ if (typeof value === "string") {
441
+ // All numeric types are supported as strings for historical reasons
442
+ value = parseFloat(value)
443
+
444
+ if (Number.isNaN(value)) {
445
+ throw new TypeError(
446
+ `Expected string representation of a number, obtained ${util.inspect(value)}`,
447
+ )
448
+ }
449
+ }
450
+
451
+ if (typeof value !== "number") {
452
+ throw new TypeError(
453
+ "Expected Number, obtained " + util.inspect(value),
454
+ )
455
+ }
456
+
457
+ const buf = utils.allocBufferUnsafe(4)
458
+ buf.writeFloatBE(value, 0)
459
+ return buf
460
+ }
461
+
462
+ this.encodeDouble = function (value) {
463
+ if (typeof value === "string") {
464
+ // All numeric types are supported as strings for historical reasons
465
+ value = parseFloat(value)
466
+
467
+ if (Number.isNaN(value)) {
468
+ throw new TypeError(
469
+ `Expected string representation of a number, obtained ${util.inspect(value)}`,
470
+ )
471
+ }
472
+ }
473
+
474
+ if (typeof value !== "number") {
475
+ throw new TypeError(
476
+ "Expected Number, obtained " + util.inspect(value),
477
+ )
478
+ }
479
+
480
+ const buf = utils.allocBufferUnsafe(8)
481
+ buf.writeDoubleBE(value, 0)
482
+ return buf
483
+ }
484
+
485
+ /**
486
+ * @param {Date|String|Long|Number} value
487
+ * @private
488
+ */
489
+ this.encodeTimestamp = function (value) {
490
+ const originalValue = value
491
+ if (typeof value === "string") {
492
+ value = new Date(value)
493
+ }
494
+ if (value instanceof Date) {
495
+ //milliseconds since epoch
496
+ value = value.getTime()
497
+ if (isNaN(value)) {
498
+ throw new TypeError("Invalid date: " + originalValue)
499
+ }
500
+ }
501
+ if (this.encodingOptions.useBigIntAsLong) {
502
+ value = BigInt(value)
503
+ }
504
+ return this.encodeLong(value)
505
+ }
506
+ /**
507
+ * @param {Date|String|LocalDate} value
508
+ * @returns {Buffer}
509
+ * @throws {TypeError}
510
+ * @private
511
+ */
512
+ this.encodeDate = function (value) {
513
+ const originalValue = value
514
+ try {
515
+ if (typeof value === "string") {
516
+ value = types.LocalDate.fromString(value)
517
+ }
518
+ if (value instanceof Date) {
519
+ value = types.LocalDate.fromDate(value)
520
+ }
521
+ } catch (err) {
522
+ //Wrap into a TypeError
523
+ throw new TypeError("LocalDate could not be parsed " + err)
524
+ }
525
+ if (!(value instanceof types.LocalDate)) {
526
+ throw new TypeError(
527
+ "Expected Date/String/LocalDate, obtained " +
528
+ util.inspect(originalValue),
529
+ )
530
+ }
531
+ return value.toBuffer()
532
+ }
533
+ /**
534
+ * @param {String|LocalDate} value
535
+ * @returns {Buffer}
536
+ * @throws {TypeError}
537
+ * @private
538
+ */
539
+ this.encodeTime = function (value) {
540
+ const originalValue = value
541
+ try {
542
+ if (typeof value === "string") {
543
+ value = types.LocalTime.fromString(value)
544
+ }
545
+ } catch (err) {
546
+ //Wrap into a TypeError
547
+ throw new TypeError("LocalTime could not be parsed " + err)
548
+ }
549
+ if (!(value instanceof types.LocalTime)) {
550
+ throw new TypeError(
551
+ "Expected String/LocalTime, obtained " +
552
+ util.inspect(originalValue),
553
+ )
554
+ }
555
+ return value.toBuffer()
556
+ }
557
+ /**
558
+ * @param {Uuid|String|Buffer} value
559
+ * @private
560
+ */
561
+ this.encodeUuid = function (value) {
562
+ if (typeof value === "string") {
563
+ try {
564
+ value = types.Uuid.fromString(value).getBuffer()
565
+ } catch (err) {
566
+ throw new TypeError(err.message)
567
+ }
568
+ } else if (value instanceof types.Uuid) {
569
+ value = value.getBuffer()
570
+ } else {
571
+ throw new TypeError(
572
+ "Not a valid Uuid, expected Uuid/String/Buffer, obtained " +
573
+ util.inspect(value),
574
+ )
575
+ }
576
+
577
+ return value
578
+ }
579
+ /**
580
+ * @param {String|InetAddress|Buffer} value
581
+ * @returns {Buffer}
582
+ * @private
583
+ */
584
+ this.encodeInet = function (value) {
585
+ if (typeof value === "string") {
586
+ value = types.InetAddress.fromString(value)
587
+ }
588
+ if (value instanceof types.InetAddress) {
589
+ value = value.getBuffer()
590
+ }
591
+ if (!(value instanceof Buffer)) {
592
+ throw new TypeError(
593
+ "Not a valid Inet, expected InetAddress/Buffer, obtained " +
594
+ util.inspect(value),
595
+ )
596
+ }
597
+ return value
598
+ }
599
+
600
+ /**
601
+ * @param {Long|Buffer|String|Number} value
602
+ * @private
603
+ */
604
+ this._encodeBigIntFromLong = function (value) {
605
+ if (typeof value === "number") {
606
+ value = Long.fromNumber(value)
607
+ } else if (typeof value === "string") {
608
+ value = Long.fromString(value)
609
+ }
610
+
611
+ let buf = null
612
+
613
+ if (value instanceof Long) {
614
+ buf = Long.toBuffer(value)
615
+ } else if (value instanceof MutableLong) {
616
+ buf = Long.toBuffer(value.toImmutable())
617
+ }
618
+
619
+ if (buf === null) {
620
+ throw new TypeError(
621
+ "Not a valid bigint, expected Long/Number/String/Buffer, obtained " +
622
+ util.inspect(value),
623
+ )
624
+ }
625
+
626
+ return buf
627
+ }
628
+
629
+ this._encodeBigIntFromBigInt = function (value) {
630
+ if (typeof value === "string") {
631
+ // All numeric types are supported as strings for historical reasons
632
+ value = BigInt(value)
633
+ }
634
+
635
+ // eslint-disable-next-line valid-typeof
636
+ if (typeof value !== "bigint") {
637
+ // Only BigInt values are supported
638
+ throw new TypeError(
639
+ "Not a valid BigInt value, obtained " + util.inspect(value),
640
+ )
641
+ }
642
+
643
+ const buffer = utils.allocBufferUnsafe(8)
644
+ buffer.writeUInt32BE(Number(value >> bigInt32) >>> 0, 0)
645
+ buffer.writeUInt32BE(Number(value & bigInt32BitsOn), 4)
646
+ return buffer
647
+ }
648
+
649
+ this.encodeLong = this.encodingOptions.useBigIntAsLong
650
+ ? this._encodeBigIntFromBigInt
651
+ : this._encodeBigIntFromLong
652
+
653
+ /**
654
+ * @param {Integer|Buffer|String|Number} value
655
+ * @returns {Buffer}
656
+ * @private
657
+ */
658
+ this._encodeVarintFromInteger = function (value) {
659
+ if (typeof value === "number") {
660
+ value = Integer.fromNumber(value)
661
+ }
662
+ if (typeof value === "string") {
663
+ value = Integer.fromString(value)
664
+ }
665
+ let buf = null
666
+ if (value instanceof Buffer) {
667
+ buf = value
668
+ }
669
+ if (value instanceof Integer) {
670
+ buf = Integer.toBuffer(value)
671
+ }
672
+ if (buf === null) {
673
+ throw new TypeError(
674
+ "Not a valid varint, expected Integer/Number/String/Buffer, obtained " +
675
+ util.inspect(value),
676
+ )
677
+ }
678
+ return buf
679
+ }
680
+
681
+ this._encodeVarintFromBigInt = function (value) {
682
+ if (typeof value === "string") {
683
+ // All numeric types are supported as strings for historical reasons
684
+ value = BigInt(value)
685
+ }
686
+
687
+ // eslint-disable-next-line valid-typeof
688
+ if (typeof value !== "bigint") {
689
+ throw new TypeError(
690
+ "Not a valid varint, expected BigInt, obtained " +
691
+ util.inspect(value),
692
+ )
693
+ }
694
+
695
+ if (value === bigInt0) {
696
+ return buffers.int8Zero
697
+ } else if (value === bigIntMinus1) {
698
+ return buffers.int8MaxValue
699
+ }
700
+
701
+ const parts = []
702
+
703
+ if (value > bigInt0) {
704
+ while (value !== bigInt0) {
705
+ parts.unshift(Number(value & bigInt8BitsOn))
706
+ value = value >> bigInt8
707
+ }
708
+
709
+ if (parts[0] > 0x7f) {
710
+ // Positive value needs a padding
711
+ parts.unshift(0)
712
+ }
713
+ } else {
714
+ while (value !== bigIntMinus1) {
715
+ parts.unshift(Number(value & bigInt8BitsOn))
716
+ value = value >> bigInt8
717
+ }
718
+
719
+ if (parts[0] <= 0x7f) {
720
+ // Negative value needs a padding
721
+ parts.unshift(0xff)
722
+ }
723
+ }
724
+
725
+ return utils.allocBufferFromArray(parts)
726
+ }
727
+
728
+ this.encodeVarint = this.encodingOptions.useBigIntAsVarint
729
+ ? this._encodeVarintFromBigInt
730
+ : this._encodeVarintFromInteger
731
+
732
+ /**
733
+ * @param {BigDecimal|Buffer|String|Number} value
734
+ * @returns {Buffer}
735
+ * @private
736
+ */
737
+ this.encodeDecimal = function (value) {
738
+ if (typeof value === "number") {
739
+ value = BigDecimal.fromNumber(value)
740
+ } else if (typeof value === "string") {
741
+ value = BigDecimal.fromString(value)
742
+ }
743
+
744
+ let buf = null
745
+
746
+ if (value instanceof BigDecimal) {
747
+ buf = BigDecimal.toBuffer(value)
748
+ } else {
749
+ throw new TypeError(
750
+ "Not a valid varint, expected BigDecimal/Number/String/Buffer, obtained " +
751
+ util.inspect(value),
752
+ )
753
+ }
754
+
755
+ return buf
756
+ }
757
+ this.encodeString = function (value, encoding) {
758
+ if (typeof value !== "string") {
759
+ throw new TypeError(
760
+ "Not a valid text value, expected String obtained " +
761
+ util.inspect(value),
762
+ )
763
+ }
764
+ return utils.allocBufferFromString(value, encoding)
765
+ }
766
+ this.encodeUtf8String = function (value) {
767
+ return this.encodeString(value, "utf8")
768
+ }
769
+ this.encodeAsciiString = function (value) {
770
+ return this.encodeString(value, "ascii")
771
+ }
772
+ this.encodeBlob = function (value) {
773
+ if (!(value instanceof Buffer)) {
774
+ throw new TypeError(
775
+ "Not a valid blob, expected Buffer obtained " +
776
+ util.inspect(value),
777
+ )
778
+ }
779
+ return value
780
+ }
781
+
782
+ /**
783
+ *
784
+ * @param {any} value
785
+ * @param {OtherCustomColumnInfo | VectorColumnInfo} columnInfo
786
+ */
787
+ this.encodeCustom = function (value, columnInfo) {
788
+ if (
789
+ "customTypeName" in columnInfo &&
790
+ columnInfo.customTypeName === "vector"
791
+ ) {
792
+ return this.encodeVector(value, columnInfo)
793
+ }
794
+
795
+ if (
796
+ typeof columnInfo.info === "string" &&
797
+ columnInfo.info.startsWith(customTypeNames.vector)
798
+ ) {
799
+ const vectorColumnInfo = /** @type {VectorColumnInfo} */ (
800
+ this.parseFqTypeName(columnInfo.info)
801
+ )
802
+ return this.encodeVector(value, vectorColumnInfo)
803
+ }
804
+
805
+ const handler = customEncoders[columnInfo.info]
806
+ if (handler) {
807
+ return handler.call(this, value)
808
+ }
809
+ throw new TypeError("No encoding handler found for type " + columnInfo)
810
+ }
811
+ /**
812
+ * @param {Boolean} value
813
+ * @returns {Buffer}
814
+ * @private
815
+ */
816
+ this.encodeBoolean = function (value) {
817
+ return value ? buffers.int8One : buffers.int8Zero
818
+ }
819
+ /**
820
+ * @param {Number|String} value
821
+ * @private
822
+ */
823
+ this.encodeInt = function (value) {
824
+ if (isNaN(value)) {
825
+ throw new TypeError(
826
+ "Expected Number, obtained " + util.inspect(value),
827
+ )
828
+ }
829
+ const buf = utils.allocBufferUnsafe(4)
830
+ buf.writeInt32BE(value, 0)
831
+ return buf
832
+ }
833
+ /**
834
+ * @param {Number|String} value
835
+ * @private
836
+ */
837
+ this.encodeSmallint = function (value) {
838
+ if (isNaN(value)) {
839
+ throw new TypeError(
840
+ "Expected Number, obtained " + util.inspect(value),
841
+ )
842
+ }
843
+ const buf = utils.allocBufferUnsafe(2)
844
+ buf.writeInt16BE(value, 0)
845
+ return buf
846
+ }
847
+ /**
848
+ * @param {Number} value
849
+ * @private
850
+ */
851
+ this.encodeTinyint = function (value) {
852
+ if (isNaN(value)) {
853
+ throw new TypeError(
854
+ "Expected Number, obtained " + util.inspect(value),
855
+ )
856
+ }
857
+ const buf = utils.allocBufferUnsafe(1)
858
+ buf.writeInt8(value, 0)
859
+ return buf
860
+ }
861
+ this.encodeList = function (value, columnInfo) {
862
+ const subtype = columnInfo.info
863
+ if (!Array.isArray(value)) {
864
+ throw new TypeError(
865
+ "Not a valid list value, expected Array obtained " +
866
+ util.inspect(value),
867
+ )
868
+ }
869
+ if (value.length === 0) {
870
+ return null
871
+ }
872
+ const parts = []
873
+ parts.push(this.getLengthBuffer(value))
874
+ for (let i = 0; i < value.length; i++) {
875
+ const val = value[i]
876
+ if (
877
+ val === null ||
878
+ typeof val === "undefined" ||
879
+ val === types.unset
880
+ ) {
881
+ throw new TypeError(
882
+ "A collection can't contain null or unset values",
883
+ )
884
+ }
885
+ const bytes = this.encode(val, subtype)
886
+ //include item byte length
887
+ parts.push(this.getLengthBuffer(bytes))
888
+ //include item
889
+ parts.push(bytes)
890
+ }
891
+ return Buffer.concat(parts)
892
+ }
893
+ this.encodeSet = function (value, columnInfo) {
894
+ if (
895
+ this.encodingOptions.set &&
896
+ value instanceof this.encodingOptions.set
897
+ ) {
898
+ const arr = []
899
+ value.forEach(function (x) {
900
+ arr.push(x)
901
+ })
902
+ return this.encodeList(arr, columnInfo)
903
+ }
904
+ return this.encodeList(value, columnInfo)
905
+ }
906
+ /**
907
+ * Serializes a map into a Buffer
908
+ * @param value
909
+ * @param {MapColumnInfo} columnInfo
910
+ * @returns {Buffer}
911
+ * @private
912
+ */
913
+ this.encodeMap = function (value, columnInfo) {
914
+ const subtypes = columnInfo.info
915
+ const parts = []
916
+ let propCounter = 0
917
+ let keySubtype = null
918
+ let valueSubtype = null
919
+ const self = this
920
+ if (subtypes) {
921
+ keySubtype = subtypes[0]
922
+ valueSubtype = subtypes[1]
923
+ }
924
+ function addItem(val, key) {
925
+ if (
926
+ key === null ||
927
+ typeof key === "undefined" ||
928
+ key === types.unset
929
+ ) {
930
+ throw new TypeError("A map can't contain null or unset keys")
931
+ }
932
+ if (
933
+ val === null ||
934
+ typeof val === "undefined" ||
935
+ val === types.unset
936
+ ) {
937
+ throw new TypeError("A map can't contain null or unset values")
938
+ }
939
+ const keyBuffer = self.encode(key, keySubtype)
940
+ //include item byte length
941
+ parts.push(self.getLengthBuffer(keyBuffer))
942
+ //include item
943
+ parts.push(keyBuffer)
944
+ //value
945
+ const valueBuffer = self.encode(val, valueSubtype)
946
+ //include item byte length
947
+ parts.push(self.getLengthBuffer(valueBuffer))
948
+ //include item
949
+ if (valueBuffer !== null) {
950
+ parts.push(valueBuffer)
951
+ }
952
+ propCounter++
953
+ }
954
+ if (
955
+ this.encodingOptions.map &&
956
+ value instanceof this.encodingOptions.map
957
+ ) {
958
+ //Use Map#forEach() method to iterate
959
+ value.forEach(addItem)
960
+ } else {
961
+ //Use object
962
+ for (const key in value) {
963
+ if (!value.hasOwnProperty(key)) {
964
+ continue
965
+ }
966
+ const val = value[key]
967
+ addItem(val, key)
968
+ }
969
+ }
970
+
971
+ parts.unshift(this.getLengthBuffer(propCounter))
972
+ return Buffer.concat(parts)
973
+ }
974
+ /**
975
+ *
976
+ * @param {any} value
977
+ * @param {UdtColumnInfo} columnInfo
978
+ */
979
+ this.encodeUdt = function (value, columnInfo) {
980
+ const udtInfo = columnInfo.info
981
+ const parts = []
982
+ let totalLength = 0
983
+ for (let i = 0; i < udtInfo.fields.length; i++) {
984
+ const field = udtInfo.fields[i]
985
+ const item = this.encode(value[field.name], field.type)
986
+ if (!item) {
987
+ parts.push(nullValueBuffer)
988
+ totalLength += 4
989
+ continue
990
+ }
991
+ if (item === types.unset) {
992
+ parts.push(unsetValueBuffer)
993
+ totalLength += 4
994
+ continue
995
+ }
996
+ const lengthBuffer = utils.allocBufferUnsafe(4)
997
+ lengthBuffer.writeInt32BE(item.length, 0)
998
+ parts.push(lengthBuffer)
999
+ parts.push(item)
1000
+ totalLength += item.length + 4
1001
+ }
1002
+ return Buffer.concat(parts, totalLength)
1003
+ }
1004
+ /**
1005
+ *
1006
+ * @param {any} value
1007
+ * @param {TupleColumnInfo} columnInfo
1008
+ */
1009
+ this.encodeTuple = function (value, columnInfo) {
1010
+ const tupleInfo = columnInfo.info
1011
+ const parts = []
1012
+ let totalLength = 0
1013
+ const length = Math.min(tupleInfo.length, value.length)
1014
+
1015
+ for (let i = 0; i < length; i++) {
1016
+ const type = tupleInfo[i]
1017
+ const item = this.encode(value.get(i), type)
1018
+
1019
+ if (!item) {
1020
+ parts.push(nullValueBuffer)
1021
+ totalLength += 4
1022
+ continue
1023
+ }
1024
+
1025
+ if (item === types.unset) {
1026
+ parts.push(unsetValueBuffer)
1027
+ totalLength += 4
1028
+ continue
1029
+ }
1030
+
1031
+ const lengthBuffer = utils.allocBufferUnsafe(4)
1032
+ lengthBuffer.writeInt32BE(item.length, 0)
1033
+ parts.push(lengthBuffer)
1034
+ parts.push(item)
1035
+ totalLength += item.length + 4
1036
+ }
1037
+
1038
+ return Buffer.concat(parts, totalLength)
1039
+ }
1040
+
1041
+ /**
1042
+ *
1043
+ * @param {Buffer} buffer
1044
+ * @param {VectorColumnInfo} params
1045
+ * @returns {Vector}
1046
+ */
1047
+ this.decodeVector = function (buffer, params) {
1048
+ const subtype = params.info[0]
1049
+ const dimension = params.info[1]
1050
+ const elemLength = this.serializationSizeIfFixed(subtype)
1051
+
1052
+ const rv = []
1053
+ let offset = 0
1054
+ for (let i = 0; i < dimension; i++) {
1055
+ if (elemLength === -1) {
1056
+ // var sized
1057
+ const [size, bytesRead] = utils.VIntCoding.uvintUnpack(
1058
+ buffer.subarray(offset),
1059
+ )
1060
+ offset += bytesRead
1061
+ if (offset + size > buffer.length) {
1062
+ throw new TypeError("Not enough bytes to decode the vector")
1063
+ }
1064
+ rv[i] = this.decode(
1065
+ buffer.subarray(offset, offset + size),
1066
+ subtype,
1067
+ )
1068
+ offset += size
1069
+ } else {
1070
+ if (offset + elemLength > buffer.length) {
1071
+ throw new TypeError("Not enough bytes to decode the vector")
1072
+ }
1073
+ rv[i] = this.decode(
1074
+ buffer.subarray(offset, offset + elemLength),
1075
+ subtype,
1076
+ )
1077
+ offset += elemLength
1078
+ }
1079
+ }
1080
+ if (offset !== buffer.length) {
1081
+ throw new TypeError("Extra bytes found after decoding the vector")
1082
+ }
1083
+ const typeInfo = types.getDataTypeNameByCode(subtype)
1084
+ return new Vector(rv, typeInfo)
1085
+ }
1086
+
1087
+ /**
1088
+ * @param {ColumnInfo} cqlType
1089
+ * @returns {Number}
1090
+ */
1091
+ this.serializationSizeIfFixed = function (cqlType) {
1092
+ switch (cqlType.code) {
1093
+ case dataTypes.bigint:
1094
+ return 8
1095
+ case dataTypes.boolean:
1096
+ return 1
1097
+ case dataTypes.timestamp:
1098
+ return 8
1099
+ case dataTypes.double:
1100
+ return 8
1101
+ case dataTypes.float:
1102
+ return 4
1103
+ case dataTypes.int:
1104
+ return 4
1105
+ case dataTypes.timeuuid:
1106
+ return 16
1107
+ case dataTypes.uuid:
1108
+ return 16
1109
+ case dataTypes.custom:
1110
+ if (
1111
+ "customTypeName" in cqlType &&
1112
+ cqlType.customTypeName === "vector"
1113
+ ) {
1114
+ const subtypeSerialSize = this.serializationSizeIfFixed(
1115
+ cqlType.info[0],
1116
+ )
1117
+ if (subtypeSerialSize === -1) {
1118
+ return -1
1119
+ }
1120
+ return subtypeSerialSize * cqlType.info[1]
1121
+ }
1122
+ return -1
1123
+ default:
1124
+ return -1
1125
+ }
1126
+ }
1127
+ /**
1128
+ * @param {Vector} value
1129
+ * @param {VectorColumnInfo} params
1130
+ * @returns {Buffer}
1131
+ */
1132
+ this.encodeVector = function (value, params) {
1133
+ if (!(value instanceof Vector)) {
1134
+ throw new TypeError(
1135
+ "Driver only supports Vector type when encoding a vector",
1136
+ )
1137
+ }
1138
+
1139
+ const dimension = params.info[1]
1140
+ if (value.length !== dimension) {
1141
+ throw new TypeError(
1142
+ `Expected vector with ${dimension} dimensions, observed size of ${value.length}`,
1143
+ )
1144
+ }
1145
+
1146
+ if (value.length === 0) {
1147
+ throw new TypeError("Cannot encode empty array as vector")
1148
+ }
1149
+
1150
+ const serializationSize = this.serializationSizeIfFixed(params.info[0])
1151
+ const encoded = []
1152
+ for (const elem of value) {
1153
+ const elemBuffer = this.encode(elem, params.info[0])
1154
+ if (serializationSize === -1) {
1155
+ encoded.push(utils.VIntCoding.uvintPack(elemBuffer.length))
1156
+ }
1157
+ encoded.push(elemBuffer)
1158
+ }
1159
+ return Buffer.concat(encoded)
1160
+ }
1161
+
1162
+ /**
1163
+ * Extract the (typed) arguments from a vector type
1164
+ *
1165
+ * @param {String} typeName
1166
+ * @param {String} stringToExclude Leading string indicating this is a vector type (to be excluded when eval'ing args)
1167
+ * @param {Function} subtypeResolveFn Function used to resolve subtype type; varies depending on type naming convention
1168
+ * @returns {VectorColumnInfo}
1169
+ * @internal
1170
+ */
1171
+ this.parseVectorTypeArgs = function (
1172
+ typeName,
1173
+ stringToExclude,
1174
+ subtypeResolveFn,
1175
+ ) {
1176
+ const argsStartIndex = stringToExclude.length + 1
1177
+ const argsLength = typeName.length - (stringToExclude.length + 2)
1178
+ const params = parseParams(typeName, argsStartIndex, argsLength)
1179
+ if (params.length === 2) {
1180
+ /** @type {VectorColumnInfo} */
1181
+ const columnInfo = {
1182
+ code: dataTypes.custom,
1183
+ info: [
1184
+ subtypeResolveFn.bind(this)(params[0].trim()),
1185
+ parseInt(params[1].trim(), 10),
1186
+ ],
1187
+ customTypeName: "vector",
1188
+ }
1189
+ return columnInfo
1190
+ }
1191
+
1192
+ throw new TypeError("Not a valid type " + typeName)
1193
+ }
1194
+
1195
+ /**
1196
+ * If not provided, it uses the array of buffers or the parameters and hints to build the routingKey
1197
+ * @param {Array} params
1198
+ * @param [keys] parameter keys and positions in the params array
1199
+ * @throws TypeError
1200
+ * @internal
1201
+ * @ignore
1202
+ */
1203
+ this.setRoutingKeyFromUser = function (params, execOptions, keys) {
1204
+ let totalLength = 0
1205
+ const userRoutingKey = execOptions.getRoutingKey()
1206
+ if (Array.isArray(userRoutingKey)) {
1207
+ if (userRoutingKey.length === 1) {
1208
+ execOptions.setRoutingKey(userRoutingKey[0])
1209
+ return
1210
+ }
1211
+
1212
+ // Its a composite routing key
1213
+ totalLength = 0
1214
+ for (let i = 0; i < userRoutingKey.length; i++) {
1215
+ const item = userRoutingKey[i]
1216
+ if (!item) {
1217
+ // Invalid routing key part provided by the user, clear the value
1218
+ execOptions.setRoutingKey(null)
1219
+ return
1220
+ }
1221
+ totalLength += item.length + 3
1222
+ }
1223
+
1224
+ execOptions.setRoutingKey(
1225
+ concatRoutingKey(userRoutingKey, totalLength),
1226
+ )
1227
+ return
1228
+ }
1229
+ // If routingKey is present, ensure it is a Buffer, Token, or TokenRange. Otherwise throw an error.
1230
+ if (userRoutingKey) {
1231
+ if (
1232
+ userRoutingKey instanceof Buffer ||
1233
+ userRoutingKey instanceof token.Token ||
1234
+ userRoutingKey instanceof token.TokenRange
1235
+ ) {
1236
+ return
1237
+ }
1238
+
1239
+ throw new TypeError(
1240
+ `Unexpected routingKey '${util.inspect(userRoutingKey)}' provided. ` +
1241
+ `Expected Buffer, Array<Buffer>, Token, or TokenRange.`,
1242
+ )
1243
+ }
1244
+
1245
+ // If no params are present, return as routing key cannot be determined.
1246
+ if (!params || params.length === 0) {
1247
+ return
1248
+ }
1249
+
1250
+ let routingIndexes = execOptions.getRoutingIndexes()
1251
+ if (execOptions.getRoutingNames()) {
1252
+ routingIndexes = execOptions.getRoutingNames().map((k) => keys[k])
1253
+ }
1254
+ if (!routingIndexes) {
1255
+ return
1256
+ }
1257
+
1258
+ const parts = []
1259
+ const hints = execOptions.getHints() || utils.emptyArray
1260
+
1261
+ const encodeParam = !keys
1262
+ ? (i) => this.encode(params[i], hints[i])
1263
+ : (i) => this.encode(params[i].value, hints[i])
1264
+
1265
+ try {
1266
+ totalLength = this._encodeRoutingKeyParts(
1267
+ parts,
1268
+ routingIndexes,
1269
+ encodeParam,
1270
+ )
1271
+ } catch (e) {
1272
+ // There was an error encoding a parameter that is part of the routing key,
1273
+ // ignore now to fail afterwards
1274
+ }
1275
+
1276
+ if (totalLength === 0) {
1277
+ return
1278
+ }
1279
+
1280
+ execOptions.setRoutingKey(concatRoutingKey(parts, totalLength))
1281
+ }
1282
+
1283
+ /**
1284
+ * Sets the routing key in the options based on the prepared statement metadata.
1285
+ * @param {Object} meta Prepared metadata
1286
+ * @param {Array} params Array of parameters
1287
+ * @param {ExecutionOptions} execOptions
1288
+ * @throws TypeError
1289
+ * @internal
1290
+ * @ignore
1291
+ */
1292
+ this.setRoutingKeyFromMeta = function (meta, params, execOptions) {
1293
+ const routingIndexes = execOptions.getRoutingIndexes()
1294
+ if (!routingIndexes) {
1295
+ return
1296
+ }
1297
+ const parts = new Array(routingIndexes.length)
1298
+ const encodeParam = (i) => {
1299
+ const columnInfo = meta.columns[i]
1300
+ return this.encode(params[i], columnInfo ? columnInfo.type : null)
1301
+ }
1302
+
1303
+ let totalLength = 0
1304
+
1305
+ try {
1306
+ totalLength = this._encodeRoutingKeyParts(
1307
+ parts,
1308
+ routingIndexes,
1309
+ encodeParam,
1310
+ )
1311
+ } catch (e) {
1312
+ // There was an error encoding a parameter that is part of the routing key,
1313
+ // ignore now to fail afterwards
1314
+ }
1315
+
1316
+ if (totalLength === 0) {
1317
+ return
1318
+ }
1319
+
1320
+ execOptions.setRoutingKey(concatRoutingKey(parts, totalLength))
1321
+ }
1322
+
1323
+ /**
1324
+ * @param {Array} parts
1325
+ * @param {Array} routingIndexes
1326
+ * @param {Function} encodeParam
1327
+ * @returns {Number} The total length
1328
+ * @private
1329
+ */
1330
+ this._encodeRoutingKeyParts = function (
1331
+ parts,
1332
+ routingIndexes,
1333
+ encodeParam,
1334
+ ) {
1335
+ let totalLength = 0
1336
+ for (let i = 0; i < routingIndexes.length; i++) {
1337
+ const paramIndex = routingIndexes[i]
1338
+ if (paramIndex === undefined) {
1339
+ // Bad input from the user, ignore
1340
+ return 0
1341
+ }
1342
+
1343
+ const item = encodeParam(paramIndex)
1344
+ if (item === null || item === undefined || item === types.unset) {
1345
+ // The encoded partition key should an instance of Buffer
1346
+ // Let it fail later in the pipeline for null/undefined parameter values
1347
+ return 0
1348
+ }
1349
+
1350
+ // Per each part of the routing key, 3 extra bytes are needed
1351
+ totalLength += item.length + 3
1352
+ parts[i] = item
1353
+ }
1354
+ return totalLength
1355
+ }
1356
+
1357
+ /**
1358
+ * Parses a CQL name string into data type information
1359
+ * @param {String} keyspace
1360
+ * @param {String} typeName
1361
+ * @param {Number} startIndex
1362
+ * @param {Number|null} length
1363
+ * @param {Function} udtResolver
1364
+ * @async
1365
+ * @returns {Promise.<ColumnInfo>} callback Callback invoked with err and {{code: number, info: Object|Array|null, options: {frozen: Boolean}}}
1366
+ * @internal
1367
+ * @throws {Error}
1368
+ * @ignore
1369
+ */
1370
+ this.parseTypeName = async function (
1371
+ keyspace,
1372
+ typeName,
1373
+ startIndex,
1374
+ length,
1375
+ udtResolver,
1376
+ ) {
1377
+ startIndex = startIndex || 0
1378
+ if (!length) {
1379
+ length = typeName.length
1380
+ }
1381
+
1382
+ let innerTypes
1383
+ let frozen = false
1384
+
1385
+ if (typeName.indexOf("'", startIndex) === startIndex) {
1386
+ //If quoted, this is a custom type.
1387
+ const info = typeName.substr(startIndex + 1, length - 2)
1388
+ return {
1389
+ code: dataTypes.custom,
1390
+ info: info,
1391
+ }
1392
+ }
1393
+
1394
+ if (!length) {
1395
+ length = typeName.length
1396
+ }
1397
+
1398
+ if (typeName.indexOf(cqlNames.frozen, startIndex) === startIndex) {
1399
+ //Remove the frozen token
1400
+ startIndex += cqlNames.frozen.length + 1
1401
+ length -= cqlNames.frozen.length + 2
1402
+ frozen = true
1403
+ }
1404
+
1405
+ if (typeName.indexOf(cqlNames.list, startIndex) === startIndex) {
1406
+ //move cursor across the name and bypass the angle brackets
1407
+ startIndex += cqlNames.list.length + 1
1408
+ length -= cqlNames.list.length + 2
1409
+ innerTypes = parseParams(typeName, startIndex, length, "<", ">")
1410
+
1411
+ if (innerTypes.length !== 1) {
1412
+ throw new TypeError("Not a valid type " + typeName)
1413
+ }
1414
+
1415
+ const info = await this.parseTypeName(
1416
+ keyspace,
1417
+ innerTypes[0],
1418
+ 0,
1419
+ null,
1420
+ udtResolver,
1421
+ )
1422
+ return {
1423
+ code: dataTypes.list,
1424
+ info: info,
1425
+ options: {
1426
+ frozen: frozen,
1427
+ },
1428
+ }
1429
+ }
1430
+
1431
+ if (typeName.indexOf(cqlNames.set, startIndex) === startIndex) {
1432
+ //move cursor across the name and bypass the angle brackets
1433
+ startIndex += cqlNames.set.length + 1
1434
+ length -= cqlNames.set.length + 2
1435
+ innerTypes = parseParams(typeName, startIndex, length, "<", ">")
1436
+
1437
+ if (innerTypes.length !== 1) {
1438
+ throw new TypeError("Not a valid type " + typeName)
1439
+ }
1440
+
1441
+ const info = await this.parseTypeName(
1442
+ keyspace,
1443
+ innerTypes[0],
1444
+ 0,
1445
+ null,
1446
+ udtResolver,
1447
+ )
1448
+ return {
1449
+ code: dataTypes.set,
1450
+ info: info,
1451
+ options: {
1452
+ frozen: frozen,
1453
+ },
1454
+ }
1455
+ }
1456
+
1457
+ if (typeName.indexOf(cqlNames.map, startIndex) === startIndex) {
1458
+ //move cursor across the name and bypass the angle brackets
1459
+ startIndex += cqlNames.map.length + 1
1460
+ length -= cqlNames.map.length + 2
1461
+ innerTypes = parseParams(typeName, startIndex, length, "<", ">")
1462
+
1463
+ //It should contain the key and value types
1464
+ if (innerTypes.length !== 2) {
1465
+ throw new TypeError("Not a valid type " + typeName)
1466
+ }
1467
+
1468
+ const info = await this._parseChildTypes(
1469
+ keyspace,
1470
+ innerTypes,
1471
+ udtResolver,
1472
+ )
1473
+ return {
1474
+ code: dataTypes.map,
1475
+ info: info,
1476
+ options: {
1477
+ frozen: frozen,
1478
+ },
1479
+ }
1480
+ }
1481
+
1482
+ if (typeName.indexOf(cqlNames.tuple, startIndex) === startIndex) {
1483
+ //move cursor across the name and bypass the angle brackets
1484
+ startIndex += cqlNames.tuple.length + 1
1485
+ length -= cqlNames.tuple.length + 2
1486
+ innerTypes = parseParams(typeName, startIndex, length, "<", ">")
1487
+
1488
+ if (innerTypes.length < 1) {
1489
+ throw new TypeError("Not a valid type " + typeName)
1490
+ }
1491
+
1492
+ const info = await this._parseChildTypes(
1493
+ keyspace,
1494
+ innerTypes,
1495
+ udtResolver,
1496
+ )
1497
+ return {
1498
+ code: dataTypes.tuple,
1499
+ info: info,
1500
+ options: { frozen: frozen },
1501
+ }
1502
+ }
1503
+
1504
+ if (typeName.indexOf(cqlNames.vector, startIndex) === startIndex) {
1505
+ // It's a vector, so record the subtype and dimension.
1506
+
1507
+ // parseVectorTypeArgs is not an async function but we are. To keep things simple let's ask the
1508
+ // function to just return whatever it finds for an arg and we'll eval it after the fact
1509
+ const params = this.parseVectorTypeArgs.bind(this)(
1510
+ typeName,
1511
+ cqlNames.vector,
1512
+ (arg) => arg,
1513
+ )
1514
+ params["info"][0] = await this.parseTypeName(
1515
+ keyspace,
1516
+ params["info"][0],
1517
+ )
1518
+
1519
+ return params
1520
+ }
1521
+
1522
+ const quoted = typeName.indexOf('"', startIndex) === startIndex
1523
+ if (quoted) {
1524
+ // Remove quotes
1525
+ startIndex++
1526
+ length -= 2
1527
+ }
1528
+
1529
+ // Quick check if its a single type
1530
+ if (startIndex > 0) {
1531
+ typeName = typeName.substr(startIndex, length)
1532
+ }
1533
+
1534
+ // Un-escape double quotes if quoted.
1535
+ if (quoted) {
1536
+ typeName = typeName.replace('""', '"')
1537
+ }
1538
+
1539
+ const typeCode = dataTypes[typeName]
1540
+ if (typeof typeCode === "number") {
1541
+ return { code: typeCode, info: null }
1542
+ }
1543
+
1544
+ if (typeName === cqlNames.duration) {
1545
+ return { code: dataTypes.custom, info: customTypeNames.duration }
1546
+ }
1547
+
1548
+ if (typeName === cqlNames.empty) {
1549
+ // Set as custom
1550
+ return { code: dataTypes.custom, info: "empty" }
1551
+ }
1552
+
1553
+ const udtInfo = await udtResolver(keyspace, typeName)
1554
+ if (udtInfo) {
1555
+ return {
1556
+ code: dataTypes.udt,
1557
+ info: udtInfo,
1558
+ options: {
1559
+ frozen: frozen,
1560
+ },
1561
+ }
1562
+ }
1563
+
1564
+ throw new TypeError('Not a valid type "' + typeName + '"')
1565
+ }
1566
+
1567
+ /**
1568
+ * @param {String} keyspace
1569
+ * @param {Array} typeNames
1570
+ * @param {Function} udtResolver
1571
+ * @returns {Promise}
1572
+ * @private
1573
+ */
1574
+ this._parseChildTypes = function (keyspace, typeNames, udtResolver) {
1575
+ return Promise.all(
1576
+ typeNames.map((name) =>
1577
+ this.parseTypeName(keyspace, name.trim(), 0, null, udtResolver),
1578
+ ),
1579
+ )
1580
+ }
1581
+
1582
+ /**
1583
+ * Parses a Cassandra fully-qualified class name string into data type information
1584
+ * @param {String} typeName
1585
+ * @param {Number} [startIndex]
1586
+ * @param {Number} [length]
1587
+ * @throws {TypeError}
1588
+ * @returns {ColumnInfo}
1589
+ * @internal
1590
+ * @ignore
1591
+ */
1592
+ this.parseFqTypeName = function (typeName, startIndex, length) {
1593
+ let frozen = false
1594
+ let reversed = false
1595
+ startIndex = startIndex || 0
1596
+ let params
1597
+ if (!length) {
1598
+ length = typeName.length
1599
+ }
1600
+ if (
1601
+ length > complexTypeNames.reversed.length &&
1602
+ typeName.indexOf(complexTypeNames.reversed) === startIndex
1603
+ ) {
1604
+ //Remove the reversed token
1605
+ startIndex += complexTypeNames.reversed.length + 1
1606
+ length -= complexTypeNames.reversed.length + 2
1607
+ reversed = true
1608
+ }
1609
+ if (
1610
+ length > complexTypeNames.frozen.length &&
1611
+ typeName.indexOf(complexTypeNames.frozen, startIndex) === startIndex
1612
+ ) {
1613
+ //Remove the frozen token
1614
+ startIndex += complexTypeNames.frozen.length + 1
1615
+ length -= complexTypeNames.frozen.length + 2
1616
+ frozen = true
1617
+ }
1618
+ const options = {
1619
+ frozen: frozen,
1620
+ reversed: reversed,
1621
+ }
1622
+ if (typeName === complexTypeNames.empty) {
1623
+ //set as custom
1624
+ return {
1625
+ code: dataTypes.custom,
1626
+ info: "empty",
1627
+ options: options,
1628
+ }
1629
+ }
1630
+ //Quick check if its a single type
1631
+ if (length <= singleFqTypeNamesLength) {
1632
+ if (startIndex > 0) {
1633
+ typeName = typeName.substr(startIndex, length)
1634
+ }
1635
+ const typeCode = singleTypeNames[typeName]
1636
+ if (typeof typeCode === "number") {
1637
+ return { code: typeCode, info: null, options: options }
1638
+ }
1639
+ // special handling for duration
1640
+ if (typeName === customTypeNames.duration) {
1641
+ return { code: dataTypes.duration, options: options }
1642
+ }
1643
+ throw new TypeError('Not a valid type "' + typeName + '"')
1644
+ }
1645
+ if (
1646
+ typeName.indexOf(complexTypeNames.list, startIndex) === startIndex
1647
+ ) {
1648
+ //Its a list
1649
+ //org.apache.cassandra.db.marshal.ListType(innerType)
1650
+ //move cursor across the name and bypass the parenthesis
1651
+ startIndex += complexTypeNames.list.length + 1
1652
+ length -= complexTypeNames.list.length + 2
1653
+ params = parseParams(typeName, startIndex, length)
1654
+ if (params.length !== 1) {
1655
+ throw new TypeError("Not a valid type " + typeName)
1656
+ }
1657
+ const info = this.parseFqTypeName(params[0])
1658
+ return {
1659
+ code: dataTypes.list,
1660
+ info: info,
1661
+ options: options,
1662
+ }
1663
+ }
1664
+ if (typeName.indexOf(complexTypeNames.set, startIndex) === startIndex) {
1665
+ //Its a set
1666
+ //org.apache.cassandra.db.marshal.SetType(innerType)
1667
+ //move cursor across the name and bypass the parenthesis
1668
+ startIndex += complexTypeNames.set.length + 1
1669
+ length -= complexTypeNames.set.length + 2
1670
+ params = parseParams(typeName, startIndex, length)
1671
+ if (params.length !== 1) {
1672
+ throw new TypeError("Not a valid type " + typeName)
1673
+ }
1674
+ const info = this.parseFqTypeName(params[0])
1675
+ return {
1676
+ code: dataTypes.set,
1677
+ info: info,
1678
+ options: options,
1679
+ }
1680
+ }
1681
+ if (typeName.indexOf(complexTypeNames.map, startIndex) === startIndex) {
1682
+ //org.apache.cassandra.db.marshal.MapType(keyType,valueType)
1683
+ //move cursor across the name and bypass the parenthesis
1684
+ startIndex += complexTypeNames.map.length + 1
1685
+ length -= complexTypeNames.map.length + 2
1686
+ params = parseParams(typeName, startIndex, length)
1687
+ //It should contain the key and value types
1688
+ if (params.length !== 2) {
1689
+ throw new TypeError("Not a valid type " + typeName)
1690
+ }
1691
+ const info1 = this.parseFqTypeName(params[0])
1692
+ const info2 = this.parseFqTypeName(params[1])
1693
+ return {
1694
+ code: dataTypes.map,
1695
+ info: [info1, info2],
1696
+ options: options,
1697
+ }
1698
+ }
1699
+ if (typeName.indexOf(complexTypeNames.udt, startIndex) === startIndex) {
1700
+ //move cursor across the name and bypass the parenthesis
1701
+ startIndex += complexTypeNames.udt.length + 1
1702
+ length -= complexTypeNames.udt.length + 2
1703
+ const udtType = this._parseUdtName(typeName, startIndex, length)
1704
+ udtType.options = options
1705
+ return udtType
1706
+ }
1707
+ if (
1708
+ typeName.indexOf(complexTypeNames.tuple, startIndex) === startIndex
1709
+ ) {
1710
+ //move cursor across the name and bypass the parenthesis
1711
+ startIndex += complexTypeNames.tuple.length + 1
1712
+ length -= complexTypeNames.tuple.length + 2
1713
+ params = parseParams(typeName, startIndex, length)
1714
+ if (params.length < 1) {
1715
+ throw new TypeError("Not a valid type " + typeName)
1716
+ }
1717
+ const info = params.map((x) => this.parseFqTypeName(x))
1718
+ return {
1719
+ code: dataTypes.tuple,
1720
+ info: info,
1721
+ options: options,
1722
+ }
1723
+ }
1724
+
1725
+ if (
1726
+ typeName.indexOf(customTypeNames.vector, startIndex) === startIndex
1727
+ ) {
1728
+ // It's a vector, so record the subtype and dimension.
1729
+ const params = this.parseVectorTypeArgs.bind(this)(
1730
+ typeName,
1731
+ customTypeNames.vector,
1732
+ this.parseFqTypeName,
1733
+ )
1734
+ params.options = options
1735
+ return params
1736
+ }
1737
+
1738
+ // Assume custom type if cannot be parsed up to this point.
1739
+ const info = typeName.substr(startIndex, length)
1740
+ return {
1741
+ code: dataTypes.custom,
1742
+ info: info,
1743
+ options: options,
1744
+ }
1745
+ }
1746
+ /**
1747
+ * Parses type names with composites
1748
+ * @param {String} typesString
1749
+ * @returns {{types: Array, isComposite: Boolean, hasCollections: Boolean}}
1750
+ * @internal
1751
+ * @ignore
1752
+ */
1753
+ this.parseKeyTypes = function (typesString) {
1754
+ let i = 0
1755
+ let length = typesString.length
1756
+ const isComposite =
1757
+ typesString.indexOf(complexTypeNames.composite) === 0
1758
+ if (isComposite) {
1759
+ i = complexTypeNames.composite.length + 1
1760
+ length--
1761
+ }
1762
+ const types = []
1763
+ let startIndex = i
1764
+ let nested = 0
1765
+ let inCollectionType = false
1766
+ let hasCollections = false
1767
+ //as collection types are not allowed, it is safe to split by ,
1768
+ while (++i < length) {
1769
+ switch (typesString[i]) {
1770
+ case ",":
1771
+ if (nested > 0) {
1772
+ break
1773
+ }
1774
+ if (inCollectionType) {
1775
+ //remove type id
1776
+ startIndex = typesString.indexOf(":", startIndex) + 1
1777
+ }
1778
+ types.push(typesString.substring(startIndex, i))
1779
+ startIndex = i + 1
1780
+ break
1781
+ case "(":
1782
+ if (
1783
+ nested === 0 &&
1784
+ typesString.indexOf(
1785
+ complexTypeNames.collection,
1786
+ startIndex,
1787
+ ) === startIndex
1788
+ ) {
1789
+ inCollectionType = true
1790
+ hasCollections = true
1791
+ //skip collection type
1792
+ i++
1793
+ startIndex = i
1794
+ break
1795
+ }
1796
+ nested++
1797
+ break
1798
+ case ")":
1799
+ if (inCollectionType && nested === 0) {
1800
+ types.push(
1801
+ typesString.substring(
1802
+ typesString.indexOf(":", startIndex) + 1,
1803
+ i,
1804
+ ),
1805
+ )
1806
+ startIndex = i + 1
1807
+ break
1808
+ }
1809
+ nested--
1810
+ break
1811
+ }
1812
+ }
1813
+ if (startIndex < length) {
1814
+ types.push(typesString.substring(startIndex, length))
1815
+ }
1816
+ return {
1817
+ types: types.map((name) => this.parseFqTypeName(name)),
1818
+ hasCollections: hasCollections,
1819
+ isComposite: isComposite,
1820
+ }
1821
+ }
1822
+ /**
1823
+ *
1824
+ * @param {string} typeName
1825
+ * @param {number} startIndex
1826
+ * @param {number} length
1827
+ * @returns {UdtColumnInfo}
1828
+ */
1829
+ this._parseUdtName = function (typeName, startIndex, length) {
1830
+ const udtParams = parseParams(typeName, startIndex, length)
1831
+ if (udtParams.length < 2) {
1832
+ //It should contain at least the keyspace, name of the udt and a type
1833
+ throw new TypeError("Not a valid type " + typeName)
1834
+ }
1835
+ /**
1836
+ * @type {{keyspace: String, name: String, fields: Array}}
1837
+ */
1838
+ const udtInfo = {
1839
+ keyspace: udtParams[0],
1840
+ name: utils.allocBufferFromString(udtParams[1], "hex").toString(),
1841
+ fields: [],
1842
+ }
1843
+ for (let i = 2; i < udtParams.length; i++) {
1844
+ const p = udtParams[i]
1845
+ const separatorIndex = p.indexOf(":")
1846
+ const fieldType = this.parseFqTypeName(
1847
+ p,
1848
+ separatorIndex + 1,
1849
+ p.length - (separatorIndex + 1),
1850
+ )
1851
+ udtInfo.fields.push({
1852
+ name: utils
1853
+ .allocBufferFromString(p.substr(0, separatorIndex), "hex")
1854
+ .toString(),
1855
+ type: fieldType,
1856
+ })
1857
+ }
1858
+ return {
1859
+ code: dataTypes.udt,
1860
+ info: udtInfo,
1861
+ }
1862
+ }
1863
+ }
1864
+
1865
+ /**
1866
+ * Sets the encoder and decoder methods for this instance
1867
+ * @private
1868
+ */
1869
+ function setEncoders() {
1870
+ this.decoders = {
1871
+ [dataTypes.custom]: this.decodeCustom,
1872
+ [dataTypes.ascii]: this.decodeAsciiString,
1873
+ [dataTypes.bigint]: this.decodeLong,
1874
+ [dataTypes.blob]: this.decodeBlob,
1875
+ [dataTypes.boolean]: this.decodeBoolean,
1876
+ [dataTypes.counter]: this.decodeLong,
1877
+ [dataTypes.decimal]: this.decodeDecimal,
1878
+ [dataTypes.double]: this.decodeDouble,
1879
+ [dataTypes.float]: this.decodeFloat,
1880
+ [dataTypes.int]: this.decodeInt,
1881
+ [dataTypes.text]: this.decodeUtf8String,
1882
+ [dataTypes.timestamp]: this.decodeTimestamp,
1883
+ [dataTypes.uuid]: this.decodeUuid,
1884
+ [dataTypes.varchar]: this.decodeUtf8String,
1885
+ [dataTypes.varint]: this.decodeVarint,
1886
+ [dataTypes.timeuuid]: this.decodeTimeUuid,
1887
+ [dataTypes.inet]: this.decodeInet,
1888
+ [dataTypes.date]: this.decodeDate,
1889
+ [dataTypes.time]: this.decodeTime,
1890
+ [dataTypes.smallint]: this.decodeSmallint,
1891
+ [dataTypes.tinyint]: this.decodeTinyint,
1892
+ [dataTypes.duration]: decodeDuration,
1893
+ [dataTypes.list]: this.decodeList,
1894
+ [dataTypes.map]: this.decodeMap,
1895
+ [dataTypes.set]: this.decodeSet,
1896
+ [dataTypes.udt]: this.decodeUdt,
1897
+ [dataTypes.tuple]: this.decodeTuple,
1898
+ }
1899
+
1900
+ this.encoders = {
1901
+ [dataTypes.custom]: this.encodeCustom,
1902
+ [dataTypes.ascii]: this.encodeAsciiString,
1903
+ [dataTypes.bigint]: this.encodeLong,
1904
+ [dataTypes.blob]: this.encodeBlob,
1905
+ [dataTypes.boolean]: this.encodeBoolean,
1906
+ [dataTypes.counter]: this.encodeLong,
1907
+ [dataTypes.decimal]: this.encodeDecimal,
1908
+ [dataTypes.double]: this.encodeDouble,
1909
+ [dataTypes.float]: this.encodeFloat,
1910
+ [dataTypes.int]: this.encodeInt,
1911
+ [dataTypes.text]: this.encodeUtf8String,
1912
+ [dataTypes.timestamp]: this.encodeTimestamp,
1913
+ [dataTypes.uuid]: this.encodeUuid,
1914
+ [dataTypes.varchar]: this.encodeUtf8String,
1915
+ [dataTypes.varint]: this.encodeVarint,
1916
+ [dataTypes.timeuuid]: this.encodeUuid,
1917
+ [dataTypes.inet]: this.encodeInet,
1918
+ [dataTypes.date]: this.encodeDate,
1919
+ [dataTypes.time]: this.encodeTime,
1920
+ [dataTypes.smallint]: this.encodeSmallint,
1921
+ [dataTypes.tinyint]: this.encodeTinyint,
1922
+ [dataTypes.duration]: encodeDuration,
1923
+ [dataTypes.list]: this.encodeList,
1924
+ [dataTypes.map]: this.encodeMap,
1925
+ [dataTypes.set]: this.encodeSet,
1926
+ [dataTypes.udt]: this.encodeUdt,
1927
+ [dataTypes.tuple]: this.encodeTuple,
1928
+ }
1929
+ }
1930
+
1931
+ /**
1932
+ * Decodes Cassandra bytes into Javascript values.
1933
+ * <p>
1934
+ * This is part of an <b>experimental</b> API, this can be changed future releases.
1935
+ * </p>
1936
+ * @param {Buffer} buffer Raw buffer to be decoded.
1937
+ * @param {ColumnInfo} type
1938
+ */
1939
+ Encoder.prototype.decode = function (buffer, type) {
1940
+ if (
1941
+ buffer === null ||
1942
+ (buffer.length === 0 && !zeroLengthTypesSupported.has(type.code))
1943
+ ) {
1944
+ return null
1945
+ }
1946
+
1947
+ const decoder = this.decoders[type.code]
1948
+
1949
+ if (!decoder) {
1950
+ throw new Error("Unknown data type: " + type.code)
1951
+ }
1952
+
1953
+ return decoder.call(this, buffer, type)
1954
+ }
1955
+
1956
+ /**
1957
+ * Encodes Javascript types into Buffer according to the Cassandra protocol.
1958
+ * <p>
1959
+ * This is part of an <b>experimental</b> API, this can be changed future releases.
1960
+ * </p>
1961
+ * @param {*} value The value to be converted.
1962
+ * @param {ColumnInfo | Number | String} typeInfo The type information.
1963
+ * <p>It can be either a:</p>
1964
+ * <ul>
1965
+ * <li>A <code>String</code> representing the data type.</li>
1966
+ * <li>A <code>Number</code> with one of the values of {@link module:types~dataTypes dataTypes}.</li>
1967
+ * <li>An <code>Object</code> containing the <code>type.code</code> as one of the values of
1968
+ * {@link module:types~dataTypes dataTypes} and <code>type.info</code>.
1969
+ * </li>
1970
+ * </ul>
1971
+ * @returns {Buffer}
1972
+ * @throws {TypeError} When there is an encoding error
1973
+ */
1974
+ Encoder.prototype.encode = function (value, typeInfo) {
1975
+ if (value === undefined) {
1976
+ value =
1977
+ this.encodingOptions.useUndefinedAsUnset &&
1978
+ this.protocolVersion >= 4
1979
+ ? types.unset
1980
+ : null
1981
+ }
1982
+
1983
+ if (value === types.unset) {
1984
+ if (!types.protocolVersion.supportsUnset(this.protocolVersion)) {
1985
+ throw new TypeError(
1986
+ "Unset value can not be used for this version of Cassandra, protocol version: " +
1987
+ this.protocolVersion,
1988
+ )
1989
+ }
1990
+
1991
+ return value
1992
+ }
1993
+
1994
+ if (value === null || value instanceof Buffer) {
1995
+ return value
1996
+ }
1997
+
1998
+ /** @type {ColumnInfo | null} */
1999
+ let type = null
2000
+
2001
+ if (typeInfo) {
2002
+ if (typeof typeInfo === "number") {
2003
+ type = {
2004
+ code: typeInfo,
2005
+ }
2006
+ } else if (typeof typeInfo === "string") {
2007
+ type = dataTypes.getByName(typeInfo)
2008
+ } else if (typeof typeInfo.code === "number") {
2009
+ type = typeInfo
2010
+ }
2011
+ if (type == null || typeof type.code !== "number") {
2012
+ throw new TypeError(
2013
+ "Type information not valid, only String and Number values are valid hints",
2014
+ )
2015
+ }
2016
+ } else {
2017
+ //Lets guess
2018
+ type = Encoder.guessDataType(value)
2019
+ if (!type) {
2020
+ throw new TypeError(
2021
+ "Target data type could not be guessed, you should use prepared statements for accurate type mapping. Value: " +
2022
+ util.inspect(value),
2023
+ )
2024
+ }
2025
+ }
2026
+
2027
+ const encoder = this.encoders[type.code]
2028
+
2029
+ if (!encoder) {
2030
+ throw new Error("Type not supported " + type.code)
2031
+ }
2032
+
2033
+ return encoder.call(this, value, type)
2034
+ }
2035
+
2036
+ /**
2037
+ * Try to guess the Cassandra type to be stored, based on the javascript value type
2038
+ * @param value
2039
+ * @returns {ColumnInfo | null}
2040
+ * @ignore
2041
+ * @internal
2042
+ */
2043
+ Encoder.guessDataType = function (value) {
2044
+ const esTypeName = typeof value
2045
+ if (esTypeName === "number") {
2046
+ return { code: dataTypes.double }
2047
+ } else if (esTypeName === "string") {
2048
+ if (value.length === 36 && uuidRegex.test(value)) {
2049
+ return { code: dataTypes.uuid }
2050
+ }
2051
+ return { code: dataTypes.text }
2052
+ } else if (esTypeName === "boolean") {
2053
+ return { code: dataTypes.boolean }
2054
+ } else if (value instanceof Buffer) {
2055
+ return { code: dataTypes.blob }
2056
+ } else if (value instanceof Date) {
2057
+ return { code: dataTypes.timestamp }
2058
+ } else if (value instanceof Long) {
2059
+ return { code: dataTypes.bigint }
2060
+ } else if (value instanceof Integer) {
2061
+ return { code: dataTypes.varint }
2062
+ } else if (value instanceof BigDecimal) {
2063
+ return { code: dataTypes.decimal }
2064
+ } else if (value instanceof types.Uuid) {
2065
+ return { code: dataTypes.uuid }
2066
+ } else if (value instanceof types.InetAddress) {
2067
+ return { code: dataTypes.inet }
2068
+ } else if (value instanceof types.Tuple) {
2069
+ return { code: dataTypes.tuple }
2070
+ } else if (value instanceof types.LocalDate) {
2071
+ return { code: dataTypes.date }
2072
+ } else if (value instanceof types.LocalTime) {
2073
+ return { code: dataTypes.time }
2074
+ } else if (value instanceof types.Duration) {
2075
+ return { code: dataTypes.custom, info: customTypeNames.duration }
2076
+ }
2077
+ // Map JS TypedArrays onto vectors
2078
+ else if (value instanceof types.Vector) {
2079
+ if (value && value.length > 0) {
2080
+ if (value instanceof Float32Array) {
2081
+ return {
2082
+ code: dataTypes.custom,
2083
+ customTypeName: "vector",
2084
+ info: [{ code: dataTypes.float }, value.length],
2085
+ }
2086
+ }
2087
+
2088
+ /** @type {ColumnInfo?} */
2089
+ let subtypeColumnInfo = null
2090
+ // try to fetch the subtype from the Vector, or else guess
2091
+ if (value.subtype) {
2092
+ try {
2093
+ subtypeColumnInfo = dataTypes.getByName(value.subtype)
2094
+ } catch (TypeError) {
2095
+ // ignore
2096
+ }
2097
+ }
2098
+ if (subtypeColumnInfo == null) {
2099
+ subtypeColumnInfo = this.guessDataType(value[0])
2100
+ }
2101
+ if (subtypeColumnInfo != null) {
2102
+ return {
2103
+ code: dataTypes.custom,
2104
+ customTypeName: "vector",
2105
+ info: [subtypeColumnInfo, value.length],
2106
+ }
2107
+ }
2108
+ throw new TypeError("Cannot guess subtype from element " + value[0])
2109
+ } else {
2110
+ throw new TypeError("Cannot guess subtype of empty vector")
2111
+ }
2112
+ } else if (Array.isArray(value)) {
2113
+ return { code: dataTypes.list }
2114
+ }
2115
+
2116
+ return null
2117
+ }
2118
+
2119
+ /**
2120
+ * Gets a buffer containing with the bytes (BE) representing the collection length for protocol v2 and below
2121
+ * @param {Buffer|Number} value
2122
+ * @returns {Buffer}
2123
+ * @private
2124
+ */
2125
+ function getLengthBufferV2(value) {
2126
+ if (!value) {
2127
+ return buffers.int16Zero
2128
+ }
2129
+ const lengthBuffer = utils.allocBufferUnsafe(2)
2130
+ if (typeof value === "number") {
2131
+ lengthBuffer.writeUInt16BE(value, 0)
2132
+ } else {
2133
+ lengthBuffer.writeUInt16BE(value.length, 0)
2134
+ }
2135
+ return lengthBuffer
2136
+ }
2137
+
2138
+ /**
2139
+ * Gets a buffer containing with the bytes (BE) representing the collection length for protocol v3 and above
2140
+ * @param {Buffer|Number} value
2141
+ * @returns {Buffer}
2142
+ * @private
2143
+ */
2144
+ function getLengthBufferV3(value) {
2145
+ if (!value) {
2146
+ return buffers.int32Zero
2147
+ }
2148
+ const lengthBuffer = utils.allocBufferUnsafe(4)
2149
+ if (typeof value === "number") {
2150
+ lengthBuffer.writeInt32BE(value, 0)
2151
+ } else {
2152
+ lengthBuffer.writeInt32BE(value.length, 0)
2153
+ }
2154
+ return lengthBuffer
2155
+ }
2156
+
2157
+ /**
2158
+ * @param {Buffer} buffer
2159
+ * @private
2160
+ */
2161
+ function handleBufferCopy(buffer) {
2162
+ if (buffer === null) {
2163
+ return null
2164
+ }
2165
+ return utils.copyBuffer(buffer)
2166
+ }
2167
+
2168
+ /**
2169
+ * @param {Buffer} buffer
2170
+ * @private
2171
+ */
2172
+ function handleBufferRef(buffer) {
2173
+ return buffer
2174
+ }
2175
+ /**
2176
+ * Decodes collection length for protocol v3 and above
2177
+ * @param bytes
2178
+ * @param offset
2179
+ * @returns {Number}
2180
+ * @private
2181
+ */
2182
+ function decodeCollectionLengthV3(bytes, offset) {
2183
+ return bytes.readInt32BE(offset)
2184
+ }
2185
+ /**
2186
+ * Decodes collection length for protocol v2 and below
2187
+ * @param bytes
2188
+ * @param offset
2189
+ * @returns {Number}
2190
+ * @private
2191
+ */
2192
+ function decodeCollectionLengthV2(bytes, offset) {
2193
+ return bytes.readUInt16BE(offset)
2194
+ }
2195
+
2196
+ function decodeDuration(bytes) {
2197
+ return types.Duration.fromBuffer(bytes)
2198
+ }
2199
+
2200
+ function encodeDuration(value) {
2201
+ if (!(value instanceof types.Duration)) {
2202
+ throw new TypeError(
2203
+ "Not a valid duration, expected Duration/Buffer obtained " +
2204
+ util.inspect(value),
2205
+ )
2206
+ }
2207
+ return value.toBuffer()
2208
+ }
2209
+
2210
+ /**
2211
+ * @private
2212
+ * @param {Buffer} buffer
2213
+ */
2214
+ // geometry and daterange types not supported in this build
2215
+ function decodeLineString() {
2216
+ throw new Error("LineString type not supported")
2217
+ }
2218
+ function encodeLineString() {
2219
+ throw new Error("LineString type not supported")
2220
+ }
2221
+ function decodePoint() {
2222
+ throw new Error("Point type not supported")
2223
+ }
2224
+ function encodePoint() {
2225
+ throw new Error("Point type not supported")
2226
+ }
2227
+ function decodePolygon() {
2228
+ throw new Error("Polygon type not supported")
2229
+ }
2230
+ function encodePolygon() {
2231
+ throw new Error("Polygon type not supported")
2232
+ }
2233
+ function decodeDateRange() {
2234
+ throw new Error("DateRange type not supported")
2235
+ }
2236
+ function encodeDateRange() {
2237
+ throw new Error("DateRange type not supported")
2238
+ }
2239
+
2240
+ /**
2241
+ * @param {String} value
2242
+ * @param {Number} startIndex
2243
+ * @param {Number} length
2244
+ * @param {String} [open]
2245
+ * @param {String} [close]
2246
+ * @returns {Array<String>}
2247
+ * @private
2248
+ */
2249
+ function parseParams(value, startIndex, length, open, close) {
2250
+ open = open || "("
2251
+ close = close || ")"
2252
+ const types = []
2253
+ let paramStart = startIndex
2254
+ let level = 0
2255
+ for (let i = startIndex; i < startIndex + length; i++) {
2256
+ const c = value[i]
2257
+ if (c === open) {
2258
+ level++
2259
+ }
2260
+ if (c === close) {
2261
+ level--
2262
+ }
2263
+ if (level === 0 && c === ",") {
2264
+ types.push(value.substr(paramStart, i - paramStart))
2265
+ paramStart = i + 1
2266
+ }
2267
+ }
2268
+ //Add the last one
2269
+ types.push(value.substr(paramStart, length - (paramStart - startIndex)))
2270
+ return types
2271
+ }
2272
+
2273
+ /**
2274
+ * @param {Array.<Buffer>} parts
2275
+ * @param {Number} totalLength
2276
+ * @returns {Buffer}
2277
+ * @private
2278
+ */
2279
+ function concatRoutingKey(parts, totalLength) {
2280
+ if (totalLength === 0) {
2281
+ return null
2282
+ }
2283
+ if (parts.length === 1) {
2284
+ return parts[0]
2285
+ }
2286
+ const routingKey = utils.allocBufferUnsafe(totalLength)
2287
+ let offset = 0
2288
+ for (let i = 0; i < parts.length; i++) {
2289
+ const item = parts[i]
2290
+ routingKey.writeUInt16BE(item.length, offset)
2291
+ offset += 2
2292
+ item.copy(routingKey, offset)
2293
+ offset += item.length
2294
+ routingKey[offset] = 0
2295
+ offset++
2296
+ }
2297
+ return routingKey
2298
+ }
2299
+
2300
+ function invertObject(obj) {
2301
+ const rv = {}
2302
+ for (const k in obj) {
2303
+ if (obj.hasOwnProperty(k)) {
2304
+ rv[obj[k]] = k
2305
+ }
2306
+ }
2307
+ return rv
2308
+ }
2309
+ Encoder.isTypedArray = function (arg) {
2310
+ // The TypedArray superclass isn't available directly so to detect an instance of a TypedArray
2311
+ // subclass we have to access the prototype of a concrete instance. There's nothing magical about
2312
+ // Uint8Array here; we could just as easily use any of the other TypedArray subclasses.
2313
+ return arg instanceof Object.getPrototypeOf(Uint8Array)
2314
+ }
2315
+
2316
+ export default Encoder