2024-05-01 03:28:50 +00:00
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
|
import { readPlain } from '../src/plain.js'
|
|
|
|
|
|
|
|
|
|
describe('readPlain', () => {
|
2024-05-13 04:11:57 +00:00
|
|
|
it('returns empty array for count 0', () => {
|
|
|
|
|
const view = new DataView(new ArrayBuffer(4))
|
|
|
|
|
const reader = { view, offset: 0 }
|
|
|
|
|
const result = readPlain(reader, 'INT32', 0, undefined)
|
|
|
|
|
expect(result).toEqual([])
|
|
|
|
|
expect(reader.offset).toBe(0)
|
|
|
|
|
})
|
2024-05-01 03:28:50 +00:00
|
|
|
|
2024-05-03 00:21:17 +00:00
|
|
|
it('reads BOOLEAN values', () => {
|
2024-05-01 03:28:50 +00:00
|
|
|
const view = new DataView(new ArrayBuffer(1))
|
2024-05-03 00:21:17 +00:00
|
|
|
view.setUint8(0, 0b00000101) // true, false, true
|
2024-05-01 03:28:50 +00:00
|
|
|
const reader = { view, offset: 0 }
|
2024-05-13 04:11:57 +00:00
|
|
|
const result = readPlain(reader, 'BOOLEAN', 3, undefined)
|
2024-05-03 00:21:17 +00:00
|
|
|
expect(result).toEqual([true, false, true])
|
2024-05-01 03:28:50 +00:00
|
|
|
expect(reader.offset).toBe(1)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-03 00:21:17 +00:00
|
|
|
it('reads INT32 values', () => {
|
2024-05-01 03:28:50 +00:00
|
|
|
const view = new DataView(new ArrayBuffer(4))
|
|
|
|
|
view.setInt32(0, 123456789, true) // little-endian
|
|
|
|
|
const reader = { view, offset: 0 }
|
2024-05-13 04:11:57 +00:00
|
|
|
const result = readPlain(reader, 'INT32', 1, undefined)
|
2024-05-02 06:23:50 +00:00
|
|
|
expect(result).toEqual(new Int32Array([123456789]))
|
2024-05-01 03:28:50 +00:00
|
|
|
expect(reader.offset).toBe(4)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-13 04:11:57 +00:00
|
|
|
it('reads unaligned INT32 values', () => {
|
|
|
|
|
const view = new DataView(new ArrayBuffer(5))
|
|
|
|
|
view.setInt32(1, 123456789, true) // little-endian
|
|
|
|
|
const reader = { view, offset: 1 }
|
|
|
|
|
const result = readPlain(reader, 'INT32', 1, undefined)
|
|
|
|
|
expect(result).toEqual(new Int32Array([123456789]))
|
|
|
|
|
expect(reader.offset).toBe(5)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-03 00:21:17 +00:00
|
|
|
it('reads INT64 values', () => {
|
2024-05-01 03:28:50 +00:00
|
|
|
const view = new DataView(new ArrayBuffer(8))
|
2025-02-08 01:49:03 +00:00
|
|
|
view.setBigInt64(0, 1234567890123456789n, true)
|
2024-05-01 03:28:50 +00:00
|
|
|
const reader = { view, offset: 0 }
|
2024-05-13 04:11:57 +00:00
|
|
|
const result = readPlain(reader, 'INT64', 1, undefined)
|
2024-05-02 06:23:50 +00:00
|
|
|
expect(result).toEqual(new BigInt64Array([1234567890123456789n]))
|
2024-05-01 03:28:50 +00:00
|
|
|
expect(reader.offset).toBe(8)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-13 04:11:57 +00:00
|
|
|
it('reads unaligned INT64 values', () => {
|
|
|
|
|
const view = new DataView(new ArrayBuffer(9))
|
2025-02-08 01:49:03 +00:00
|
|
|
view.setBigInt64(1, 1234567890123456789n, true)
|
2024-05-13 04:11:57 +00:00
|
|
|
const reader = { view, offset: 1 }
|
|
|
|
|
const result = readPlain(reader, 'INT64', 1, undefined)
|
|
|
|
|
expect(result).toEqual(new BigInt64Array([1234567890123456789n]))
|
|
|
|
|
expect(reader.offset).toBe(9)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-03 00:21:17 +00:00
|
|
|
it('reads INT96 values', () => {
|
2024-05-01 03:28:50 +00:00
|
|
|
const buffer = new ArrayBuffer(12)
|
|
|
|
|
const view = new DataView(buffer)
|
|
|
|
|
|
2024-05-03 00:21:17 +00:00
|
|
|
// INT96 value split into 64-bit low part and 32-bit high part
|
2024-05-01 03:28:50 +00:00
|
|
|
const low = BigInt('0x0123456789ABCDEF')
|
|
|
|
|
const high = 0x02345678
|
|
|
|
|
view.setBigInt64(0, low, true)
|
|
|
|
|
view.setInt32(8, high, true)
|
|
|
|
|
const reader = { view, offset: 0 }
|
2024-05-13 04:11:57 +00:00
|
|
|
const result = readPlain(reader, 'INT96', 1, undefined)
|
2024-05-19 01:21:18 +00:00
|
|
|
const expectedValue = BigInt(high) << 64n | low
|
2024-05-01 03:28:50 +00:00
|
|
|
expect(result).toEqual([expectedValue])
|
|
|
|
|
expect(reader.offset).toBe(12)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-03 00:21:17 +00:00
|
|
|
it('reads FLOAT values', () => {
|
2024-05-01 03:28:50 +00:00
|
|
|
const view = new DataView(new ArrayBuffer(4))
|
|
|
|
|
view.setFloat32(0, 1234.5, true) // little-endian
|
|
|
|
|
const reader = { view, offset: 0 }
|
2024-05-13 04:11:57 +00:00
|
|
|
const result = readPlain(reader, 'FLOAT', 1, undefined)
|
2024-05-02 06:23:50 +00:00
|
|
|
expect(result).toEqual(new Float32Array([1234.5]))
|
2024-05-01 03:28:50 +00:00
|
|
|
expect(reader.offset).toBe(4)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-13 04:11:57 +00:00
|
|
|
it('reads unaligned FLOAT values', () => {
|
|
|
|
|
const view = new DataView(new ArrayBuffer(5))
|
|
|
|
|
view.setFloat32(1, 1234.5, true) // little-endian
|
|
|
|
|
const reader = { view, offset: 1 }
|
|
|
|
|
const result = readPlain(reader, 'FLOAT', 1, undefined)
|
|
|
|
|
expect(result).toEqual(new Float32Array([1234.5]))
|
|
|
|
|
expect(reader.offset).toBe(5)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-03 00:21:17 +00:00
|
|
|
it('reads DOUBLE values', () => {
|
2024-05-01 03:28:50 +00:00
|
|
|
const view = new DataView(new ArrayBuffer(8))
|
|
|
|
|
view.setFloat64(0, 12345.6789, true) // little-endian
|
|
|
|
|
const reader = { view, offset: 0 }
|
2024-05-13 04:11:57 +00:00
|
|
|
const result = readPlain(reader, 'DOUBLE', 1, undefined)
|
2024-05-02 06:23:50 +00:00
|
|
|
expect(result).toEqual(new Float64Array([12345.6789]))
|
2024-05-01 03:28:50 +00:00
|
|
|
expect(reader.offset).toBe(8)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-13 04:11:57 +00:00
|
|
|
it('reads unaligned DOUBLE values', () => {
|
|
|
|
|
const view = new DataView(new ArrayBuffer(9))
|
|
|
|
|
view.setFloat64(1, 12345.6789, true) // little-endian
|
|
|
|
|
const reader = { view, offset: 1 }
|
|
|
|
|
const result = readPlain(reader, 'DOUBLE', 1, undefined)
|
|
|
|
|
expect(result).toEqual(new Float64Array([12345.6789]))
|
|
|
|
|
expect(reader.offset).toBe(9)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-03 00:21:17 +00:00
|
|
|
it('reads BYTE_ARRAY values', () => {
|
2024-05-01 03:28:50 +00:00
|
|
|
const view = new DataView(new ArrayBuffer(10))
|
2024-05-03 00:21:17 +00:00
|
|
|
view.setInt32(0, 3, true) // length 3
|
|
|
|
|
view.setUint8(4, 1)
|
2024-05-01 03:28:50 +00:00
|
|
|
view.setUint8(5, 2)
|
|
|
|
|
view.setUint8(6, 3)
|
|
|
|
|
const reader = { view, offset: 0 }
|
2024-05-13 04:11:57 +00:00
|
|
|
const result = readPlain(reader, 'BYTE_ARRAY', 1, undefined)
|
2024-05-01 03:28:50 +00:00
|
|
|
expect(result).toEqual([new Uint8Array([1, 2, 3])])
|
|
|
|
|
expect(reader.offset).toBe(7)
|
|
|
|
|
})
|
|
|
|
|
|
2024-05-03 00:21:17 +00:00
|
|
|
it('reads FIXED_LEN_BYTE_ARRAY values', () => {
|
2024-05-13 04:11:57 +00:00
|
|
|
const fixedLength = 2
|
|
|
|
|
const view = new DataView(new ArrayBuffer(fixedLength * 2))
|
2024-05-01 03:28:50 +00:00
|
|
|
view.setUint8(0, 4)
|
|
|
|
|
view.setUint8(1, 5)
|
|
|
|
|
view.setUint8(2, 6)
|
2024-05-13 04:11:57 +00:00
|
|
|
view.setUint8(3, 7)
|
|
|
|
|
const reader = { view, offset: 0 }
|
|
|
|
|
const result = readPlain(reader, 'FIXED_LEN_BYTE_ARRAY', 2, fixedLength)
|
|
|
|
|
expect(result).toEqual([new Uint8Array([4, 5]), new Uint8Array([6, 7])])
|
|
|
|
|
expect(reader.offset).toBe(4)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('throws for missing fixedLength', () => {
|
|
|
|
|
const view = new DataView(new ArrayBuffer(1))
|
2024-05-01 03:28:50 +00:00
|
|
|
const reader = { view, offset: 0 }
|
2024-05-13 04:11:57 +00:00
|
|
|
expect(() => readPlain(reader, 'FIXED_LEN_BYTE_ARRAY', 1, undefined))
|
|
|
|
|
.toThrow('parquet missing fixed length')
|
2024-05-01 03:28:50 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('throws an error for unhandled types', () => {
|
|
|
|
|
const view = new DataView(new ArrayBuffer(0))
|
|
|
|
|
const reader = { view, offset: 0 }
|
|
|
|
|
/** @type any */
|
|
|
|
|
const invalidType = 'invalidType'
|
2024-05-13 04:11:57 +00:00
|
|
|
expect(() => readPlain(reader, invalidType, 1, undefined))
|
2024-05-01 03:28:50 +00:00
|
|
|
.toThrow(`parquet unhandled type: ${invalidType}`)
|
|
|
|
|
})
|
|
|
|
|
})
|