1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18import { Data } from '../data';
19import { BN } from '../util/bn';
20import { Visitor } from '../visitor';
21import { decodeUtf8 } from '../util/utf8';
22import { VectorType } from '../interfaces';
23import { uint16ToFloat64 } from '../util/math';
24import { Type, UnionMode, Precision, DateUnit, TimeUnit, IntervalUnit } from '../enum';
25import {
26    DataType, Dictionary,
27    Bool, Null, Utf8, Binary, Decimal, FixedSizeBinary, List, FixedSizeList, Map_, Struct,
28    Float, Float16, Float32, Float64,
29    Int, Uint8, Uint16, Uint32, Uint64, Int8, Int16, Int32, Int64,
30    Date_, DateDay, DateMillisecond,
31    Interval, IntervalDayTime, IntervalYearMonth,
32    Time, TimeSecond, TimeMillisecond, TimeMicrosecond, TimeNanosecond,
33    Timestamp, TimestampSecond, TimestampMillisecond, TimestampMicrosecond, TimestampNanosecond,
34    Union, DenseUnion, SparseUnion,
35} from '../type';
36
37/** @ignore */
38export interface GetVisitor extends Visitor {
39    visit<T extends VectorType>  (node: T, index: number): T['TValue'];
40    visitMany<T extends VectorType>  (nodes: T[], indices: number[]): T['TValue'][];
41    getVisitFn<T extends Type>    (node: T): (vector: VectorType<T>, index: number) => VectorType<T>['TValue'];
42    getVisitFn<T extends DataType>(node: VectorType<T> | Data<T> | T): (vector: VectorType<T>, index: number) => VectorType<T>['TValue'];
43    visitNull                 <T extends Null>                 (vector: VectorType<T>, index: number): T['TValue'];
44    visitBool                 <T extends Bool>                 (vector: VectorType<T>, index: number): T['TValue'];
45    visitInt                  <T extends Int>                  (vector: VectorType<T>, index: number): T['TValue'];
46    visitInt8                 <T extends Int8>                 (vector: VectorType<T>, index: number): T['TValue'];
47    visitInt16                <T extends Int16>                (vector: VectorType<T>, index: number): T['TValue'];
48    visitInt32                <T extends Int32>                (vector: VectorType<T>, index: number): T['TValue'];
49    visitInt64                <T extends Int64>                (vector: VectorType<T>, index: number): T['TValue'];
50    visitUint8                <T extends Uint8>                (vector: VectorType<T>, index: number): T['TValue'];
51    visitUint16               <T extends Uint16>               (vector: VectorType<T>, index: number): T['TValue'];
52    visitUint32               <T extends Uint32>               (vector: VectorType<T>, index: number): T['TValue'];
53    visitUint64               <T extends Uint64>               (vector: VectorType<T>, index: number): T['TValue'];
54    visitFloat                <T extends Float>                (vector: VectorType<T>, index: number): T['TValue'];
55    visitFloat16              <T extends Float16>              (vector: VectorType<T>, index: number): T['TValue'];
56    visitFloat32              <T extends Float32>              (vector: VectorType<T>, index: number): T['TValue'];
57    visitFloat64              <T extends Float64>              (vector: VectorType<T>, index: number): T['TValue'];
58    visitUtf8                 <T extends Utf8>                 (vector: VectorType<T>, index: number): T['TValue'];
59    visitBinary               <T extends Binary>               (vector: VectorType<T>, index: number): T['TValue'];
60    visitFixedSizeBinary      <T extends FixedSizeBinary>      (vector: VectorType<T>, index: number): T['TValue'];
61    visitDate                 <T extends Date_>                (vector: VectorType<T>, index: number): T['TValue'];
62    visitDateDay              <T extends DateDay>              (vector: VectorType<T>, index: number): T['TValue'];
63    visitDateMillisecond      <T extends DateMillisecond>      (vector: VectorType<T>, index: number): T['TValue'];
64    visitTimestamp            <T extends Timestamp>            (vector: VectorType<T>, index: number): T['TValue'];
65    visitTimestampSecond      <T extends TimestampSecond>      (vector: VectorType<T>, index: number): T['TValue'];
66    visitTimestampMillisecond <T extends TimestampMillisecond> (vector: VectorType<T>, index: number): T['TValue'];
67    visitTimestampMicrosecond <T extends TimestampMicrosecond> (vector: VectorType<T>, index: number): T['TValue'];
68    visitTimestampNanosecond  <T extends TimestampNanosecond>  (vector: VectorType<T>, index: number): T['TValue'];
69    visitTime                 <T extends Time>                 (vector: VectorType<T>, index: number): T['TValue'];
70    visitTimeSecond           <T extends TimeSecond>           (vector: VectorType<T>, index: number): T['TValue'];
71    visitTimeMillisecond      <T extends TimeMillisecond>      (vector: VectorType<T>, index: number): T['TValue'];
72    visitTimeMicrosecond      <T extends TimeMicrosecond>      (vector: VectorType<T>, index: number): T['TValue'];
73    visitTimeNanosecond       <T extends TimeNanosecond>       (vector: VectorType<T>, index: number): T['TValue'];
74    visitDecimal              <T extends Decimal>              (vector: VectorType<T>, index: number): T['TValue'];
75    visitList                 <T extends List>                 (vector: VectorType<T>, index: number): T['TValue'];
76    visitStruct               <T extends Struct>               (vector: VectorType<T>, index: number): T['TValue'];
77    visitUnion                <T extends Union>                (vector: VectorType<T>, index: number): T['TValue'];
78    visitDenseUnion           <T extends DenseUnion>           (vector: VectorType<T>, index: number): T['TValue'];
79    visitSparseUnion          <T extends SparseUnion>          (vector: VectorType<T>, index: number): T['TValue'];
80    visitDictionary           <T extends Dictionary>           (vector: VectorType<T>, index: number): T['TValue'];
81    visitInterval             <T extends Interval>             (vector: VectorType<T>, index: number): T['TValue'];
82    visitIntervalDayTime      <T extends IntervalDayTime>      (vector: VectorType<T>, index: number): T['TValue'];
83    visitIntervalYearMonth    <T extends IntervalYearMonth>    (vector: VectorType<T>, index: number): T['TValue'];
84    visitFixedSizeList        <T extends FixedSizeList>        (vector: VectorType<T>, index: number): T['TValue'];
85    visitMap                  <T extends Map_>                 (vector: VectorType<T>, index: number): T['TValue'];
86}
87
88/** @ignore */
89export class GetVisitor extends Visitor {}
90
91/** @ignore */const epochDaysToMs = (data: Int32Array, index: number) => 86400000 * data[index];
92/** @ignore */const epochMillisecondsLongToMs = (data: Int32Array, index: number) => 4294967296 * (data[index + 1]) + (data[index] >>> 0);
93/** @ignore */const epochMicrosecondsLongToMs = (data: Int32Array, index: number) => 4294967296 * (data[index + 1] / 1000) + ((data[index] >>> 0) / 1000);
94/** @ignore */const epochNanosecondsLongToMs = (data: Int32Array, index: number) => 4294967296 * (data[index + 1] / 1000000) + ((data[index] >>> 0) / 1000000);
95
96/** @ignore */const epochMillisecondsToDate = (epochMs: number) => new Date(epochMs);
97/** @ignore */const epochDaysToDate = (data: Int32Array, index: number) => epochMillisecondsToDate(epochDaysToMs(data, index));
98/** @ignore */const epochMillisecondsLongToDate = (data: Int32Array, index: number) => epochMillisecondsToDate(epochMillisecondsLongToMs(data, index));
99
100/** @ignore */
101const getNull = <T extends Null>(_vector: VectorType<T>, _index: number): T['TValue'] => null;
102/** @ignore */
103const getVariableWidthBytes = (values: Uint8Array, valueOffsets: Int32Array, index: number) => {
104    const { [index]: x, [index + 1]: y } = valueOffsets;
105    return x != null && y != null ? values.subarray(x, y) : null as any;
106};
107
108/** @ignore */
109const getBool = <T extends Bool>({ offset, values }: VectorType<T>, index: number): T['TValue'] => {
110    const idx = offset + index;
111    const byte = values[idx >> 3];
112    return (byte & 1 << (idx % 8)) !== 0;
113};
114
115/** @ignore */
116type Numeric1X = Int8 | Int16 | Int32 | Uint8 | Uint16 | Uint32 | Float32 | Float64;
117/** @ignore */
118type Numeric2X = Int64 | Uint64;
119
120/** @ignore */
121const getDateDay         = <T extends DateDay>        ({ values         }: VectorType<T>, index: number): T['TValue'] => epochDaysToDate(values, index);
122/** @ignore */
123const getDateMillisecond = <T extends DateMillisecond>({ values         }: VectorType<T>, index: number): T['TValue'] => epochMillisecondsLongToDate(values, index * 2);
124/** @ignore */
125const getNumeric         = <T extends Numeric1X>      ({ stride, values }: VectorType<T>, index: number): T['TValue'] => values[stride * index];
126/** @ignore */
127const getFloat16         = <T extends Float16>        ({ stride, values }: VectorType<T>, index: number): T['TValue'] => uint16ToFloat64(values[stride * index]);
128/** @ignore */
129const getBigInts         = <T extends Numeric2X>({ stride, values, type }: VectorType<T>, index: number): T['TValue'] => <any> BN.new(values.subarray(stride * index, stride * (index + 1)), type.isSigned);
130/** @ignore */
131const getFixedSizeBinary = <T extends FixedSizeBinary>({ stride, values }: VectorType<T>, index: number): T['TValue'] => values.subarray(stride * index, stride * (index + 1));
132
133/** @ignore */
134const getBinary = <T extends Binary>({ values, valueOffsets }: VectorType<T>, index: number): T['TValue'] => getVariableWidthBytes(values, valueOffsets, index);
135/** @ignore */
136const getUtf8 = <T extends Utf8>({ values, valueOffsets }: VectorType<T>, index: number): T['TValue'] => {
137    const bytes = getVariableWidthBytes(values, valueOffsets, index);
138    return bytes !== null ? decodeUtf8(bytes) : null as any;
139};
140
141/* istanbul ignore next */
142/** @ignore */
143const getInt = <T extends Int>(vector: VectorType<T>, index: number): T['TValue'] => (
144    vector.type.bitWidth < 64
145        ? getNumeric(vector as VectorType<Numeric1X>, index)
146        : getBigInts(vector as VectorType<Numeric2X>, index)
147);
148
149/* istanbul ignore next */
150/** @ignore */
151const getFloat = <T extends Float> (vector: VectorType<T>, index: number): T['TValue'] => (
152    vector.type.precision !== Precision.HALF
153        ? getNumeric(vector as VectorType<Numeric1X>, index)
154        : getFloat16(vector as VectorType<Float16>, index)
155);
156
157/* istanbul ignore next */
158/** @ignore */
159const getDate = <T extends Date_> (vector: VectorType<T>, index: number): T['TValue'] => (
160    vector.type.unit === DateUnit.DAY
161        ? getDateDay(vector as VectorType<DateDay>, index)
162        : getDateMillisecond(vector as VectorType<DateMillisecond>, index)
163);
164
165/** @ignore */
166const getTimestampSecond      = <T extends TimestampSecond>     ({ values }: VectorType<T>, index: number): T['TValue'] => 1000 * epochMillisecondsLongToMs(values, index * 2);
167/** @ignore */
168const getTimestampMillisecond = <T extends TimestampMillisecond>({ values }: VectorType<T>, index: number): T['TValue'] => epochMillisecondsLongToMs(values, index * 2);
169/** @ignore */
170const getTimestampMicrosecond = <T extends TimestampMicrosecond>({ values }: VectorType<T>, index: number): T['TValue'] => epochMicrosecondsLongToMs(values, index * 2);
171/** @ignore */
172const getTimestampNanosecond  = <T extends TimestampNanosecond> ({ values }: VectorType<T>, index: number): T['TValue'] => epochNanosecondsLongToMs(values, index * 2);
173/* istanbul ignore next */
174/** @ignore */
175const getTimestamp            = <T extends Timestamp>(vector: VectorType<T>, index: number): T['TValue'] => {
176    switch (vector.type.unit) {
177        case TimeUnit.SECOND:      return      getTimestampSecond(vector as VectorType<TimestampSecond>, index);
178        case TimeUnit.MILLISECOND: return getTimestampMillisecond(vector as VectorType<TimestampMillisecond>, index);
179        case TimeUnit.MICROSECOND: return getTimestampMicrosecond(vector as VectorType<TimestampMicrosecond>, index);
180        case TimeUnit.NANOSECOND:  return  getTimestampNanosecond(vector as VectorType<TimestampNanosecond>, index);
181    }
182};
183
184/** @ignore */
185const getTimeSecond      = <T extends TimeSecond>     ({ values, stride }: VectorType<T>, index: number): T['TValue'] => values[stride * index];
186/** @ignore */
187const getTimeMillisecond = <T extends TimeMillisecond>({ values, stride }: VectorType<T>, index: number): T['TValue'] => values[stride * index];
188/** @ignore */
189const getTimeMicrosecond = <T extends TimeMicrosecond>({ values         }: VectorType<T>, index: number): T['TValue'] => BN.signed(values.subarray(2 * index, 2 * (index + 1)));
190/** @ignore */
191const getTimeNanosecond  = <T extends TimeNanosecond> ({ values         }: VectorType<T>, index: number): T['TValue'] => BN.signed(values.subarray(2 * index, 2 * (index + 1)));
192/* istanbul ignore next */
193/** @ignore */
194const getTime            = <T extends Time>(vector: VectorType<T>, index: number): T['TValue'] => {
195    switch (vector.type.unit) {
196        case TimeUnit.SECOND:      return      getTimeSecond(vector as VectorType<TimeSecond>, index);
197        case TimeUnit.MILLISECOND: return getTimeMillisecond(vector as VectorType<TimeMillisecond>, index);
198        case TimeUnit.MICROSECOND: return getTimeMicrosecond(vector as VectorType<TimeMicrosecond>, index);
199        case TimeUnit.NANOSECOND:  return  getTimeNanosecond(vector as VectorType<TimeNanosecond>, index);
200    }
201};
202
203/** @ignore */
204const getDecimal = <T extends Decimal>({ values }: VectorType<T>, index: number): T['TValue'] => BN.decimal(values.subarray(4 * index, 4 * (index + 1)));
205
206/** @ignore */
207const getList = <T extends List>(vector: VectorType<T>, index: number): T['TValue'] => {
208    const child = vector.getChildAt(0)!, { valueOffsets, stride } = vector;
209    return child.slice(valueOffsets[index * stride], valueOffsets[(index * stride) + 1]) as T['TValue'];
210};
211
212/** @ignore */
213const getMap = <T extends Map_>(vector: VectorType<T>, index: number): T['TValue'] => {
214    return vector.bind(index) as T['TValue'];
215};
216
217/** @ignore */
218const getStruct = <T extends Struct>(vector: VectorType<T>, index: number): T['TValue'] => {
219    return vector.bind(index) as T['TValue'];
220};
221
222/* istanbul ignore next */
223/** @ignore */
224const getUnion = <
225    V extends VectorType<Union> | VectorType<DenseUnion> | VectorType<SparseUnion>
226>(vector: V, index: number): V['TValue'] => {
227    return vector.type.mode === UnionMode.Dense ?
228        getDenseUnion(vector as VectorType<DenseUnion>, index) :
229        getSparseUnion(vector as VectorType<SparseUnion>, index);
230};
231
232/** @ignore */
233const getDenseUnion = <T extends DenseUnion>(vector: VectorType<T>, index: number): T['TValue'] => {
234    const childIndex = vector.typeIdToChildIndex[vector.typeIds[index]];
235    const child = vector.getChildAt(childIndex);
236    return child ? child.get(vector.valueOffsets[index]) : null;
237};
238
239/** @ignore */
240const getSparseUnion = <T extends SparseUnion>(vector: VectorType<T>, index: number): T['TValue'] => {
241    const childIndex = vector.typeIdToChildIndex[vector.typeIds[index]];
242    const child = vector.getChildAt(childIndex);
243    return child ? child.get(index) : null;
244};
245
246/** @ignore */
247const getDictionary = <T extends Dictionary>(vector: VectorType<T>, index: number): T['TValue'] => {
248    return vector.getValue(vector.getKey(index)!);
249};
250
251/* istanbul ignore next */
252/** @ignore */
253const getInterval = <T extends Interval>(vector: VectorType<T>, index: number): T['TValue'] =>
254    (vector.type.unit === IntervalUnit.DAY_TIME)
255        ? getIntervalDayTime(vector as VectorType<IntervalDayTime>, index)
256        : getIntervalYearMonth(vector as VectorType<IntervalYearMonth>, index);
257
258/** @ignore */
259const getIntervalDayTime = <T extends IntervalDayTime>({ values }: VectorType<T>, index: number): T['TValue'] => values.subarray(2 * index, 2 * (index + 1));
260
261/** @ignore */
262const getIntervalYearMonth = <T extends IntervalYearMonth>({ values }: VectorType<T>, index: number): T['TValue'] => {
263    const interval = values[index];
264    const int32s = new Int32Array(2);
265    int32s[0] = interval / 12 | 0; /* years */
266    int32s[1] = interval % 12 | 0; /* months */
267    return int32s;
268};
269
270/** @ignore */
271const getFixedSizeList = <T extends FixedSizeList>(vector: VectorType<T>, index: number): T['TValue'] => {
272    const child = vector.getChildAt(0)!, { stride } = vector;
273    return child.slice(index * stride, (index + 1) * stride) as T['TValue'];
274};
275
276GetVisitor.prototype.visitNull                 =                 getNull;
277GetVisitor.prototype.visitBool                 =                 getBool;
278GetVisitor.prototype.visitInt                  =                  getInt;
279GetVisitor.prototype.visitInt8                 =              getNumeric;
280GetVisitor.prototype.visitInt16                =              getNumeric;
281GetVisitor.prototype.visitInt32                =              getNumeric;
282GetVisitor.prototype.visitInt64                =              getBigInts;
283GetVisitor.prototype.visitUint8                =              getNumeric;
284GetVisitor.prototype.visitUint16               =              getNumeric;
285GetVisitor.prototype.visitUint32               =              getNumeric;
286GetVisitor.prototype.visitUint64               =              getBigInts;
287GetVisitor.prototype.visitFloat                =                getFloat;
288GetVisitor.prototype.visitFloat16              =              getFloat16;
289GetVisitor.prototype.visitFloat32              =              getNumeric;
290GetVisitor.prototype.visitFloat64              =              getNumeric;
291GetVisitor.prototype.visitUtf8                 =                 getUtf8;
292GetVisitor.prototype.visitBinary               =               getBinary;
293GetVisitor.prototype.visitFixedSizeBinary      =      getFixedSizeBinary;
294GetVisitor.prototype.visitDate                 =                 getDate;
295GetVisitor.prototype.visitDateDay              =              getDateDay;
296GetVisitor.prototype.visitDateMillisecond      =      getDateMillisecond;
297GetVisitor.prototype.visitTimestamp            =            getTimestamp;
298GetVisitor.prototype.visitTimestampSecond      =      getTimestampSecond;
299GetVisitor.prototype.visitTimestampMillisecond = getTimestampMillisecond;
300GetVisitor.prototype.visitTimestampMicrosecond = getTimestampMicrosecond;
301GetVisitor.prototype.visitTimestampNanosecond  =  getTimestampNanosecond;
302GetVisitor.prototype.visitTime                 =                 getTime;
303GetVisitor.prototype.visitTimeSecond           =           getTimeSecond;
304GetVisitor.prototype.visitTimeMillisecond      =      getTimeMillisecond;
305GetVisitor.prototype.visitTimeMicrosecond      =      getTimeMicrosecond;
306GetVisitor.prototype.visitTimeNanosecond       =       getTimeNanosecond;
307GetVisitor.prototype.visitDecimal              =              getDecimal;
308GetVisitor.prototype.visitList                 =                 getList;
309GetVisitor.prototype.visitStruct               =               getStruct;
310GetVisitor.prototype.visitUnion                =                getUnion;
311GetVisitor.prototype.visitDenseUnion           =           getDenseUnion;
312GetVisitor.prototype.visitSparseUnion          =          getSparseUnion;
313GetVisitor.prototype.visitDictionary           =           getDictionary;
314GetVisitor.prototype.visitInterval             =             getInterval;
315GetVisitor.prototype.visitIntervalDayTime      =      getIntervalDayTime;
316GetVisitor.prototype.visitIntervalYearMonth    =    getIntervalYearMonth;
317GetVisitor.prototype.visitFixedSizeList        =        getFixedSizeList;
318GetVisitor.prototype.visitMap                  =                  getMap;
319
320/** @ignore */
321export const instance = new GetVisitor();
322