2024-05-13 01:12:30 +00:00
|
|
|
const dayMillis = 86400000 // 1 day in milliseconds
|
2024-02-26 20:20:48 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert known types from primitive to rich.
|
|
|
|
|
*
|
2024-05-02 06:23:50 +00:00
|
|
|
* @typedef {import('./types.js').DecodedArray} DecodedArray
|
|
|
|
|
* @param {DecodedArray} data series of primitive types
|
2024-04-28 22:58:25 +00:00
|
|
|
* @param {import('./types.js').SchemaElement} schemaElement schema element for the data
|
2024-05-02 06:23:50 +00:00
|
|
|
* @returns {DecodedArray} series of rich types
|
2024-02-26 20:20:48 +00:00
|
|
|
*/
|
|
|
|
|
export function convert(data, schemaElement) {
|
|
|
|
|
const ctype = schemaElement.converted_type
|
|
|
|
|
if (ctype === 'UTF8') {
|
|
|
|
|
const decoder = new TextDecoder()
|
2024-05-14 07:35:39 +00:00
|
|
|
const arr = new Array(data.length)
|
|
|
|
|
for (let i = 0; i < arr.length; i++) {
|
|
|
|
|
arr[i] = data[i] && decoder.decode(data[i])
|
|
|
|
|
}
|
|
|
|
|
return arr
|
2024-02-26 20:20:48 +00:00
|
|
|
}
|
|
|
|
|
if (ctype === 'DECIMAL') {
|
2024-05-13 02:52:15 +00:00
|
|
|
const scale = schemaElement.scale || 0
|
2024-05-13 03:41:39 +00:00
|
|
|
const factor = Math.pow(10, -scale)
|
2024-05-14 07:35:39 +00:00
|
|
|
const arr = new Array(data.length)
|
|
|
|
|
for (let i = 0; i < arr.length; i++) {
|
|
|
|
|
if (data[0] instanceof Uint8Array) {
|
|
|
|
|
arr[i] = parseDecimal(data[i]) * factor
|
|
|
|
|
} else {
|
|
|
|
|
arr[i] = Number(data[i]) * factor
|
|
|
|
|
}
|
2024-02-26 20:20:48 +00:00
|
|
|
}
|
2024-05-14 07:35:39 +00:00
|
|
|
return arr
|
2024-02-26 20:20:48 +00:00
|
|
|
}
|
2024-05-13 01:12:30 +00:00
|
|
|
if (ctype === undefined && schemaElement.type === 'INT96') {
|
2024-05-13 03:41:39 +00:00
|
|
|
return Array.from(data).map(parseInt96Date)
|
2024-05-13 01:12:30 +00:00
|
|
|
}
|
2024-05-14 07:35:39 +00:00
|
|
|
if (ctype === 'DATE') {
|
|
|
|
|
const arr = new Array(data.length)
|
|
|
|
|
for (let i = 0; i < arr.length; i++) {
|
|
|
|
|
arr[i] = new Date(data[i] * dayMillis)
|
|
|
|
|
}
|
|
|
|
|
return arr
|
2024-02-26 20:20:48 +00:00
|
|
|
}
|
|
|
|
|
if (ctype === 'JSON') {
|
|
|
|
|
return data.map(v => JSON.parse(v))
|
|
|
|
|
}
|
|
|
|
|
if (ctype === 'BSON') {
|
|
|
|
|
throw new Error('parquet bson not supported')
|
|
|
|
|
}
|
|
|
|
|
if (ctype === 'INTERVAL') {
|
|
|
|
|
throw new Error('parquet interval not supported')
|
|
|
|
|
}
|
2024-05-14 07:35:39 +00:00
|
|
|
// TODO: ctype UINT
|
2024-05-13 16:22:55 +00:00
|
|
|
const logicalType = schemaElement.logical_type?.type
|
|
|
|
|
if (logicalType === 'FLOAT16') {
|
|
|
|
|
return Array.from(data).map(parseFloat16)
|
|
|
|
|
}
|
2024-05-14 07:35:39 +00:00
|
|
|
// TODO: logical types
|
2024-02-26 20:20:48 +00:00
|
|
|
return data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Uint8Array} bytes
|
|
|
|
|
* @returns {number}
|
|
|
|
|
*/
|
|
|
|
|
function parseDecimal(bytes) {
|
|
|
|
|
// TODO: handle signed
|
|
|
|
|
let value = 0
|
|
|
|
|
for (const byte of bytes) {
|
|
|
|
|
value = value << 8 | byte
|
|
|
|
|
}
|
|
|
|
|
return value
|
|
|
|
|
}
|
2024-05-13 01:12:30 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {bigint} value
|
|
|
|
|
* @returns {Date}
|
|
|
|
|
*/
|
|
|
|
|
function parseInt96Date(value) {
|
|
|
|
|
const days = Number((value >> 64n) - 2440588n)
|
|
|
|
|
const nano = Number((value & 0xffffffffffffffffn) / 1000000n)
|
|
|
|
|
const millis = days * dayMillis + nano
|
|
|
|
|
return new Date(millis)
|
|
|
|
|
}
|
2024-05-13 16:22:55 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Uint8Array | undefined} bytes
|
|
|
|
|
* @returns {number | undefined}
|
|
|
|
|
*/
|
|
|
|
|
export function parseFloat16(bytes) {
|
|
|
|
|
if (!bytes) return undefined
|
|
|
|
|
const int16 = (bytes[1] << 8) | bytes[0]
|
|
|
|
|
const sign = int16 >> 15 ? -1 : 1
|
|
|
|
|
const exp = (int16 >> 10) & 0x1f
|
|
|
|
|
const frac = int16 & 0x3ff
|
|
|
|
|
if (exp === 0) return sign * Math.pow(2, -14) * (frac / 1024) // subnormals
|
|
|
|
|
if (exp === 0x1f) return frac ? NaN : sign * Infinity
|
|
|
|
|
return sign * Math.pow(2, exp - 15) * (1 + frac / 1024)
|
|
|
|
|
}
|