tranfi 0.1.2 → 0.2.0

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 (132) hide show
  1. package/LICENSE +177 -0
  2. package/NOTICE +8 -0
  3. package/README.md +272 -40
  4. package/app/assets/{index-pDFMluyz.js → index-BIAIKnrp.js} +1 -1
  5. package/app/index.html +1 -1
  6. package/binding.gyp +55 -3
  7. package/csrc/arena.c +7 -5
  8. package/csrc/batch.c +818 -71
  9. package/csrc/buffer.c +84 -8
  10. package/csrc/cJSON.c +262 -19
  11. package/csrc/cJSON.h +17 -1
  12. package/csrc/codec_csv.c +1074 -181
  13. package/csrc/codec_jsonl.c +830 -118
  14. package/csrc/codec_table.c +108 -78
  15. package/csrc/codec_text.c +286 -68
  16. package/csrc/compiler.c +31 -3
  17. package/csrc/config.h +21 -0
  18. package/csrc/dsl.c +4722 -485
  19. package/csrc/expr.c +363 -55
  20. package/csrc/expr.h +2 -0
  21. package/csrc/internal.h +316 -27
  22. package/csrc/ir.c +65 -18
  23. package/csrc/ir.h +41 -0
  24. package/csrc/ir_schema.c +20 -5
  25. package/csrc/ir_serialize.c +68 -6
  26. package/csrc/ir_sql.c +796 -185
  27. package/csrc/ir_validate.c +462 -6
  28. package/csrc/json_path.c +210 -0
  29. package/csrc/main.c +879 -30
  30. package/csrc/memory_estimate.c +477 -0
  31. package/csrc/op_acf.c +171 -21
  32. package/csrc/op_across.c +477 -0
  33. package/csrc/op_anomaly.c +167 -32
  34. package/csrc/op_assert.c +761 -0
  35. package/csrc/op_bin.c +168 -29
  36. package/csrc/op_cast.c +383 -55
  37. package/csrc/op_clip.c +30 -19
  38. package/csrc/op_date_trunc.c +208 -34
  39. package/csrc/op_datetime.c +259 -77
  40. package/csrc/op_derive.c +65 -97
  41. package/csrc/op_diff.c +146 -30
  42. package/csrc/op_ewma.c +149 -30
  43. package/csrc/op_explode.c +124 -26
  44. package/csrc/op_fill_down.c +125 -53
  45. package/csrc/op_fill_null.c +176 -31
  46. package/csrc/op_filter.c +89 -40
  47. package/csrc/op_frequency.c +571 -43
  48. package/csrc/op_grep.c +36 -18
  49. package/csrc/op_group_agg.c +1790 -119
  50. package/csrc/op_hash.c +48 -15
  51. package/csrc/op_head.c +21 -86
  52. package/csrc/op_interpolate.c +268 -62
  53. package/csrc/op_join.c +2700 -182
  54. package/csrc/op_json_extract.c +227 -0
  55. package/csrc/op_json_filter.c +384 -0
  56. package/csrc/op_json_flatten.c +293 -0
  57. package/csrc/op_json_schema.c +503 -0
  58. package/csrc/op_label_encode.c +328 -53
  59. package/csrc/op_lag.c +181 -0
  60. package/csrc/op_lead.c +141 -89
  61. package/csrc/op_normalize.c +363 -79
  62. package/csrc/op_onehot.c +345 -73
  63. package/csrc/op_pivot.c +1546 -162
  64. package/csrc/op_quarantine.c +189 -0
  65. package/csrc/op_registry.c +2062 -166
  66. package/csrc/op_rename.c +41 -50
  67. package/csrc/op_replace.c +270 -118
  68. package/csrc/op_rleid.c +297 -0
  69. package/csrc/op_rowid.c +559 -0
  70. package/csrc/op_sample.c +80 -23
  71. package/csrc/op_schema.c +1341 -0
  72. package/csrc/op_schema_infer.c +252 -0
  73. package/csrc/op_select.c +265 -65
  74. package/csrc/op_set.c +3449 -0
  75. package/csrc/op_skip.c +30 -87
  76. package/csrc/op_sort.c +670 -124
  77. package/csrc/op_source_name.c +120 -0
  78. package/csrc/op_split.c +65 -28
  79. package/csrc/op_split_data.c +41 -9
  80. package/csrc/op_stack.c +178 -222
  81. package/csrc/op_stats.c +206 -110
  82. package/csrc/op_step.c +217 -55
  83. package/csrc/op_tail.c +21 -12
  84. package/csrc/op_tee.c +338 -0
  85. package/csrc/op_top.c +260 -53
  86. package/csrc/op_trim.c +48 -19
  87. package/csrc/op_unique.c +1193 -150
  88. package/csrc/op_unpivot.c +100 -66
  89. package/csrc/op_validate.c +601 -24
  90. package/csrc/op_window.c +492 -51
  91. package/csrc/path_policy.c +85 -0
  92. package/csrc/pipeline.c +872 -99
  93. package/csrc/recipes.c +3 -1
  94. package/csrc/report.c +73 -30
  95. package/csrc/selector.c +1097 -0
  96. package/csrc/size_utils.c +348 -0
  97. package/csrc/spill.c +317 -0
  98. package/csrc/spill.h +21 -0
  99. package/csrc/tranfi.h +169 -1
  100. package/csrc/transform.h +209 -0
  101. package/csrc/transform_api.c +2237 -0
  102. package/csrc/transform_categorical.c +923 -0
  103. package/csrc/transform_internal.h +472 -0
  104. package/csrc/transform_json.c +3812 -0
  105. package/csrc/transform_numeric.c +1966 -0
  106. package/csrc/transform_sha256.c +154 -0
  107. package/csrc/transform_wasm.h +162 -0
  108. package/csrc/transform_wasm_api.c +1373 -0
  109. package/csrc/wasm_api.c +70 -9
  110. package/napi_api.c +219 -11
  111. package/napi_transform.c +1648 -0
  112. package/napi_transform.h +8 -0
  113. package/package.json +27 -11
  114. package/scripts/install-native.js +76 -0
  115. package/scripts/prepack.js +64 -0
  116. package/scripts/sync-csrc.js +23 -0
  117. package/src/cli.js +8 -11
  118. package/src/engines/duckdb.js +45 -12
  119. package/src/index.js +661 -42
  120. package/src/memory_policy.js +411 -0
  121. package/src/native.js +1 -5
  122. package/src/pipeline.js +454 -31
  123. package/src/recipe_json.js +80 -0
  124. package/src/server.js +10 -8
  125. package/src/transform.js +403 -0
  126. package/src/transform_error.js +10 -0
  127. package/src/wasm.js +6 -4
  128. package/wasm/index.js +498 -10
  129. package/wasm/tranfi_core.js +0 -0
  130. package/wasm/transform.js +1156 -0
  131. package/wasm/worker.js +786 -0
  132. package/csrc/plan.c +0 -206
@@ -0,0 +1,1156 @@
1
+ 'use strict'
2
+
3
+ const { stringifyRecipe } = require('../src/recipe_json.js')
4
+
5
+ const { TranfiTransformError } = require('../src/transform_error.js')
6
+
7
+ const VIEW_FLOAT32 = 0x0101
8
+ const VIEW_FLOAT64 = 0x0102
9
+ const SCHEMA_INPUT = 1
10
+ const SCHEMA_OUTPUT = 2
11
+ const NO_HOST_CANCEL = 0xffffffff
12
+
13
+ const LIMIT_FIELDS = [
14
+ 'maxRecipeBytes',
15
+ 'maxPlanBytes',
16
+ 'maxJsonDepth',
17
+ 'maxObjectKeys',
18
+ 'maxSteps',
19
+ 'maxInputColumns',
20
+ 'maxOutputColumns',
21
+ 'maxCategoriesPerColumn',
22
+ 'maxTotalCategories',
23
+ 'maxStringBytes',
24
+ 'maxDecodedStringBytes',
25
+ 'maxAnalyzerRows',
26
+ 'maxAnalyzerInputBytes',
27
+ 'maxResidentStateBytes',
28
+ 'maxSpillBytes',
29
+ 'maxApplyRows',
30
+ 'maxApplyInputBytes',
31
+ 'maxOutputElementsPerCall',
32
+ 'maxAllocationBytes',
33
+ 'maxAllocationsPerSession',
34
+ 'maxLiveHandles',
35
+ 'maxRetiredHandleSlots'
36
+ ]
37
+ const LIMIT_FIELD_SET = new Set(LIMIT_FIELDS)
38
+
39
+ const ERROR_NAMES = {
40
+ 100: 'invalid prepared-transform argument',
41
+ 101: 'invalid prepared-transform recipe',
42
+ 102: 'prepared-transform schema mismatch',
43
+ 103: 'insufficient data to finalize prepared transform',
44
+ 104: 'prepared-transform resource limit exceeded',
45
+ 105: 'unsupported prepared-transform version',
46
+ 106: 'corrupt prepared-transform plan',
47
+ 107: 'prepared-transform numeric domain error',
48
+ 108: 'unknown prepared-transform category',
49
+ 109: 'prepared transform cancelled',
50
+ 110: 'prepared-transform allocation failed',
51
+ 111: 'prepared-transform I/O failed',
52
+ 112: 'prepared-transform object is closed or terminal',
53
+ 113: 'unsupported prepared-transform runtime',
54
+ 199: 'internal prepared-transform error'
55
+ }
56
+
57
+ function createTransformAPI(wasm) {
58
+ var encoder = new TextEncoder()
59
+ var decoder = new TextDecoder()
60
+ var cancelPolls = new Map()
61
+ var nextCancelSlot = 1
62
+ var safeLimitProfile = null
63
+
64
+ wasm.tfTransformCancelPoll = function(slot) {
65
+ var poll = cancelPolls.get(slot >>> 0)
66
+ if (!poll) return false
67
+ if (poll.observer) {
68
+ var observer = poll.observer
69
+ poll.observer = null
70
+ observer()
71
+ }
72
+ return Atomics.load(poll.flag, 0) !== 0
73
+ }
74
+
75
+ function dataView() {
76
+ return new DataView(wasm.HEAPU8.buffer)
77
+ }
78
+
79
+ function readU32(offset) {
80
+ return dataView().getUint32(offset, true)
81
+ }
82
+
83
+ function writeU32(offset, value) {
84
+ dataView().setUint32(offset, value >>> 0, true)
85
+ }
86
+
87
+ function readU64(offset) {
88
+ var value = dataView().getBigUint64(offset, true)
89
+ if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
90
+ throw new RangeError('transform limit exceeds JavaScript safe integer range')
91
+ }
92
+ return Number(value)
93
+ }
94
+
95
+ function writeU64(offset, value) {
96
+ dataView().setBigUint64(offset, BigInt(value), true)
97
+ }
98
+
99
+ function alloc(size, alignment) {
100
+ alignment = alignment || 1
101
+ if (!Number.isSafeInteger(size) || size < 0
102
+ || !Number.isSafeInteger(alignment) || alignment <= 0
103
+ || size > 0xffffffff - alignment + 1) {
104
+ throw resourceLimit('WASM transport allocation exceeds wasm32')
105
+ }
106
+ var actualSize = Math.max(1, size + alignment - 1)
107
+ var base = wasm._malloc(actualSize) >>> 0
108
+ if (!base) throw new TranfiTransformError(110, 'WASM allocation failed')
109
+ var pointer = Math.ceil(base / alignment) * alignment
110
+ return { base: base >>> 0, pointer: pointer >>> 0, size: size >>> 0 }
111
+ }
112
+
113
+ function free(owner) {
114
+ if (owner && owner.base) wasm._free(owner.base)
115
+ }
116
+
117
+ function allocBytes(bytes, alignment, cancelToken) {
118
+ throwIfCancelled(cancelToken)
119
+ var owner = alloc(bytes.byteLength, alignment || 1)
120
+ try {
121
+ for (var offset = 0; offset < bytes.byteLength; offset += 65536) {
122
+ throwIfCancelled(cancelToken)
123
+ var end = Math.min(offset + 65536, bytes.byteLength)
124
+ wasm.HEAPU8.set(bytes.subarray(offset, end), owner.pointer + offset)
125
+ }
126
+ throwIfCancelled(cancelToken)
127
+ return owner
128
+ } catch (error) {
129
+ free(owner)
130
+ throw error
131
+ }
132
+ }
133
+
134
+ function allocWord() {
135
+ var owner = alloc(4, 4)
136
+ writeU32(owner.pointer, 0)
137
+ return owner
138
+ }
139
+
140
+ function raw(name, args) {
141
+ var types = new Array(args.length).fill('number')
142
+ return wasm.ccall(name, 'number', types, args) >>> 0
143
+ }
144
+
145
+ function destroyHandle(handle) {
146
+ return raw('tf_wasm_transform_handle_destroy', [handle >>> 0])
147
+ }
148
+
149
+ function errorFromHandle(code, handle) {
150
+ var message = ERROR_NAMES[code] || ('prepared transform failed with code ' + code)
151
+ handle = handle >>> 0
152
+ if (!handle) return new TranfiTransformError(code, message)
153
+ var sizeOwner = null
154
+ var messageOwner = null
155
+ try {
156
+ sizeOwner = allocWord()
157
+ if (raw('tf_wasm_transform_error_message_size', [handle, sizeOwner.pointer]) === 0) {
158
+ var length = readU32(sizeOwner.pointer)
159
+ messageOwner = alloc(length, 1)
160
+ if (raw('tf_wasm_transform_error_message_copy', [
161
+ handle, messageOwner.pointer, length
162
+ ]) === 0) {
163
+ message = decoder.decode(wasm.HEAPU8.slice(
164
+ messageOwner.pointer, messageOwner.pointer + length
165
+ ))
166
+ }
167
+ }
168
+ } finally {
169
+ free(messageOwner)
170
+ free(sizeOwner)
171
+ destroyHandle(handle)
172
+ }
173
+ return new TranfiTransformError(code, message)
174
+ }
175
+
176
+ function callWithError(name, args) {
177
+ var errorOwner = allocWord()
178
+ try {
179
+ var code = raw(name, args.concat([errorOwner.pointer]))
180
+ if (code !== 0) throw errorFromHandle(code, readU32(errorOwner.pointer))
181
+ } finally {
182
+ free(errorOwner)
183
+ }
184
+ }
185
+
186
+ function callForHandle(name, args) {
187
+ var outputOwner = allocWord()
188
+ var errorOwner = null
189
+ try {
190
+ errorOwner = allocWord()
191
+ var code = raw(name, args.concat([outputOwner.pointer, errorOwner.pointer]))
192
+ if (code !== 0) throw errorFromHandle(code, readU32(errorOwner.pointer))
193
+ return readU32(outputOwner.pointer) >>> 0
194
+ } finally {
195
+ free(errorOwner)
196
+ free(outputOwner)
197
+ }
198
+ }
199
+
200
+ function normalizeLimits(limits) {
201
+ if (limits === undefined || limits === null) return null
202
+ if (!limits || typeof limits !== 'object' || Array.isArray(limits)) {
203
+ throw new TypeError('limits must be an object')
204
+ }
205
+ var normalized = {}
206
+ Object.keys(limits).forEach(function(name) {
207
+ if (!LIMIT_FIELD_SET.has(name)) {
208
+ throw new TypeError('unknown transform limit field: ' + name)
209
+ }
210
+ var value = limits[name]
211
+ if (!Number.isSafeInteger(value) || value <= 0) {
212
+ throw new TranfiTransformError(
213
+ 100, name + ' must be a positive safe integer'
214
+ )
215
+ }
216
+ normalized[name] = value
217
+ })
218
+ return normalized
219
+ }
220
+
221
+ function safeTransformLimits(overrides) {
222
+ var normalized = normalizeLimits(overrides || {}) || {}
223
+ if (safeLimitProfile === null) {
224
+ var owner = alloc(184, 8)
225
+ try {
226
+ var code = raw('tf_wasm_transform_limits_init_safe_v1', [owner.pointer, 184])
227
+ if (code !== 0) throw new TranfiTransformError(code, ERROR_NAMES[code])
228
+ safeLimitProfile = {}
229
+ for (var i = 0; i < LIMIT_FIELDS.length; i++) {
230
+ safeLimitProfile[LIMIT_FIELDS[i]] = readU64(owner.pointer + 8 + i * 8)
231
+ }
232
+ } finally {
233
+ free(owner)
234
+ }
235
+ }
236
+ return Object.assign({}, safeLimitProfile, normalized)
237
+ }
238
+
239
+ function limitsOwner(limits, resolved) {
240
+ var normalized = normalizeLimits(limits)
241
+ if (normalized === null) return null
242
+ var values = resolved || safeTransformLimits(normalized)
243
+ var owner = alloc(184, 8)
244
+ try {
245
+ var code = raw('tf_wasm_transform_limits_init_safe_v1', [owner.pointer, 184])
246
+ if (code !== 0) throw new TranfiTransformError(code, ERROR_NAMES[code])
247
+ for (var i = 0; i < LIMIT_FIELDS.length; i++) {
248
+ writeU64(owner.pointer + 8 + i * 8, values[LIMIT_FIELDS[i]])
249
+ }
250
+ return owner
251
+ } catch (error) {
252
+ free(owner)
253
+ throw error
254
+ }
255
+ }
256
+
257
+ function resourceLimit(message) {
258
+ return new TranfiTransformError(104, message)
259
+ }
260
+
261
+ function resolvedLimits(limits) {
262
+ return safeTransformLimits(limits || {})
263
+ }
264
+
265
+ function assertWellFormedUnicode(value, label, cancelToken, rejectNul) {
266
+ for (var index = 0; index < value.length; index++) {
267
+ if (index % 4096 === 0) throwIfCancelled(cancelToken)
268
+ var unit = value.charCodeAt(index)
269
+ if (rejectNul && unit === 0) {
270
+ throw new TypeError(label + ' must not contain NUL')
271
+ }
272
+ if (unit >= 0xd800 && unit <= 0xdbff) {
273
+ var next = index + 1 < value.length ? value.charCodeAt(index + 1) : 0
274
+ if (next < 0xdc00 || next > 0xdfff) {
275
+ throw new TypeError(label + ' must not contain an unpaired UTF-16 surrogate')
276
+ }
277
+ index++
278
+ } else if (unit >= 0xdc00 && unit <= 0xdfff) {
279
+ throw new TypeError(label + ' must not contain an unpaired UTF-16 surrogate')
280
+ }
281
+ }
282
+ throwIfCancelled(cancelToken)
283
+ return value
284
+ }
285
+
286
+ function utf8ByteLength(value, label, cancelToken, rejectNul, maxBytes) {
287
+ var bytes = 0
288
+ for (var index = 0; index < value.length; index++) {
289
+ if (index % 4096 === 0) throwIfCancelled(cancelToken)
290
+ var unit = value.charCodeAt(index)
291
+ if (rejectNul && unit === 0) {
292
+ throw new TypeError(label + ' must not contain NUL')
293
+ }
294
+ if (unit <= 0x7f) {
295
+ bytes += 1
296
+ } else if (unit <= 0x7ff) {
297
+ bytes += 2
298
+ } else if (unit >= 0xd800 && unit <= 0xdbff) {
299
+ var next = index + 1 < value.length ? value.charCodeAt(index + 1) : 0
300
+ if (next < 0xdc00 || next > 0xdfff) {
301
+ throw new TypeError(label + ' must not contain an unpaired UTF-16 surrogate')
302
+ }
303
+ bytes += 4
304
+ index++
305
+ } else if (unit >= 0xdc00 && unit <= 0xdfff) {
306
+ throw new TypeError(label + ' must not contain an unpaired UTF-16 surrogate')
307
+ } else {
308
+ bytes += 3
309
+ }
310
+ if (maxBytes !== undefined && bytes > maxBytes) {
311
+ throw resourceLimit(label + ' exceeds its configured byte limit')
312
+ }
313
+ }
314
+ throwIfCancelled(cancelToken)
315
+ return bytes
316
+ }
317
+
318
+ function encodeUtf8(value, label, cancelToken, maxBytes, knownLength) {
319
+ var total = knownLength === undefined
320
+ ? utf8ByteLength(value, label, cancelToken, true, maxBytes)
321
+ : knownLength
322
+ var encoded = new Uint8Array(total)
323
+ var destination = 0
324
+ for (var offset = 0; offset < value.length;) {
325
+ throwIfCancelled(cancelToken)
326
+ var end = Math.min(offset + 4096, value.length)
327
+ if (end < value.length) {
328
+ var last = value.charCodeAt(end - 1)
329
+ if (last >= 0xd800 && last <= 0xdbff) end--
330
+ }
331
+ var chunk = value.slice(offset, end)
332
+ var result = encoder.encodeInto(chunk, encoded.subarray(destination))
333
+ if (result.read !== chunk.length) {
334
+ throw new Error('internal UTF-8 destination mismatch for ' + label)
335
+ }
336
+ destination += result.written
337
+ offset = end
338
+ }
339
+ throwIfCancelled(cancelToken)
340
+ if (destination !== total) {
341
+ throw new Error('internal UTF-8 length mismatch for ' + label)
342
+ }
343
+ return encoded
344
+ }
345
+
346
+ function normalizeSchema(schema, limits, cancelToken) {
347
+ var fields = Array.isArray(schema)
348
+ ? schema
349
+ : schema && typeof schema === 'object' && Array.isArray(schema.fields)
350
+ ? schema.fields
351
+ : null
352
+ if (!fields || fields.length === 0) {
353
+ throw new TypeError('schema must be a nonempty array or { fields } object')
354
+ }
355
+ if (fields.length > limits.maxInputColumns) {
356
+ throw resourceLimit('prepared-transform input column limit exceeded')
357
+ }
358
+ var normalized = []
359
+ fields.forEach(function(field, index) {
360
+ if (index % 4096 === 0) throwIfCancelled(cancelToken)
361
+ if (!field || typeof field !== 'object' || Array.isArray(field)) {
362
+ throw new TypeError('schema field ' + index + ' must be an object')
363
+ }
364
+ var id = field.id
365
+ var name = field.name === undefined ? id : field.name
366
+ if (typeof id !== 'string' || !id) {
367
+ throw new TypeError('schema field ' + index + ' id must be a nonempty string')
368
+ }
369
+ if (typeof name !== 'string' || !name) {
370
+ throw new TypeError('schema field ' + index + ' name must be a nonempty string')
371
+ }
372
+ assertWellFormedUnicode(
373
+ id, 'schema field ' + index + ' id', cancelToken, true
374
+ )
375
+ assertWellFormedUnicode(
376
+ name, 'schema field ' + index + ' name', cancelToken, true
377
+ )
378
+ if (field.dtype !== 'float32' && field.dtype !== 'float64') {
379
+ throw new TypeError('schema field ' + index + ' dtype must be float32 or float64')
380
+ }
381
+ normalized.push({ id: id, name: name, dtype: field.dtype })
382
+ })
383
+ throwIfCancelled(cancelToken)
384
+ return normalized
385
+ }
386
+
387
+ function schemaOwner(schema, limits, cancelToken) {
388
+ var fields = normalizeSchema(schema, limits, cancelToken)
389
+ var descriptorBytes = fields.length * 32
390
+ if (descriptorBytes > limits.maxAllocationBytes) {
391
+ throw resourceLimit('prepared-transform schema allocation limit exceeded')
392
+ }
393
+ var decodedBytes = 0
394
+ var preparedFields = fields.map(function(field, index) {
395
+ if (index % 4096 === 0) throwIfCancelled(cancelToken)
396
+ var maxEncodedBytes = Math.min(
397
+ limits.maxStringBytes, limits.maxAllocationBytes - 1
398
+ )
399
+ var idLength = utf8ByteLength(
400
+ field.id, 'schema field ' + index + ' id', cancelToken, true,
401
+ maxEncodedBytes
402
+ )
403
+ var nameLength = utf8ByteLength(
404
+ field.name, 'schema field ' + index + ' name', cancelToken, true,
405
+ maxEncodedBytes
406
+ )
407
+ if (decodedBytes + idLength + nameLength > limits.maxDecodedStringBytes) {
408
+ throw resourceLimit('prepared-transform decoded string limit exceeded')
409
+ }
410
+ decodedBytes += idLength + nameLength
411
+ return { field: field, idLength: idLength, nameLength: nameLength }
412
+ })
413
+ throwIfCancelled(cancelToken)
414
+ var encodedFields = preparedFields.map(function(prepared, index) {
415
+ if (index % 4096 === 0) throwIfCancelled(cancelToken)
416
+ var field = prepared.field
417
+ var maxEncodedBytes = Math.min(
418
+ limits.maxStringBytes, limits.maxAllocationBytes - 1
419
+ )
420
+ return {
421
+ field: field,
422
+ id: encodeUtf8(
423
+ field.id, 'schema field ' + index + ' id', cancelToken,
424
+ maxEncodedBytes, prepared.idLength
425
+ ),
426
+ name: encodeUtf8(
427
+ field.name, 'schema field ' + index + ' name', cancelToken,
428
+ maxEncodedBytes, prepared.nameLength
429
+ )
430
+ }
431
+ })
432
+ var allocations = []
433
+ var dtypes = []
434
+ var fieldOwner = null
435
+ var schemaAllocation = null
436
+ try {
437
+ fieldOwner = alloc(descriptorBytes, 4)
438
+ allocations.push(fieldOwner)
439
+ schemaAllocation = alloc(20, 4)
440
+ allocations.push(schemaAllocation)
441
+ encodedFields.forEach(function(encoded, index) {
442
+ if (index % 4096 === 0) throwIfCancelled(cancelToken)
443
+ var field = encoded.field
444
+ var idOwner = allocBytes(encoded.id, 1, cancelToken)
445
+ allocations.push(idOwner)
446
+ var nameOwner = allocBytes(encoded.name, 1, cancelToken)
447
+ allocations.push(nameOwner)
448
+ var offset = fieldOwner.pointer + index * 32
449
+ writeU32(offset, 1)
450
+ writeU32(offset + 4, 32)
451
+ writeU32(offset + 8, field.dtype === 'float32' ? VIEW_FLOAT32 : VIEW_FLOAT64)
452
+ writeU32(offset + 12, 0)
453
+ writeU32(offset + 16, idOwner.pointer)
454
+ writeU32(offset + 20, idOwner.size)
455
+ writeU32(offset + 24, nameOwner.pointer)
456
+ writeU32(offset + 28, nameOwner.size)
457
+ dtypes.push(field.dtype)
458
+ })
459
+ writeU32(schemaAllocation.pointer, 1)
460
+ writeU32(schemaAllocation.pointer + 4, 20)
461
+ writeU32(schemaAllocation.pointer + 8, fields.length)
462
+ writeU32(schemaAllocation.pointer + 12, fieldOwner.pointer)
463
+ writeU32(schemaAllocation.pointer + 16, descriptorBytes)
464
+ return {
465
+ pointer: schemaAllocation.pointer,
466
+ dtypes: dtypes,
467
+ free: function() { allocations.reverse().forEach(free) }
468
+ }
469
+ } catch (error) {
470
+ allocations.reverse().forEach(free)
471
+ throw error
472
+ }
473
+ }
474
+
475
+ function tableOwner(table, dtypes, limits, phase, cancelToken) {
476
+ throwIfCancelled(cancelToken)
477
+ if (!table || typeof table !== 'object' || Array.isArray(table)) {
478
+ throw new TypeError('table must be an object with rows and columns')
479
+ }
480
+ var rows = table.rows
481
+ var columns = table.columns
482
+ if (!Number.isInteger(rows) || rows < 0 || rows > 0xffffffff) {
483
+ throw new TypeError('table.rows must be a nonnegative uint32 integer')
484
+ }
485
+ if (!Array.isArray(columns) || columns.length !== dtypes.length) {
486
+ throw new TypeError('table column count does not match the prepared schema')
487
+ }
488
+ var maxRows = phase === 'analyze'
489
+ ? limits.maxAnalyzerRows
490
+ : limits.maxApplyRows
491
+ var maxInputBytes = phase === 'analyze'
492
+ ? limits.maxAnalyzerInputBytes
493
+ : limits.maxApplyInputBytes
494
+ if (rows > maxRows) {
495
+ throw resourceLimit('prepared-transform row limit exceeded')
496
+ }
497
+ var descriptorBytes = columns.length * 36
498
+ if (descriptorBytes > limits.maxAllocationBytes) {
499
+ throw resourceLimit('prepared-transform table allocation limit exceeded')
500
+ }
501
+ var totalInputBytes = 0n
502
+ var prepared = columns.map(function(value, index) {
503
+ if (index % 4096 === 0) throwIfCancelled(cancelToken)
504
+ var config = ArrayBuffer.isView(value) ? { data: value } : value
505
+ if (!config || typeof config !== 'object' || !ArrayBuffer.isView(config.data)) {
506
+ throw new TypeError('table column ' + index + ' data must be a typed array')
507
+ }
508
+ var expected = dtypes[index]
509
+ var ArrayType = expected === 'float32' ? Float32Array : Float64Array
510
+ if (!(config.data instanceof ArrayType)) {
511
+ throw new TypeError('table column ' + index + ' dtype mismatches schema')
512
+ }
513
+ if (rows === 0 && (config.data.byteLength !== 0
514
+ || config.validity !== undefined && config.validity !== null
515
+ || config.validityBitOffset !== undefined
516
+ || config.validityBitStride !== undefined)) {
517
+ throw new TranfiTransformError(
518
+ 100, 'zero-row column must carry empty data and no validity span'
519
+ )
520
+ }
521
+ var itemSize = expected === 'float32' ? 4 : 8
522
+ var stride = config.strideBytes === undefined ? itemSize : config.strideBytes
523
+ if (!Number.isInteger(stride) || stride <= 0 || stride > 0xffffffff) {
524
+ throw new TypeError('table column ' + index + ' strideBytes must be positive')
525
+ }
526
+ var requiredData = rows === 0
527
+ ? 0n
528
+ : BigInt(rows - 1) * BigInt(stride) + BigInt(itemSize)
529
+ if (requiredData > BigInt(config.data.byteLength)) {
530
+ throw new TypeError('table column ' + index + ' data buffer is too small')
531
+ }
532
+ if (requiredData > 0xffffffffn
533
+ || requiredData > BigInt(limits.maxAllocationBytes)) {
534
+ throw resourceLimit('prepared-transform input allocation limit exceeded')
535
+ }
536
+
537
+ var bitOffset = 0
538
+ var bitStride = 0
539
+ var requiredValidity = 0n
540
+ if (config.validity !== undefined && config.validity !== null) {
541
+ if (!(config.validity instanceof Uint8Array)) {
542
+ throw new TypeError('table column ' + index + ' validity must be Uint8Array')
543
+ }
544
+ bitOffset = config.validityBitOffset === undefined ? 0 : config.validityBitOffset
545
+ bitStride = config.validityBitStride === undefined ? 1 : config.validityBitStride
546
+ if (!Number.isInteger(bitOffset) || bitOffset < 0 || bitOffset > 0xffffffff
547
+ || !Number.isInteger(bitStride) || bitStride <= 0 || bitStride > 0xffffffff) {
548
+ throw new TypeError('table column ' + index + ' validity bit metadata is invalid')
549
+ }
550
+ var requiredBits = rows === 0
551
+ ? 0n
552
+ : BigInt(bitOffset) + BigInt(rows - 1) * BigInt(bitStride) + 1n
553
+ requiredValidity = (requiredBits + 7n) / 8n
554
+ if (requiredValidity > BigInt(config.validity.byteLength)) {
555
+ throw new TypeError('table column ' + index + ' validity buffer is too small')
556
+ }
557
+ if (requiredValidity > 0xffffffffn
558
+ || requiredValidity > BigInt(limits.maxAllocationBytes)) {
559
+ throw resourceLimit('prepared-transform validity allocation limit exceeded')
560
+ }
561
+ } else if (config.validityBitOffset !== undefined
562
+ || config.validityBitStride !== undefined) {
563
+ throw new TypeError('validity bit metadata requires a validity bitmap')
564
+ }
565
+ totalInputBytes += requiredData + requiredValidity
566
+ if (totalInputBytes > BigInt(maxInputBytes)) {
567
+ throw resourceLimit('prepared-transform input byte limit exceeded')
568
+ }
569
+ return {
570
+ config: config,
571
+ itemSize: itemSize,
572
+ stride: stride,
573
+ dataBytes: Number(requiredData),
574
+ validityBytes: Number(requiredValidity),
575
+ bitOffset: bitOffset,
576
+ bitStride: bitStride
577
+ }
578
+ })
579
+ var allocations = []
580
+ var columnsOwner = null
581
+ var tableAllocation = null
582
+ try {
583
+ columnsOwner = alloc(descriptorBytes, 4)
584
+ allocations.push(columnsOwner)
585
+ tableAllocation = alloc(24, 4)
586
+ allocations.push(tableAllocation)
587
+ prepared.forEach(function(input, index) {
588
+ if (index % 4096 === 0) throwIfCancelled(cancelToken)
589
+ var config = input.config
590
+ var bytes = new Uint8Array(
591
+ config.data.buffer, config.data.byteOffset, input.dataBytes
592
+ )
593
+ var dataOwner = bytes.byteLength
594
+ ? allocBytes(bytes, input.itemSize, cancelToken) : null
595
+ if (dataOwner) allocations.push(dataOwner)
596
+ var validityOwner = null
597
+ if (input.validityBytes) {
598
+ validityOwner = input.validityBytes
599
+ ? allocBytes(new Uint8Array(
600
+ config.validity.buffer,
601
+ config.validity.byteOffset,
602
+ input.validityBytes
603
+ ), 1, cancelToken)
604
+ : null
605
+ if (validityOwner) allocations.push(validityOwner)
606
+ }
607
+ var offset = columnsOwner.pointer + index * 36
608
+ writeU32(offset, 1)
609
+ writeU32(offset + 4, 36)
610
+ writeU32(offset + 8, dataOwner ? dataOwner.pointer : 0)
611
+ writeU32(offset + 12, input.dataBytes)
612
+ writeU32(offset + 16, input.stride)
613
+ writeU32(offset + 20, validityOwner ? validityOwner.pointer : 0)
614
+ writeU32(offset + 24, input.validityBytes)
615
+ writeU32(offset + 28, input.bitOffset)
616
+ writeU32(offset + 32, input.bitStride)
617
+ })
618
+ writeU32(tableAllocation.pointer, 1)
619
+ writeU32(tableAllocation.pointer + 4, 24)
620
+ writeU32(tableAllocation.pointer + 8, rows)
621
+ writeU32(tableAllocation.pointer + 12, columns.length)
622
+ writeU32(tableAllocation.pointer + 16, columnsOwner.pointer)
623
+ writeU32(tableAllocation.pointer + 20, descriptorBytes)
624
+ return {
625
+ pointer: tableAllocation.pointer,
626
+ free: function() { allocations.reverse().forEach(free) }
627
+ }
628
+ } catch (error) {
629
+ allocations.reverse().forEach(free)
630
+ throw error
631
+ }
632
+ }
633
+
634
+ function bytesFromHandle(handle) {
635
+ var sizeOwner = null
636
+ var dataOwner = null
637
+ try {
638
+ sizeOwner = allocWord()
639
+ var code = raw('tf_wasm_transform_owned_bytes_size', [handle, sizeOwner.pointer])
640
+ if (code !== 0) throw new TranfiTransformError(code, ERROR_NAMES[code])
641
+ var length = readU32(sizeOwner.pointer)
642
+ dataOwner = alloc(length, 1)
643
+ code = raw('tf_wasm_transform_owned_bytes_copy', [
644
+ handle, dataOwner.pointer, length
645
+ ])
646
+ if (code !== 0) throw new TranfiTransformError(code, ERROR_NAMES[code])
647
+ return wasm.HEAPU8.slice(dataOwner.pointer, dataOwner.pointer + length)
648
+ } finally {
649
+ free(dataOwner)
650
+ free(sizeOwner)
651
+ destroyHandle(handle)
652
+ }
653
+ }
654
+
655
+ function denseFromHandle(handle, cancelToken) {
656
+ var infoOwner = null
657
+ var dataOwner = null
658
+ try {
659
+ infoOwner = alloc(28, 4)
660
+ var code = raw('tf_wasm_transform_owned_dense_info', [handle, infoOwner.pointer])
661
+ if (code !== 0) throw new TranfiTransformError(code, ERROR_NAMES[code])
662
+ var dtype = readU32(infoOwner.pointer + 8)
663
+ var rows = readU32(infoOwner.pointer + 16)
664
+ var columns = readU32(infoOwner.pointer + 20)
665
+ var byteLength = readU32(infoOwner.pointer + 24)
666
+ if (dtype !== VIEW_FLOAT64 || byteLength % 8 !== 0
667
+ || BigInt(rows) * BigInt(columns) * 8n !== BigInt(byteLength)) {
668
+ throw new TranfiTransformError(199, 'invalid dense output from WASM')
669
+ }
670
+ throwIfCancelled(cancelToken)
671
+ dataOwner = alloc(byteLength, 8)
672
+ code = raw('tf_wasm_transform_owned_dense_copy', [
673
+ handle, dataOwner.pointer, byteLength
674
+ ])
675
+ if (code !== 0) throw new TranfiTransformError(code, ERROR_NAMES[code])
676
+ throwIfCancelled(cancelToken)
677
+ var result = new Float64Array(byteLength / 8)
678
+ var view = dataView()
679
+ for (var i = 0; i < result.length; i++) {
680
+ if (i % 8192 === 0) throwIfCancelled(cancelToken)
681
+ result[i] = view.getFloat64(dataOwner.pointer + i * 8, true)
682
+ }
683
+ throwIfCancelled(cancelToken)
684
+ return { rows: rows, columns: columns, data: result }
685
+ } finally {
686
+ free(dataOwner)
687
+ free(infoOwner)
688
+ destroyHandle(handle)
689
+ }
690
+ }
691
+
692
+ function normalizeRecipeJSON(recipe, limits) {
693
+ if (typeof recipe === 'string') {
694
+ var stringLimit = Math.min(
695
+ limits.maxRecipeBytes, limits.maxAllocationBytes - 1
696
+ )
697
+ var stringLength = utf8ByteLength(
698
+ recipe, 'recipe', null, false, stringLimit
699
+ )
700
+ return encodeUtf8(recipe, 'recipe', null, stringLimit, stringLength)
701
+ }
702
+ if (recipe instanceof Uint8Array) {
703
+ if (recipe.byteLength > limits.maxRecipeBytes
704
+ || recipe.byteLength > limits.maxAllocationBytes) {
705
+ throw resourceLimit('prepared-transform recipe byte limit exceeded')
706
+ }
707
+ return new Uint8Array(recipe.buffer, recipe.byteOffset, recipe.byteLength)
708
+ }
709
+ if (!recipe || typeof recipe !== 'object' || Array.isArray(recipe)) {
710
+ throw new TypeError('recipe must be an object, string, or Uint8Array')
711
+ }
712
+ var text = stringifyRecipe(recipe, limits)
713
+ var textLimit = Math.min(
714
+ limits.maxRecipeBytes, limits.maxAllocationBytes - 1
715
+ )
716
+ var textLength = utf8ByteLength(
717
+ text, 'recipe', null, false, textLimit
718
+ )
719
+ return encodeUtf8(text, 'recipe', null, textLimit, textLength)
720
+ }
721
+
722
+ function runtimeOptions(options) {
723
+ if (options === undefined) options = {}
724
+ if (typeof options !== 'object' || Array.isArray(options)) {
725
+ throw new TypeError('transform runtime options must be an object')
726
+ }
727
+ Object.keys(options).forEach(function(name) {
728
+ if (['limits', 'cancelToken', 'hostPolicy', 'spillDir'].indexOf(name) < 0) {
729
+ throw new TypeError('unknown transform runtime option: ' + name)
730
+ }
731
+ })
732
+ if (options.hostPolicy !== undefined && options.hostPolicy !== null) {
733
+ throw new TranfiTransformError(
734
+ 113, 'prepared-transform hostPolicy is reserved but not implemented'
735
+ )
736
+ }
737
+ if (options.spillDir !== undefined && options.spillDir !== null
738
+ && options.spillDir !== '') {
739
+ throw new TranfiTransformError(
740
+ 113, 'prepared-transform spillDir is reserved but not implemented'
741
+ )
742
+ }
743
+ return {
744
+ limits: options.limits,
745
+ cancelToken: options.cancelToken || null
746
+ }
747
+ }
748
+
749
+ function throwIfCancelled(token) {
750
+ if (token && token._isRequested()) {
751
+ throw new TranfiTransformError(109, ERROR_NAMES[109])
752
+ }
753
+ }
754
+
755
+ function tokenHandle(token) {
756
+ if (token === null) return 0
757
+ if (!(token instanceof TransformCancelToken)) {
758
+ throw new TypeError('cancelToken must be a TransformCancelToken')
759
+ }
760
+ return token._requireOpen()
761
+ }
762
+
763
+ class OwnedTransform {
764
+ constructor(handle, token) {
765
+ this._handle = handle >>> 0
766
+ this._token = token || null
767
+ if (this._token) this._token._retain()
768
+ }
769
+
770
+ _requireOpen() {
771
+ if (!this._handle) {
772
+ throw new TranfiTransformError(112, 'prepared transform object is closed')
773
+ }
774
+ return this._handle
775
+ }
776
+
777
+ close() {
778
+ if (this._handle) {
779
+ var code = destroyHandle(this._handle)
780
+ this._handle = 0
781
+ if (this._token) {
782
+ this._token._release()
783
+ this._token = null
784
+ }
785
+ if (code !== 0) throw new TranfiTransformError(code, ERROR_NAMES[code])
786
+ }
787
+ }
788
+
789
+ dispose() {
790
+ this.close()
791
+ }
792
+ }
793
+
794
+ class TransformCancelToken extends OwnedTransform {
795
+ constructor(handle, sharedFlag, hostSlot) {
796
+ super(handle, null)
797
+ this._sharedFlag = sharedFlag || null
798
+ this._hostSlot = hostSlot
799
+ this._references = 1
800
+ this._requested = false
801
+ }
802
+
803
+ _retain() {
804
+ this._requireOpen()
805
+ ++this._references
806
+ }
807
+
808
+ _release() {
809
+ --this._references
810
+ if (this._references === 0 && this._hostSlot !== NO_HOST_CANCEL) {
811
+ cancelPolls.delete(this._hostSlot)
812
+ }
813
+ }
814
+
815
+ request() {
816
+ var handle = this._requireOpen()
817
+ this._requested = true
818
+ if (this._sharedFlag) Atomics.store(this._sharedFlag, 0, 1)
819
+ var code = raw('tf_wasm_transform_cancel_request', [handle])
820
+ if (code !== 0) throw new TranfiTransformError(code, ERROR_NAMES[code])
821
+ }
822
+
823
+ _observeNextPoll(observer) {
824
+ this._requireOpen()
825
+ if (typeof observer !== 'function') return
826
+ var poll = cancelPolls.get(this._hostSlot)
827
+ if (poll) poll.observer = observer
828
+ }
829
+
830
+ get requested() {
831
+ this._requireOpen()
832
+ return this._isRequested()
833
+ }
834
+
835
+ _isRequested() {
836
+ return this._requested || Boolean(
837
+ this._sharedFlag && Atomics.load(this._sharedFlag, 0) !== 0
838
+ )
839
+ }
840
+
841
+ close() {
842
+ if (this._handle) {
843
+ var code = destroyHandle(this._handle)
844
+ this._handle = 0
845
+ this._release()
846
+ if (code !== 0) throw new TranfiTransformError(code, ERROR_NAMES[code])
847
+ }
848
+ }
849
+ }
850
+
851
+ function createTransformCancelToken(options) {
852
+ options = options || {}
853
+ var flag = options.sharedFlag || null
854
+ var slot = NO_HOST_CANCEL
855
+ if (flag !== null) {
856
+ var shared = typeof SharedArrayBuffer !== 'undefined'
857
+ && flag instanceof Int32Array
858
+ && Object.prototype.toString.call(flag.buffer) === '[object SharedArrayBuffer]'
859
+ if (!shared || flag.length < 1 || typeof Atomics === 'undefined') {
860
+ throw new TypeError('sharedFlag must be a nonempty SharedArrayBuffer-backed Int32Array')
861
+ }
862
+ do {
863
+ slot = nextCancelSlot++ >>> 0
864
+ if (nextCancelSlot === NO_HOST_CANCEL) nextCancelSlot = 1
865
+ } while (cancelPolls.has(slot))
866
+ cancelPolls.set(slot, { flag: flag, observer: null })
867
+ }
868
+ var limits = null
869
+ try {
870
+ var effectiveLimits = resolvedLimits(options.limits)
871
+ limits = limitsOwner(options.limits, effectiveLimits)
872
+ var handle = callForHandle('tf_wasm_transform_cancel_create', [
873
+ slot, limits ? limits.pointer : 0
874
+ ])
875
+ return new TransformCancelToken(handle, flag, slot)
876
+ } catch (error) {
877
+ if (slot !== NO_HOST_CANCEL) cancelPolls.delete(slot)
878
+ throw error
879
+ } finally {
880
+ free(limits)
881
+ }
882
+ }
883
+
884
+ class TransformRecipe extends OwnedTransform {
885
+ static fromJSON(recipe, options) {
886
+ options = options || {}
887
+ var bytes = null
888
+ var limits = null
889
+ try {
890
+ var effectiveLimits = resolvedLimits(options.limits)
891
+ var normalized = normalizeRecipeJSON(recipe, effectiveLimits)
892
+ limits = limitsOwner(options.limits, effectiveLimits)
893
+ bytes = allocBytes(normalized, 1)
894
+ var handle = callForHandle('tf_wasm_transform_recipe_from_json', [
895
+ bytes.pointer, bytes.size, limits ? limits.pointer : 0
896
+ ])
897
+ return new TransformRecipe(handle)
898
+ } finally {
899
+ free(limits)
900
+ free(bytes)
901
+ }
902
+ }
903
+
904
+ analyzer(schema, options) {
905
+ var runtime = runtimeOptions(options)
906
+ var schemaAllocation = null
907
+ var limits = null
908
+ try {
909
+ var effectiveLimits = resolvedLimits(runtime.limits)
910
+ var cancelHandle = tokenHandle(runtime.cancelToken)
911
+ throwIfCancelled(runtime.cancelToken)
912
+ schemaAllocation = schemaOwner(
913
+ schema, effectiveLimits, runtime.cancelToken
914
+ )
915
+ throwIfCancelled(runtime.cancelToken)
916
+ limits = limitsOwner(runtime.limits, effectiveLimits)
917
+ var handle = callForHandle('tf_wasm_transform_analyzer_create', [
918
+ this._requireOpen(), schemaAllocation.pointer,
919
+ limits ? limits.pointer : 0, cancelHandle
920
+ ])
921
+ return new TransformAnalyzer(
922
+ handle, schemaAllocation.dtypes, runtime.cancelToken, effectiveLimits
923
+ )
924
+ } finally {
925
+ free(limits)
926
+ if (schemaAllocation) schemaAllocation.free()
927
+ }
928
+ }
929
+ }
930
+
931
+ class TransformAnalyzer extends OwnedTransform {
932
+ constructor(handle, dtypes, token, limits) {
933
+ super(handle, token)
934
+ this._dtypes = dtypes.slice()
935
+ this._limits = limits
936
+ }
937
+
938
+ push(table) {
939
+ try {
940
+ throwIfCancelled(this._token)
941
+ } catch (error) {
942
+ this.close()
943
+ throw error
944
+ }
945
+ var tableAllocation
946
+ try {
947
+ tableAllocation = tableOwner(
948
+ table, this._dtypes, this._limits, 'analyze', this._token
949
+ )
950
+ } catch (error) {
951
+ if (error && error.code === 109) this.close()
952
+ throw error
953
+ }
954
+ try {
955
+ try {
956
+ throwIfCancelled(this._token)
957
+ } catch (error) {
958
+ this.close()
959
+ throw error
960
+ }
961
+ try {
962
+ callWithError('tf_wasm_transform_analyzer_push', [
963
+ this._requireOpen(), tableAllocation.pointer
964
+ ])
965
+ } catch (error) {
966
+ if (error && error.code === 109) this.close()
967
+ throw error
968
+ }
969
+ return this
970
+ } finally {
971
+ tableAllocation.free()
972
+ }
973
+ }
974
+
975
+ finalize() {
976
+ try {
977
+ return new TransformPlan(callForHandle(
978
+ 'tf_wasm_transform_analyzer_finalize', [this._requireOpen()]
979
+ ))
980
+ } catch (error) {
981
+ if (error && error.code === 109) this.close()
982
+ throw error
983
+ }
984
+ }
985
+ }
986
+
987
+ class TransformPlan extends OwnedTransform {
988
+ static fromBytes(bytes, options) {
989
+ options = options || {}
990
+ if (!(bytes instanceof Uint8Array)) {
991
+ throw new TypeError('plan bytes must be Uint8Array')
992
+ }
993
+ var input = null
994
+ var runtime = runtimeOptions(options)
995
+ var limits = null
996
+ try {
997
+ var effectiveLimits = resolvedLimits(runtime.limits)
998
+ if (bytes.byteLength > effectiveLimits.maxPlanBytes
999
+ || bytes.byteLength > effectiveLimits.maxAllocationBytes) {
1000
+ throw resourceLimit('prepared-transform plan byte limit exceeded')
1001
+ }
1002
+ throwIfCancelled(runtime.cancelToken)
1003
+ limits = limitsOwner(runtime.limits, effectiveLimits)
1004
+ input = allocBytes(new Uint8Array(
1005
+ bytes.buffer, bytes.byteOffset, bytes.byteLength
1006
+ ), 1, runtime.cancelToken)
1007
+ throwIfCancelled(runtime.cancelToken)
1008
+ var handle = callForHandle('tf_wasm_transform_plan_import', [
1009
+ input.pointer, input.size, limits ? limits.pointer : 0,
1010
+ tokenHandle(runtime.cancelToken)
1011
+ ])
1012
+ return new TransformPlan(handle)
1013
+ } finally {
1014
+ free(limits)
1015
+ free(input)
1016
+ }
1017
+ }
1018
+
1019
+ toBytes(options) {
1020
+ options = options || {}
1021
+ var limits = limitsOwner(options.limits)
1022
+ try {
1023
+ return bytesFromHandle(callForHandle('tf_wasm_transform_plan_export', [
1024
+ this._requireOpen(), limits ? limits.pointer : 0
1025
+ ]))
1026
+ } finally {
1027
+ free(limits)
1028
+ }
1029
+ }
1030
+
1031
+ schemaJSON(which, options) {
1032
+ which = which === undefined ? 'output' : which
1033
+ options = options || {}
1034
+ var selector = which === 'input'
1035
+ ? SCHEMA_INPUT
1036
+ : which === 'output'
1037
+ ? SCHEMA_OUTPUT
1038
+ : 0
1039
+ if (!selector) throw new TypeError("which must be 'input' or 'output'")
1040
+ var limits = limitsOwner(options.limits)
1041
+ try {
1042
+ return bytesFromHandle(callForHandle('tf_wasm_transform_plan_schema_json', [
1043
+ this._requireOpen(), selector, limits ? limits.pointer : 0
1044
+ ]))
1045
+ } finally {
1046
+ free(limits)
1047
+ }
1048
+ }
1049
+
1050
+ recipeSha256(options) {
1051
+ options = options || {}
1052
+ var limits = limitsOwner(options.limits)
1053
+ try {
1054
+ return decoder.decode(bytesFromHandle(callForHandle(
1055
+ 'tf_wasm_transform_plan_recipe_sha256', [
1056
+ this._requireOpen(), limits ? limits.pointer : 0
1057
+ ]
1058
+ )))
1059
+ } finally {
1060
+ free(limits)
1061
+ }
1062
+ }
1063
+
1064
+ apply(schema, options) {
1065
+ var runtime = runtimeOptions(options)
1066
+ var schemaAllocation = null
1067
+ var limits = null
1068
+ try {
1069
+ var effectiveLimits = resolvedLimits(runtime.limits)
1070
+ var cancelHandle = tokenHandle(runtime.cancelToken)
1071
+ throwIfCancelled(runtime.cancelToken)
1072
+ schemaAllocation = schemaOwner(
1073
+ schema, effectiveLimits, runtime.cancelToken
1074
+ )
1075
+ throwIfCancelled(runtime.cancelToken)
1076
+ limits = limitsOwner(runtime.limits, effectiveLimits)
1077
+ var handle = callForHandle('tf_wasm_transform_apply_create', [
1078
+ this._requireOpen(), schemaAllocation.pointer,
1079
+ limits ? limits.pointer : 0, cancelHandle
1080
+ ])
1081
+ return new TransformApply(
1082
+ handle, schemaAllocation.dtypes, runtime.cancelToken, effectiveLimits
1083
+ )
1084
+ } finally {
1085
+ free(limits)
1086
+ if (schemaAllocation) schemaAllocation.free()
1087
+ }
1088
+ }
1089
+ }
1090
+
1091
+ class TransformApply extends OwnedTransform {
1092
+ constructor(handle, dtypes, token, limits) {
1093
+ super(handle, token)
1094
+ this._dtypes = dtypes.slice()
1095
+ this._limits = limits
1096
+ }
1097
+
1098
+ run(table) {
1099
+ try {
1100
+ throwIfCancelled(this._token)
1101
+ } catch (error) {
1102
+ this.close()
1103
+ throw error
1104
+ }
1105
+ var tableAllocation
1106
+ try {
1107
+ tableAllocation = tableOwner(
1108
+ table, this._dtypes, this._limits, 'apply', this._token
1109
+ )
1110
+ } catch (error) {
1111
+ if (error && error.code === 109) this.close()
1112
+ throw error
1113
+ }
1114
+ try {
1115
+ try {
1116
+ throwIfCancelled(this._token)
1117
+ } catch (error) {
1118
+ this.close()
1119
+ throw error
1120
+ }
1121
+ var denseHandle
1122
+ try {
1123
+ denseHandle = callForHandle('tf_wasm_transform_apply_run', [
1124
+ this._requireOpen(), tableAllocation.pointer
1125
+ ])
1126
+ } catch (error) {
1127
+ if (error && error.code === 109) this.close()
1128
+ throw error
1129
+ }
1130
+ try {
1131
+ return denseFromHandle(denseHandle, this._token)
1132
+ } catch (error) {
1133
+ try {
1134
+ this.close()
1135
+ } catch (_) {}
1136
+ throw error
1137
+ }
1138
+ } finally {
1139
+ tableAllocation.free()
1140
+ }
1141
+ }
1142
+ }
1143
+
1144
+ return {
1145
+ TranfiTransformError: TranfiTransformError,
1146
+ TransformRecipe: TransformRecipe,
1147
+ TransformAnalyzer: TransformAnalyzer,
1148
+ TransformPlan: TransformPlan,
1149
+ TransformApply: TransformApply,
1150
+ TransformCancelToken: TransformCancelToken,
1151
+ createTransformCancelToken: createTransformCancelToken,
1152
+ safeTransformLimits: safeTransformLimits
1153
+ }
1154
+ }
1155
+
1156
+ module.exports = createTransformAPI