Skip to content

Commit 349081e

Browse files
authored
Implement Map type (#61)
* Implement Map type * add test * readme note
1 parent 83aa1ba commit 349081e

7 files changed

+107
-19
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ Most of the unsupported types should be pretty straightforward to implement; the
173173
- [x] Large List (Not implemented by Arrow JS but supported by downcasting to `List`.)
174174
- [x] Fixed-size List
175175
- [x] Struct
176-
- [ ] Map
176+
- [x] Map (though not yet tested, see [#97](https://github.com/kylebarron/arrow-js-ffi/issues/97))
177177
- [x] Dense Union
178178
- [x] Sparse Union
179179
- [x] Dictionary-encoded arrays

src/field.ts

+7
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,13 @@ function parseFieldContent({
222222
return new arrow.Field(name, type, flags.nullable, metadata);
223223
}
224224

225+
// Map
226+
if (formatString === "+m") {
227+
assert(childrenFields.length === 1);
228+
const type = new arrow.Map_(childrenFields[0], flags.mapKeysSorted);
229+
return new arrow.Field(name, type, flags.nullable, metadata);
230+
}
231+
225232
// Dense union
226233
if (formatString.slice(0, 4) === "+ud:") {
227234
const typeIds = formatString.slice(4).split(",").map(Number);

src/vector.ts

+30
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,36 @@ function parseDataContent<T extends DataType>({
669669
});
670670
}
671671

672+
if (DataType.isMap(dataType)) {
673+
assert(nChildren === 1);
674+
const [validityPtr, offsetsPtr] = bufferPtrs;
675+
const nullBitmap = parseNullBitmap(
676+
dataView.buffer,
677+
validityPtr,
678+
length,
679+
copy,
680+
);
681+
const valueOffsets = copy
682+
? new Int32Array(
683+
copyBuffer(
684+
dataView.buffer,
685+
offsetsPtr,
686+
(length + 1) * Int32Array.BYTES_PER_ELEMENT,
687+
),
688+
)
689+
: new Int32Array(dataView.buffer, offsetsPtr, length + 1);
690+
691+
return arrow.makeData({
692+
type: dataType,
693+
offset,
694+
length,
695+
nullCount,
696+
nullBitmap,
697+
valueOffsets,
698+
child: children[0],
699+
});
700+
}
701+
672702
if (DataType.isDenseUnion(dataType)) {
673703
const [typeIdsPtr, offsetsPtr] = bufferPtrs;
674704

tests/ffi.test.ts

+39
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,45 @@ describe("nullable int", (t) => {
683683
it("copy=true", () => test(true));
684684
});
685685

686+
// Skipping this test because of rust issues
687+
// ref: https://github.com/kylebarron/arrow-js-ffi/issues/97
688+
describe.skip("map array", (t) => {
689+
function test(copy: boolean) {
690+
let columnIndex = TEST_TABLE.schema.fields.findIndex(
691+
(field) => field.name == "map_array"
692+
);
693+
694+
const originalField = TEST_TABLE.schema.fields[columnIndex];
695+
// declare it's not null
696+
const originalVector = TEST_TABLE.getChildAt(columnIndex) as arrow.Vector;
697+
const fieldPtr = FFI_TABLE.schemaAddr(columnIndex);
698+
const field = parseField(WASM_MEMORY.buffer, fieldPtr);
699+
700+
expect(field.name).toStrictEqual(originalField.name);
701+
expect(field.typeId).toStrictEqual(originalField.typeId);
702+
expect(field.nullable).toStrictEqual(originalField.nullable);
703+
704+
const arrayPtr = FFI_TABLE.arrayAddr(0, columnIndex);
705+
const wasmVector = parseVector(
706+
WASM_MEMORY.buffer,
707+
arrayPtr,
708+
field.type,
709+
copy
710+
);
711+
712+
console.log(originalVector);
713+
console.log(wasmVector);
714+
715+
// expect(
716+
// validityEqual(originalVector, wasmVector),
717+
// "validity should be equal"
718+
// ).toBeTruthy();
719+
}
720+
721+
it("copy=false", () => test(false));
722+
it("copy=true", () => test(true));
723+
});
724+
686725
describe("dictionary encoded string", (t) => {
687726
function test(copy: boolean) {
688727
let columnIndex = TEST_TABLE.schema.fields.findIndex(

tests/pyarrow_generate_data.py

+12
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,15 @@ def nullable_int() -> pa.Array:
140140
return arr
141141

142142

143+
def map_array() -> pa.Array:
144+
offsets = [0, 2, 3, 4]
145+
keys = ["a", "b", "a", "b"]
146+
items = [1, 2, 3, 4]
147+
arr = pa.MapArray.from_arrays(offsets, keys, items)
148+
assert isinstance(arr, pa.MapArray)
149+
return arr
150+
151+
143152
def sparse_union_array() -> pa.Array:
144153
"""Generate a sparse union array
145154
@@ -251,6 +260,9 @@ def table() -> pa.Table:
251260
"date64": date64_array(),
252261
"timestamp": timestamp_array(),
253262
"nullable_int": nullable_int(),
263+
# We don't yet include "map" in tests because of issues on the Rust side.
264+
# ref: https://github.com/kylebarron/arrow-js-ffi/issues/97
265+
# "map": map_array(),
254266
"sparse_union": sparse_union_array(),
255267
"dense_union": dense_union_array(),
256268
"duration": duration_array(),

tests/table.arrow

0 Bytes
Binary file not shown.

yarn.lock

+18-18
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,10 @@ __metadata:
338338
linkType: hard
339339

340340
"@rollup/plugin-typescript@npm:^11.1.2":
341-
version: 11.1.6
342-
resolution: "@rollup/plugin-typescript@npm:11.1.6"
341+
version: 11.1.5
342+
resolution: "@rollup/plugin-typescript@npm:11.1.5"
343343
dependencies:
344-
"@rollup/pluginutils": "npm:^5.1.0"
344+
"@rollup/pluginutils": "npm:^5.0.1"
345345
resolve: "npm:^1.22.1"
346346
peerDependencies:
347347
rollup: ^2.14.0||^3.0.0||^4.0.0
@@ -352,23 +352,23 @@ __metadata:
352352
optional: true
353353
tslib:
354354
optional: true
355-
checksum: 4ae4d6cfc929393171288df2f18b5eb837fa53d8689118d9661b3064567341f6f6cf8389af55f1d5f015e3682abf30a64ab609fdf75ecb5a84224505e407eb69
355+
checksum: 3048c7837bcaae3770e6977aa22b34b7da3862f14f25a22249c83867be1a3f78138c0a62b28efd22037890dfd6933e960007da6667a945dcef45f585a581f1aa
356356
languageName: node
357357
linkType: hard
358358

359-
"@rollup/pluginutils@npm:^5.1.0":
360-
version: 5.1.0
361-
resolution: "@rollup/pluginutils@npm:5.1.0"
359+
"@rollup/pluginutils@npm:^5.0.1":
360+
version: 5.0.2
361+
resolution: "@rollup/pluginutils@npm:5.0.2"
362362
dependencies:
363363
"@types/estree": "npm:^1.0.0"
364364
estree-walker: "npm:^2.0.2"
365365
picomatch: "npm:^2.3.1"
366366
peerDependencies:
367-
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
367+
rollup: ^1.20.0||^2.0.0||^3.0.0
368368
peerDependenciesMeta:
369369
rollup:
370370
optional: true
371-
checksum: abb15eaec5b36f159ec351b48578401bedcefdfa371d24a914cfdbb1e27d0ebfbf895299ec18ccc343d247e71f2502cba21202bc1362d7ef27d5ded699e5c2b2
371+
checksum: 7aebf04d5d25d7d2e9514cc8f81a49b11f093b29eae2862da29022532b66e3de4681f537cc785fdcf438bcdefa3af4453470e7951ca91d6ebea2f41d6aea42d3
372372
languageName: node
373373
linkType: hard
374374

@@ -2597,8 +2597,8 @@ __metadata:
25972597
linkType: hard
25982598

25992599
"ts-node@npm:^10.9.1":
2600-
version: 10.9.2
2601-
resolution: "ts-node@npm:10.9.2"
2600+
version: 10.9.1
2601+
resolution: "ts-node@npm:10.9.1"
26022602
dependencies:
26032603
"@cspotcode/source-map-support": "npm:^0.8.0"
26042604
"@tsconfig/node10": "npm:^1.0.7"
@@ -2630,7 +2630,7 @@ __metadata:
26302630
ts-node-script: dist/bin-script.js
26312631
ts-node-transpile-only: dist/bin-transpile.js
26322632
ts-script: dist/bin-script-deprecated.js
2633-
checksum: a91a15b3c9f76ac462f006fa88b6bfa528130dcfb849dd7ef7f9d640832ab681e235b8a2bc58ecde42f72851cc1d5d4e22c901b0c11aa51001ea1d395074b794
2633+
checksum: bee56d4dc96ccbafc99dfab7b73fbabc62abab2562af53cdea91c874a301b9d11e42bc33c0a032a6ed6d813dbdc9295ec73dde7b73ea4ebde02b0e22006f7e04
26342634
languageName: node
26352635
linkType: hard
26362636

@@ -2649,22 +2649,22 @@ __metadata:
26492649
linkType: hard
26502650

26512651
"typescript@npm:^5.2.2":
2652-
version: 5.3.3
2653-
resolution: "typescript@npm:5.3.3"
2652+
version: 5.2.2
2653+
resolution: "typescript@npm:5.2.2"
26542654
bin:
26552655
tsc: bin/tsc
26562656
tsserver: bin/tsserver
2657-
checksum: 6e4e6a14a50c222b3d14d4ea2f729e79f972fa536ac1522b91202a9a65af3605c2928c4a790a4a50aa13694d461c479ba92cedaeb1e7b190aadaa4e4b96b8e18
2657+
checksum: d65e50eb849bd21ff8677e5b9447f9c6e74777e346afd67754934264dcbf4bd59e7d2473f6062d9a015d66bd573311166357e3eb07fea0b52859cf9bb2b58555
26582658
languageName: node
26592659
linkType: hard
26602660

26612661
"typescript@patch:typescript@npm%3A^5.2.2#optional!builtin<compat/typescript>":
2662-
version: 5.3.3
2663-
resolution: "typescript@patch:typescript@npm%3A5.3.3#optional!builtin<compat/typescript>::version=5.3.3&hash=e012d7"
2662+
version: 5.2.2
2663+
resolution: "typescript@patch:typescript@npm%3A5.2.2#optional!builtin<compat/typescript>::version=5.2.2&hash=f3b441"
26642664
bin:
26652665
tsc: bin/tsc
26662666
tsserver: bin/tsserver
2667-
checksum: c93786fcc9a70718ba1e3819bab56064ead5817004d1b8186f8ca66165f3a2d0100fee91fa64c840dcd45f994ca5d615d8e1f566d39a7470fc1e014dbb4cf15d
2667+
checksum: f79cc2ba802c94c2b78dbb00d767a10adb67368ae764709737dc277273ec148aa4558033a03ce901406b35fddf4eac46dabc94a1e1d12d2587e2b9cfe5707b4a
26682668
languageName: node
26692669
linkType: hard
26702670

0 commit comments

Comments
 (0)