blob: c9c9d111193630e8545cc39c600e992dace88d43 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
import { Data } from '../data';
import { Field } from '../schema';
import { Column } from '../column';
import { Vector } from '../vector';
import { DataType } from '../type';
import { Chunked } from '../vector/chunked';
type RecordBatchCtor = typeof import('../recordbatch').RecordBatch;
const isArray = Array.isArray;
/** @ignore */
export const selectArgs = <T>(Ctor: any, vals: any[]) => _selectArgs(Ctor, vals, [], 0) as T[];
/** @ignore */
export const selectColumnArgs = <T extends { [key: string]: DataType }>(args: any[]) => {
const [fields, values] = _selectFieldArgs<T>(args, [[], []]);
return values.map((x, i) =>
x instanceof Column ? Column.new(x.field.clone(fields[i]), x) :
x instanceof Vector ? Column.new(fields[i], x) as Column<T[keyof T]> :
Column.new(fields[i], [] as Vector<T[keyof T]>[]));
};
/** @ignore */
export const selectFieldArgs = <T extends { [key: string]: DataType }>(args: any[]) => _selectFieldArgs<T>(args, [[], []]);
/** @ignore */
export const selectChunkArgs = <T>(Ctor: any, vals: any[]) => _selectChunkArgs(Ctor, vals, [], 0) as T[];
/** @ignore */
export const selectVectorChildrenArgs = <T extends Vector>(Ctor: RecordBatchCtor, vals: any[]) => _selectVectorChildrenArgs(Ctor, vals, [], 0) as T[];
/** @ignore */
export const selectColumnChildrenArgs = <T extends Column>(Ctor: RecordBatchCtor, vals: any[]) => _selectColumnChildrenArgs(Ctor, vals, [], 0) as T[];
/** @ignore */
function _selectArgs<T>(Ctor: any, vals: any[], res: T[], idx: number) {
let value: any, j = idx;
let i = -1;
const n = vals.length;
while (++i < n) {
if (isArray(value = vals[i])) {
j = _selectArgs(Ctor, value, res, j).length;
} else if (value instanceof Ctor) { res[j++] = value; }
}
return res;
}
/** @ignore */
function _selectChunkArgs<T>(Ctor: any, vals: any[], res: T[], idx: number) {
let value: any, j = idx;
let i = -1;
const n = vals.length;
while (++i < n) {
if (isArray(value = vals[i])) {
j = _selectChunkArgs(Ctor, value, res, j).length;
} else if (value instanceof Chunked) {
j = _selectChunkArgs(Ctor, value.chunks, res, j).length;
} else if (value instanceof Ctor) { res[j++] = value; }
}
return res;
}
/** @ignore */
function _selectVectorChildrenArgs<T extends Vector>(Ctor: RecordBatchCtor, vals: any[], res: T[], idx: number) {
let value: any, j = idx;
let i = -1;
const n = vals.length;
while (++i < n) {
if (isArray(value = vals[i])) {
j = _selectVectorChildrenArgs(Ctor, value, res, j).length;
} else if (value instanceof Ctor) {
j = _selectArgs(Vector, value.schema.fields.map((_, i) => value.getChildAt(i)!), res, j).length;
} else if (value instanceof Vector) { res[j++] = value as T; }
}
return res;
}
/** @ignore */
function _selectColumnChildrenArgs<T extends Column>(Ctor: RecordBatchCtor, vals: any[], res: T[], idx: number) {
let value: any, j = idx;
let i = -1;
const n = vals.length;
while (++i < n) {
if (isArray(value = vals[i])) {
j = _selectColumnChildrenArgs(Ctor, value, res, j).length;
} else if (value instanceof Ctor) {
j = _selectArgs(Column, value.schema.fields.map((f, i) => Column.new(f, value.getChildAt(i)!)), res, j).length;
} else if (value instanceof Column) { res[j++] = value as T; }
}
return res;
}
/** @ignore */
const toKeysAndValues = (xs: [any[], any[]], [k, v]: [any, any], i: number) => (xs[0][i] = k, xs[1][i] = v, xs);
/** @ignore */
function _selectFieldArgs<T extends { [key: string]: DataType }>(vals: any[], ret: [Field<T[keyof T]>[], Vector<T[keyof T]>[]]): [Field<T[keyof T]>[], (T[keyof T] | Vector<T[keyof T]>)[]] {
let keys: any[];
let n: number;
switch (n = vals.length) {
case 0: return ret;
case 1:
keys = ret[0];
if (!(vals[0])) { return ret; }
if (isArray(vals[0])) { return _selectFieldArgs(vals[0], ret); }
if (!(vals[0] instanceof Data || vals[0] instanceof Vector || vals[0] instanceof DataType)) {
[keys, vals] = Object.entries(vals[0]).reduce(toKeysAndValues, ret);
}
break;
default:
!isArray(keys = vals[n - 1])
? (vals = isArray(vals[0]) ? vals[0] : vals, keys = [])
: (vals = isArray(vals[0]) ? vals[0] : vals.slice(0, n - 1));
}
let fieldIndex = -1;
let valueIndex = -1;
let idx = -1;
const len = vals.length;
let field: number | string | Field<T[keyof T]>;
let val: Vector<T[keyof T]> | Data<T[keyof T]>;
const [fields, values] = ret as [Field<T[keyof T]>[], any[]];
while (++idx < len) {
val = vals[idx];
if (val instanceof Column && (values[++valueIndex] = val)) {
fields[++fieldIndex] = val.field.clone(keys[idx], val.type, true);
} else {
({ [idx]: field = idx } = keys);
if (val instanceof DataType && (values[++valueIndex] = val)) {
fields[++fieldIndex] = Field.new(field, val as DataType, true) as Field<T[keyof T]>;
} else if (val && val.type && (values[++valueIndex] = val)) {
val instanceof Data && (values[valueIndex] = val = Vector.new(val) as Vector);
fields[++fieldIndex] = Field.new(field, val.type, true) as Field<T[keyof T]>;
}
}
}
return ret;
}