From 02c2c6b32c5e23cf77f1cefcf0e8dbf894df001e Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Fri, 11 Aug 2023 11:56:21 +0100 Subject: [PATCH 1/9] feat: More scalars --- src/scalar/int16.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/scalar/int32.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/scalar/int64.ts | 14 +++++++-- src/scalar/uint16.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/scalar/uint32.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/scalar/uint64.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 372 insertions(+), 2 deletions(-) create mode 100644 src/scalar/int16.ts create mode 100644 src/scalar/int32.ts create mode 100644 src/scalar/uint16.ts create mode 100644 src/scalar/uint32.ts create mode 100644 src/scalar/uint64.ts diff --git a/src/scalar/int16.ts b/src/scalar/int16.ts new file mode 100644 index 0000000..120fdbb --- /dev/null +++ b/src/scalar/int16.ts @@ -0,0 +1,72 @@ +import { DataType, Int16 as ArrowInt16 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Int16 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowInt16(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Int16) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validInt16(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Int16`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validInt16(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Int16`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Int16`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validInt16(n: bigint) { + return Number.isSafeInteger(n) && n >= -32_768 && n <= 32_767; + } +} diff --git a/src/scalar/int32.ts b/src/scalar/int32.ts new file mode 100644 index 0000000..62e91f9 --- /dev/null +++ b/src/scalar/int32.ts @@ -0,0 +1,72 @@ +import { DataType, Int32 as ArrowInt32 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Int32 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowInt32(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Int32) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validInt32(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Int32`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validInt32(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Int32`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Int32`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validInt32(n: bigint) { + return Number.isSafeInteger(n) && n >= -2_147_483_648 && n <= 2_147_483_647; + } +} diff --git a/src/scalar/int64.ts b/src/scalar/int64.ts index fea0d8b..c956081 100644 --- a/src/scalar/int64.ts +++ b/src/scalar/int64.ts @@ -37,16 +37,20 @@ export class Int64 implements Scalar { } if (typeof value === 'bigint') { + if (!this.validInt64(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Int64`); + } this._value = value; this._valid = true; return; } if (typeof value === 'number') { - if (!Number.isSafeInteger(value)) { + const v = BigInt(value); + if (!this.validInt64(v)) { throw new TypeError(`Value '${value}' cannot be safely converted to Int64`); } - this._value = BigInt(value); + this._value = v; this._valid = true; return; } @@ -61,4 +65,10 @@ export class Int64 implements Scalar { return NULL_VALUE; } + + validInt64(n: bigint) { + const MIN_INT64 = BigInt('-9223372036854775808'); // -2^63 + const MAX_INT64 = BigInt('9223372036854775807'); // 2^63 - 1 + return Number.isSafeInteger(n) && n >= MIN_INT64 && n <= MAX_INT64; + } } diff --git a/src/scalar/uint16.ts b/src/scalar/uint16.ts new file mode 100644 index 0000000..dcee777 --- /dev/null +++ b/src/scalar/uint16.ts @@ -0,0 +1,72 @@ +import { DataType, Uint16 as ArrowUint16 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Uint16 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowUint16(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Uint16) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validUint16(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint16`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validUint16(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint16`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Uint16`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validUint16(n: bigint) { + return Number.isSafeInteger(n) && n >= 0 && n <= 65535; + } +} diff --git a/src/scalar/uint32.ts b/src/scalar/uint32.ts new file mode 100644 index 0000000..a1f4fca --- /dev/null +++ b/src/scalar/uint32.ts @@ -0,0 +1,72 @@ +import { DataType, Uint32 as ArrowUint32 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Uint32 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowUint32(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Uint32) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validUint32(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint32`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validUint32(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint32`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Uint32`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validUint32(n: bigint) { + return Number.isSafeInteger(n) && n >= 0 && n <= 4294967295; + } +} diff --git a/src/scalar/uint64.ts b/src/scalar/uint64.ts new file mode 100644 index 0000000..9bb7c6c --- /dev/null +++ b/src/scalar/uint64.ts @@ -0,0 +1,72 @@ +import { DataType, Uint64 as ArrowUint64 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Uint64 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowUint64(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Uint64) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validUint64(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint64`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validUint64(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint64`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Uint64`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validUint64(n: bigint) { + return Number.isSafeInteger(n) && n >= 0 && n <= 18446744073709551615n; + } +} From 49b6d6f0dfeb84e448f62a3129fd1700f01dee19 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Fri, 11 Aug 2023 11:56:36 +0100 Subject: [PATCH 2/9] Remove redundant ints --- src/scalar/int16.ts | 72 -------------------------------------------- src/scalar/int32.ts | 72 -------------------------------------------- src/scalar/uint16.ts | 72 -------------------------------------------- src/scalar/uint32.ts | 72 -------------------------------------------- src/scalar/uint64.ts | 72 -------------------------------------------- 5 files changed, 360 deletions(-) delete mode 100644 src/scalar/int16.ts delete mode 100644 src/scalar/int32.ts delete mode 100644 src/scalar/uint16.ts delete mode 100644 src/scalar/uint32.ts delete mode 100644 src/scalar/uint64.ts diff --git a/src/scalar/int16.ts b/src/scalar/int16.ts deleted file mode 100644 index 120fdbb..0000000 --- a/src/scalar/int16.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { DataType, Int16 as ArrowInt16 } from '@apache-arrow/esnext-esm'; - -import { Scalar } from './scalar.js'; -import { isInvalid, NULL_VALUE } from './util.js'; - -export class Int16 implements Scalar { - private _valid = false; - private _value: bigint = BigInt(0); - - public constructor(v?: unknown) { - this.value = v; - return this; - } - - public get dataType(): DataType { - return new ArrowInt16(); - } - - public get valid(): boolean { - return this._valid; - } - - public get value(): bigint { - return this._value; - } - - public set value(value: unknown) { - if (isInvalid(value)) { - this._valid = false; - return; - } - - if (value instanceof Int16) { - this._valid = value.valid; - this._value = value.value; - return; - } - - if (typeof value === 'bigint') { - if (!this.validInt16(value)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Int16`); - } - this._value = value; - this._valid = true; - return; - } - - if (typeof value === 'number') { - const v = BigInt(value); - if (!this.validInt16(v)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Int16`); - } - this._value = v; - this._valid = true; - return; - } - - throw new Error(`Unable to set '${value}' as Int16`); - } - - public toString() { - if (this._valid) { - return String(this._value); - } - - return NULL_VALUE; - } - - validInt16(n: bigint) { - return Number.isSafeInteger(n) && n >= -32_768 && n <= 32_767; - } -} diff --git a/src/scalar/int32.ts b/src/scalar/int32.ts deleted file mode 100644 index 62e91f9..0000000 --- a/src/scalar/int32.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { DataType, Int32 as ArrowInt32 } from '@apache-arrow/esnext-esm'; - -import { Scalar } from './scalar.js'; -import { isInvalid, NULL_VALUE } from './util.js'; - -export class Int32 implements Scalar { - private _valid = false; - private _value: bigint = BigInt(0); - - public constructor(v?: unknown) { - this.value = v; - return this; - } - - public get dataType(): DataType { - return new ArrowInt32(); - } - - public get valid(): boolean { - return this._valid; - } - - public get value(): bigint { - return this._value; - } - - public set value(value: unknown) { - if (isInvalid(value)) { - this._valid = false; - return; - } - - if (value instanceof Int32) { - this._valid = value.valid; - this._value = value.value; - return; - } - - if (typeof value === 'bigint') { - if (!this.validInt32(value)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Int32`); - } - this._value = value; - this._valid = true; - return; - } - - if (typeof value === 'number') { - const v = BigInt(value); - if (!this.validInt32(v)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Int32`); - } - this._value = v; - this._valid = true; - return; - } - - throw new Error(`Unable to set '${value}' as Int32`); - } - - public toString() { - if (this._valid) { - return String(this._value); - } - - return NULL_VALUE; - } - - validInt32(n: bigint) { - return Number.isSafeInteger(n) && n >= -2_147_483_648 && n <= 2_147_483_647; - } -} diff --git a/src/scalar/uint16.ts b/src/scalar/uint16.ts deleted file mode 100644 index dcee777..0000000 --- a/src/scalar/uint16.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { DataType, Uint16 as ArrowUint16 } from '@apache-arrow/esnext-esm'; - -import { Scalar } from './scalar.js'; -import { isInvalid, NULL_VALUE } from './util.js'; - -export class Uint16 implements Scalar { - private _valid = false; - private _value: bigint = BigInt(0); - - public constructor(v?: unknown) { - this.value = v; - return this; - } - - public get dataType(): DataType { - return new ArrowUint16(); - } - - public get valid(): boolean { - return this._valid; - } - - public get value(): bigint { - return this._value; - } - - public set value(value: unknown) { - if (isInvalid(value)) { - this._valid = false; - return; - } - - if (value instanceof Uint16) { - this._valid = value.valid; - this._value = value.value; - return; - } - - if (typeof value === 'bigint') { - if (!this.validUint16(value)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Uint16`); - } - this._value = value; - this._valid = true; - return; - } - - if (typeof value === 'number') { - const v = BigInt(value); - if (!this.validUint16(v)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Uint16`); - } - this._value = v; - this._valid = true; - return; - } - - throw new Error(`Unable to set '${value}' as Uint16`); - } - - public toString() { - if (this._valid) { - return String(this._value); - } - - return NULL_VALUE; - } - - validUint16(n: bigint) { - return Number.isSafeInteger(n) && n >= 0 && n <= 65535; - } -} diff --git a/src/scalar/uint32.ts b/src/scalar/uint32.ts deleted file mode 100644 index a1f4fca..0000000 --- a/src/scalar/uint32.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { DataType, Uint32 as ArrowUint32 } from '@apache-arrow/esnext-esm'; - -import { Scalar } from './scalar.js'; -import { isInvalid, NULL_VALUE } from './util.js'; - -export class Uint32 implements Scalar { - private _valid = false; - private _value: bigint = BigInt(0); - - public constructor(v?: unknown) { - this.value = v; - return this; - } - - public get dataType(): DataType { - return new ArrowUint32(); - } - - public get valid(): boolean { - return this._valid; - } - - public get value(): bigint { - return this._value; - } - - public set value(value: unknown) { - if (isInvalid(value)) { - this._valid = false; - return; - } - - if (value instanceof Uint32) { - this._valid = value.valid; - this._value = value.value; - return; - } - - if (typeof value === 'bigint') { - if (!this.validUint32(value)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Uint32`); - } - this._value = value; - this._valid = true; - return; - } - - if (typeof value === 'number') { - const v = BigInt(value); - if (!this.validUint32(v)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Uint32`); - } - this._value = v; - this._valid = true; - return; - } - - throw new Error(`Unable to set '${value}' as Uint32`); - } - - public toString() { - if (this._valid) { - return String(this._value); - } - - return NULL_VALUE; - } - - validUint32(n: bigint) { - return Number.isSafeInteger(n) && n >= 0 && n <= 4294967295; - } -} diff --git a/src/scalar/uint64.ts b/src/scalar/uint64.ts deleted file mode 100644 index 9bb7c6c..0000000 --- a/src/scalar/uint64.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { DataType, Uint64 as ArrowUint64 } from '@apache-arrow/esnext-esm'; - -import { Scalar } from './scalar.js'; -import { isInvalid, NULL_VALUE } from './util.js'; - -export class Uint64 implements Scalar { - private _valid = false; - private _value: bigint = BigInt(0); - - public constructor(v?: unknown) { - this.value = v; - return this; - } - - public get dataType(): DataType { - return new ArrowUint64(); - } - - public get valid(): boolean { - return this._valid; - } - - public get value(): bigint { - return this._value; - } - - public set value(value: unknown) { - if (isInvalid(value)) { - this._valid = false; - return; - } - - if (value instanceof Uint64) { - this._valid = value.valid; - this._value = value.value; - return; - } - - if (typeof value === 'bigint') { - if (!this.validUint64(value)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Uint64`); - } - this._value = value; - this._valid = true; - return; - } - - if (typeof value === 'number') { - const v = BigInt(value); - if (!this.validUint64(v)) { - throw new TypeError(`Value '${value}' cannot be safely converted to Uint64`); - } - this._value = v; - this._valid = true; - return; - } - - throw new Error(`Unable to set '${value}' as Uint64`); - } - - public toString() { - if (this._valid) { - return String(this._value); - } - - return NULL_VALUE; - } - - validUint64(n: bigint) { - return Number.isSafeInteger(n) && n >= 0 && n <= 18446744073709551615n; - } -} From e35350f3ae76a22f9da3706c305a06561cccd373 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Fri, 11 Aug 2023 11:57:22 +0100 Subject: [PATCH 3/9] Revert "Remove redundant ints" This reverts commit 49b6d6f0dfeb84e448f62a3129fd1700f01dee19. --- src/scalar/int16.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/scalar/int32.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/scalar/uint16.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/scalar/uint32.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ src/scalar/uint64.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 360 insertions(+) create mode 100644 src/scalar/int16.ts create mode 100644 src/scalar/int32.ts create mode 100644 src/scalar/uint16.ts create mode 100644 src/scalar/uint32.ts create mode 100644 src/scalar/uint64.ts diff --git a/src/scalar/int16.ts b/src/scalar/int16.ts new file mode 100644 index 0000000..120fdbb --- /dev/null +++ b/src/scalar/int16.ts @@ -0,0 +1,72 @@ +import { DataType, Int16 as ArrowInt16 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Int16 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowInt16(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Int16) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validInt16(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Int16`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validInt16(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Int16`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Int16`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validInt16(n: bigint) { + return Number.isSafeInteger(n) && n >= -32_768 && n <= 32_767; + } +} diff --git a/src/scalar/int32.ts b/src/scalar/int32.ts new file mode 100644 index 0000000..62e91f9 --- /dev/null +++ b/src/scalar/int32.ts @@ -0,0 +1,72 @@ +import { DataType, Int32 as ArrowInt32 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Int32 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowInt32(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Int32) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validInt32(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Int32`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validInt32(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Int32`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Int32`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validInt32(n: bigint) { + return Number.isSafeInteger(n) && n >= -2_147_483_648 && n <= 2_147_483_647; + } +} diff --git a/src/scalar/uint16.ts b/src/scalar/uint16.ts new file mode 100644 index 0000000..dcee777 --- /dev/null +++ b/src/scalar/uint16.ts @@ -0,0 +1,72 @@ +import { DataType, Uint16 as ArrowUint16 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Uint16 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowUint16(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Uint16) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validUint16(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint16`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validUint16(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint16`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Uint16`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validUint16(n: bigint) { + return Number.isSafeInteger(n) && n >= 0 && n <= 65535; + } +} diff --git a/src/scalar/uint32.ts b/src/scalar/uint32.ts new file mode 100644 index 0000000..a1f4fca --- /dev/null +++ b/src/scalar/uint32.ts @@ -0,0 +1,72 @@ +import { DataType, Uint32 as ArrowUint32 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Uint32 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowUint32(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Uint32) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validUint32(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint32`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validUint32(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint32`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Uint32`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validUint32(n: bigint) { + return Number.isSafeInteger(n) && n >= 0 && n <= 4294967295; + } +} diff --git a/src/scalar/uint64.ts b/src/scalar/uint64.ts new file mode 100644 index 0000000..9bb7c6c --- /dev/null +++ b/src/scalar/uint64.ts @@ -0,0 +1,72 @@ +import { DataType, Uint64 as ArrowUint64 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Uint64 implements Scalar { + private _valid = false; + private _value: bigint = BigInt(0); + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowUint64(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): bigint { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Uint64) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'bigint') { + if (!this.validUint64(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint64`); + } + this._value = value; + this._valid = true; + return; + } + + if (typeof value === 'number') { + const v = BigInt(value); + if (!this.validUint64(v)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Uint64`); + } + this._value = v; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Uint64`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validUint64(n: bigint) { + return Number.isSafeInteger(n) && n >= 0 && n <= 18446744073709551615n; + } +} From b36f3100694bf078c3d0df5a55ced04cd8f85ab1 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Fri, 11 Aug 2023 12:02:07 +0100 Subject: [PATCH 4/9] init other int/uint bitwidths --- src/scalar/scalar.ts | 31 ++++++++++++++++++++++++++++++- src/scalar/uint16.ts | 2 +- src/scalar/uint32.ts | 2 +- src/scalar/uint64.ts | 2 +- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/scalar/scalar.ts b/src/scalar/scalar.ts index 13847c4..eb5d8dd 100644 --- a/src/scalar/scalar.ts +++ b/src/scalar/scalar.ts @@ -2,9 +2,14 @@ import { DataType } from '@apache-arrow/esnext-esm'; import { Bool } from './bool.js'; import { Float64 } from './float64.js'; +import { Int16 } from './int16.js'; +import { Int32 } from './int32.js'; import { Int64 } from './int64.js'; import { Text } from './text.js'; import { Timestamp } from './timestamp.js'; +import { Uint16 } from './uint16.js'; +import { Uint32 } from './uint32.js'; +import { Uint64 } from './uint64.js'; export interface Scalar { toString: () => string; @@ -21,7 +26,31 @@ export const newScalar = (dataType: DataType): Scalar => { return new Bool(); } if (DataType.isInt(dataType)) { - return new Int64(); + if (dataType.isSigned) { + switch (dataType.bitWidth) { + case 16: { + return new Int16(); + } + case 32: { + return new Int32(); + } + default: { + return new Int64(); + } + } + } + + switch (dataType.bitWidth) { + case 16: { + return new Uint16(); + } + case 32: { + return new Uint32(); + } + default: { + return new Uint64(); + } + } } if (DataType.isFloat(dataType)) { return new Float64(); diff --git a/src/scalar/uint16.ts b/src/scalar/uint16.ts index dcee777..765f644 100644 --- a/src/scalar/uint16.ts +++ b/src/scalar/uint16.ts @@ -67,6 +67,6 @@ export class Uint16 implements Scalar { } validUint16(n: bigint) { - return Number.isSafeInteger(n) && n >= 0 && n <= 65535; + return Number.isSafeInteger(n) && n >= 0 && n <= 65_535; } } diff --git a/src/scalar/uint32.ts b/src/scalar/uint32.ts index a1f4fca..600e9f2 100644 --- a/src/scalar/uint32.ts +++ b/src/scalar/uint32.ts @@ -67,6 +67,6 @@ export class Uint32 implements Scalar { } validUint32(n: bigint) { - return Number.isSafeInteger(n) && n >= 0 && n <= 4294967295; + return Number.isSafeInteger(n) && n >= 0 && n <= 4_294_967_295; } } diff --git a/src/scalar/uint64.ts b/src/scalar/uint64.ts index 9bb7c6c..87be869 100644 --- a/src/scalar/uint64.ts +++ b/src/scalar/uint64.ts @@ -67,6 +67,6 @@ export class Uint64 implements Scalar { } validUint64(n: bigint) { - return Number.isSafeInteger(n) && n >= 0 && n <= 18446744073709551615n; + return Number.isSafeInteger(n) && n >= 0 && n <= 18_446_744_073_709_551_615n; } } From e6d1225b08cf7fdc8f882ca0522b6107931091b4 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Fri, 11 Aug 2023 12:10:08 +0100 Subject: [PATCH 5/9] Add float32 --- src/scalar/float32.ts | 76 +++++++++++++++++++++++++++++++++++++++++++ src/scalar/scalar.ts | 18 ++++++++-- 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 src/scalar/float32.ts diff --git a/src/scalar/float32.ts b/src/scalar/float32.ts new file mode 100644 index 0000000..0c31ed3 --- /dev/null +++ b/src/scalar/float32.ts @@ -0,0 +1,76 @@ +import { DataType, Float32 as ArrowFloat32 } from '@apache-arrow/esnext-esm'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Float32 implements Scalar { + private _valid = false; + private _value: number = 0; + + public constructor(v?: unknown) { + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowFloat32(); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): number { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Float32) { + this._valid = value.valid; + this._value = value.value; + return; + } + + if (typeof value === 'number') { + if (!this.validFloat32(value)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Float32`); + } + + this._value = value; + this._valid = true; + return; + } + + const floatValue = Number.parseFloat(String(value)); + if (!Number.isNaN(floatValue)) { + if (!this.validFloat32(floatValue)) { + throw new TypeError(`Value '${value}' cannot be safely converted to Float32`); + } + + this._value = floatValue; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Float32`); + } + + public toString() { + if (this._valid) { + return String(this._value); + } + + return NULL_VALUE; + } + + validFloat32(n: number) { + const float32 = new Float32Array(1); + float32[0] = n; + return float32[0] === n; + } +} diff --git a/src/scalar/scalar.ts b/src/scalar/scalar.ts index eb5d8dd..89b3241 100644 --- a/src/scalar/scalar.ts +++ b/src/scalar/scalar.ts @@ -1,6 +1,7 @@ -import { DataType } from '@apache-arrow/esnext-esm'; +import { DataType, Precision } from '@apache-arrow/esnext-esm'; import { Bool } from './bool.js'; +import { Float32 } from './float32.js'; import { Float64 } from './float64.js'; import { Int16 } from './int16.js'; import { Int32 } from './int32.js'; @@ -25,6 +26,7 @@ export const newScalar = (dataType: DataType): Scalar => { if (DataType.isBool(dataType)) { return new Bool(); } + if (DataType.isInt(dataType)) { if (dataType.isSigned) { switch (dataType.bitWidth) { @@ -52,9 +54,21 @@ export const newScalar = (dataType: DataType): Scalar => { } } } + if (DataType.isFloat(dataType)) { - return new Float64(); + switch (dataType.precision) { + // case Precision.HALF: { + // TODO + // } + case Precision.SINGLE: { + return new Float32(); + } + default: { + return new Float64(); + } + } } + if (DataType.isTimestamp(dataType)) { return new Timestamp(); } From 8f6dd04751f164e420276e2704a517a2d74662a2 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Fri, 11 Aug 2023 12:16:36 +0100 Subject: [PATCH 6/9] bigintToNumber before comparison --- src/scalar/int16.ts | 4 +++- src/scalar/int32.ts | 4 +++- src/scalar/int64.ts | 3 ++- src/scalar/uint16.ts | 4 +++- src/scalar/uint32.ts | 4 +++- src/scalar/uint64.ts | 3 ++- 6 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/scalar/int16.ts b/src/scalar/int16.ts index 120fdbb..b5d4557 100644 --- a/src/scalar/int16.ts +++ b/src/scalar/int16.ts @@ -2,6 +2,7 @@ import { DataType, Int16 as ArrowInt16 } from '@apache-arrow/esnext-esm'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; +import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Int16 implements Scalar { private _valid = false; @@ -67,6 +68,7 @@ export class Int16 implements Scalar { } validInt16(n: bigint) { - return Number.isSafeInteger(n) && n >= -32_768 && n <= 32_767; + const num = bigIntToNumber(n); + return Number.isSafeInteger(num) && num >= -32_768 && num <= 32_767; } } diff --git a/src/scalar/int32.ts b/src/scalar/int32.ts index 62e91f9..14ed020 100644 --- a/src/scalar/int32.ts +++ b/src/scalar/int32.ts @@ -2,6 +2,7 @@ import { DataType, Int32 as ArrowInt32 } from '@apache-arrow/esnext-esm'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; +import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Int32 implements Scalar { private _valid = false; @@ -67,6 +68,7 @@ export class Int32 implements Scalar { } validInt32(n: bigint) { - return Number.isSafeInteger(n) && n >= -2_147_483_648 && n <= 2_147_483_647; + const num = bigIntToNumber(n); + return Number.isSafeInteger(num) && num >= -2_147_483_648 && num <= 2_147_483_647; } } diff --git a/src/scalar/int64.ts b/src/scalar/int64.ts index c956081..0f5e37c 100644 --- a/src/scalar/int64.ts +++ b/src/scalar/int64.ts @@ -2,6 +2,7 @@ import { DataType, Int64 as ArrowInt64 } from '@apache-arrow/esnext-esm'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; +import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Int64 implements Scalar { private _valid = false; @@ -69,6 +70,6 @@ export class Int64 implements Scalar { validInt64(n: bigint) { const MIN_INT64 = BigInt('-9223372036854775808'); // -2^63 const MAX_INT64 = BigInt('9223372036854775807'); // 2^63 - 1 - return Number.isSafeInteger(n) && n >= MIN_INT64 && n <= MAX_INT64; + return Number.isSafeInteger(bigIntToNumber(n)) && n >= MIN_INT64 && n <= MAX_INT64; } } diff --git a/src/scalar/uint16.ts b/src/scalar/uint16.ts index 765f644..22e2f3d 100644 --- a/src/scalar/uint16.ts +++ b/src/scalar/uint16.ts @@ -2,6 +2,7 @@ import { DataType, Uint16 as ArrowUint16 } from '@apache-arrow/esnext-esm'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; +import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Uint16 implements Scalar { private _valid = false; @@ -67,6 +68,7 @@ export class Uint16 implements Scalar { } validUint16(n: bigint) { - return Number.isSafeInteger(n) && n >= 0 && n <= 65_535; + const num = bigIntToNumber(n); + return Number.isSafeInteger(num) && num >= 0 && num <= 65_535; } } diff --git a/src/scalar/uint32.ts b/src/scalar/uint32.ts index 600e9f2..4624e35 100644 --- a/src/scalar/uint32.ts +++ b/src/scalar/uint32.ts @@ -2,6 +2,7 @@ import { DataType, Uint32 as ArrowUint32 } from '@apache-arrow/esnext-esm'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; +import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Uint32 implements Scalar { private _valid = false; @@ -67,6 +68,7 @@ export class Uint32 implements Scalar { } validUint32(n: bigint) { - return Number.isSafeInteger(n) && n >= 0 && n <= 4_294_967_295; + const num = bigIntToNumber(n); + return Number.isSafeInteger(num) && num >= 0 && num <= 4_294_967_295; } } diff --git a/src/scalar/uint64.ts b/src/scalar/uint64.ts index 87be869..19ebad1 100644 --- a/src/scalar/uint64.ts +++ b/src/scalar/uint64.ts @@ -2,6 +2,7 @@ import { DataType, Uint64 as ArrowUint64 } from '@apache-arrow/esnext-esm'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; +import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Uint64 implements Scalar { private _valid = false; @@ -67,6 +68,6 @@ export class Uint64 implements Scalar { } validUint64(n: bigint) { - return Number.isSafeInteger(n) && n >= 0 && n <= 18_446_744_073_709_551_615n; + return Number.isSafeInteger(bigIntToNumber(n)) && n >= 0 && n <= 18_446_744_073_709_551_615n; } } From a2c22f3d3b72c6c454cb08355a817ef947ef8dbd Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Fri, 11 Aug 2023 12:18:29 +0100 Subject: [PATCH 7/9] fmt --- src/scalar/int16.ts | 6 +++--- src/scalar/int32.ts | 6 +++--- src/scalar/int64.ts | 2 +- src/scalar/uint16.ts | 6 +++--- src/scalar/uint32.ts | 6 +++--- src/scalar/uint64.ts | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/scalar/int16.ts b/src/scalar/int16.ts index b5d4557..ecb37a7 100644 --- a/src/scalar/int16.ts +++ b/src/scalar/int16.ts @@ -1,8 +1,8 @@ import { DataType, Int16 as ArrowInt16 } from '@apache-arrow/esnext-esm'; +import { bigIntToNumber } from '@apache-arrow/esnext-esm/util/bigint.js'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; -import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Int16 implements Scalar { private _valid = false; @@ -68,7 +68,7 @@ export class Int16 implements Scalar { } validInt16(n: bigint) { - const num = bigIntToNumber(n); - return Number.isSafeInteger(num) && num >= -32_768 && num <= 32_767; + const number_ = bigIntToNumber(n); + return Number.isSafeInteger(number_) && number_ >= -32_768 && number_ <= 32_767; } } diff --git a/src/scalar/int32.ts b/src/scalar/int32.ts index 14ed020..c998303 100644 --- a/src/scalar/int32.ts +++ b/src/scalar/int32.ts @@ -1,8 +1,8 @@ import { DataType, Int32 as ArrowInt32 } from '@apache-arrow/esnext-esm'; +import { bigIntToNumber } from '@apache-arrow/esnext-esm/util/bigint.js'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; -import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Int32 implements Scalar { private _valid = false; @@ -68,7 +68,7 @@ export class Int32 implements Scalar { } validInt32(n: bigint) { - const num = bigIntToNumber(n); - return Number.isSafeInteger(num) && num >= -2_147_483_648 && num <= 2_147_483_647; + const number_ = bigIntToNumber(n); + return Number.isSafeInteger(number_) && number_ >= -2_147_483_648 && number_ <= 2_147_483_647; } } diff --git a/src/scalar/int64.ts b/src/scalar/int64.ts index 0f5e37c..0f35041 100644 --- a/src/scalar/int64.ts +++ b/src/scalar/int64.ts @@ -1,8 +1,8 @@ import { DataType, Int64 as ArrowInt64 } from '@apache-arrow/esnext-esm'; +import { bigIntToNumber } from '@apache-arrow/esnext-esm/util/bigint.js'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; -import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Int64 implements Scalar { private _valid = false; diff --git a/src/scalar/uint16.ts b/src/scalar/uint16.ts index 22e2f3d..454b919 100644 --- a/src/scalar/uint16.ts +++ b/src/scalar/uint16.ts @@ -1,8 +1,8 @@ import { DataType, Uint16 as ArrowUint16 } from '@apache-arrow/esnext-esm'; +import { bigIntToNumber } from '@apache-arrow/esnext-esm/util/bigint.js'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; -import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Uint16 implements Scalar { private _valid = false; @@ -68,7 +68,7 @@ export class Uint16 implements Scalar { } validUint16(n: bigint) { - const num = bigIntToNumber(n); - return Number.isSafeInteger(num) && num >= 0 && num <= 65_535; + const number_ = bigIntToNumber(n); + return Number.isSafeInteger(number_) && number_ >= 0 && number_ <= 65_535; } } diff --git a/src/scalar/uint32.ts b/src/scalar/uint32.ts index 4624e35..cfa2335 100644 --- a/src/scalar/uint32.ts +++ b/src/scalar/uint32.ts @@ -1,8 +1,8 @@ import { DataType, Uint32 as ArrowUint32 } from '@apache-arrow/esnext-esm'; +import { bigIntToNumber } from '@apache-arrow/esnext-esm/util/bigint.js'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; -import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Uint32 implements Scalar { private _valid = false; @@ -68,7 +68,7 @@ export class Uint32 implements Scalar { } validUint32(n: bigint) { - const num = bigIntToNumber(n); - return Number.isSafeInteger(num) && num >= 0 && num <= 4_294_967_295; + const number_ = bigIntToNumber(n); + return Number.isSafeInteger(number_) && number_ >= 0 && number_ <= 4_294_967_295; } } diff --git a/src/scalar/uint64.ts b/src/scalar/uint64.ts index 19ebad1..0ec9b3d 100644 --- a/src/scalar/uint64.ts +++ b/src/scalar/uint64.ts @@ -1,8 +1,8 @@ import { DataType, Uint64 as ArrowUint64 } from '@apache-arrow/esnext-esm'; +import { bigIntToNumber } from '@apache-arrow/esnext-esm/util/bigint.js'; import { Scalar } from './scalar.js'; import { isInvalid, NULL_VALUE } from './util.js'; -import {bigIntToNumber} from "@apache-arrow/esnext-esm/util/bigint.js"; export class Uint64 implements Scalar { private _valid = false; From 1cbda29abe77104742a77d48adced20d5e6c478d Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Fri, 11 Aug 2023 13:16:28 +0100 Subject: [PATCH 8/9] Handle lists in newScalar --- src/scalar/list.test.ts | 20 ++++++++++---------- src/scalar/list.ts | 38 ++++++++++++++++++++++---------------- src/scalar/scalar.ts | 6 ++++++ 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/scalar/list.test.ts b/src/scalar/list.test.ts index 214f601..92d4703 100644 --- a/src/scalar/list.test.ts +++ b/src/scalar/list.test.ts @@ -4,39 +4,39 @@ import { Int64 } from './int64.js'; import { List } from './list.js'; test('list', (t) => { - const l = new List(Int64); - t.deepEqual(l, new List(Int64)); + const l = new List(new Int64()); + t.deepEqual(l, new List(new Int64())); l.value = [new Int64(17), new Int64(19), new Int64(null)]; t.is(l.length, 3); }); test('list equality', (t) => { - const l1 = new List(Int64); + const l1 = new List(new Int64()); l1.value = [new Int64(17), new Int64(19), new Int64(null)]; - const l2 = new List(Int64); + const l2 = new List(new Int64()); l2.value = [new Int64(17), new Int64(19), new Int64(null)]; t.deepEqual(l1, l2); }); test('list inequality', (t) => { - const l1 = new List(Int64); + const l1 = new List(new Int64()); l1.value = new Int64(4); - const l2 = new List(Int64); + const l2 = new List(new Int64()); l2.value = new Int64(7); t.notDeepEqual(l1, l2); }); test('list equality when invalid', (t) => { - const l1 = new List(Int64); - l1.value = new Int64(null); + const l1 = new List(new Int64()); + l1.value = new Int64(); - const l2 = new List(Int64); - l2.value = new Int64(null); + const l2 = new List(new Int64()); + l2.value = new Int64(); t.deepEqual(l1, l2); }); diff --git a/src/scalar/list.ts b/src/scalar/list.ts index f1c3f9e..86659df 100644 --- a/src/scalar/list.ts +++ b/src/scalar/list.ts @@ -6,17 +6,24 @@ import { isInvalid, NULL_VALUE } from './util.js'; type TVector> = T[]; export class List> implements Scalar> { - private _type: new (value?: unknown) => T; + private _childScalarInstance: T; private _valid = false; private _value: TVector = []; - constructor(scalarType: new (value?: unknown) => T, initialValue?: unknown) { - this._type = scalarType; - if (!isInvalid(initialValue)) this.value = initialValue; + constructor(childScalarInstance: T, initialValue?: TVector) { + this._childScalarInstance = childScalarInstance; + + if (!isInvalid(initialValue)) { + this._value = initialValue!.map((value) => { + const instance = Object.create(this._childScalarInstance); + instance.value = value; + return instance; + }); + } } get dataType(): DataType { - return new ArrowList(this._type.prototype.dataType); + return new ArrowList(this._childScalarInstance.dataType.ArrayType); } set value(inputValue: unknown) { @@ -30,23 +37,22 @@ export class List> implements Scalar> { const temporaryVector: TVector = []; if (inputArray.length > 0) { - const firstItemScalar = new this._type(); - firstItemScalar.value = inputArray[0]; - const firstItemType = Object.getPrototypeOf(firstItemScalar).constructor; + this._childScalarInstance.value = inputArray[0]; + const firstItemType = Object.getPrototypeOf(this._childScalarInstance).constructor; for (const item of inputArray) { - const scalar = new this._type(); - scalar.value = item; - - if (Object.getPrototypeOf(scalar).constructor !== firstItemType) { + try { + this._childScalarInstance.value = item; + } catch { throw new Error( - `Type mismatch: All items should be of the same type as the first item. Expected type ${ - firstItemType.name - }, but got ${Object.getPrototypeOf(scalar).constructor.name}`, + `Type mismatch: All items should be of the same type as the first item. Expected type ${firstItemType.name}`, ); } - temporaryVector.push(scalar); + // Here, instead of creating a new scalar, we clone the existing instance with the current value + const scalarClone = Object.create(this._childScalarInstance); + scalarClone.value = item; + temporaryVector.push(scalarClone); } this._value = temporaryVector; diff --git a/src/scalar/scalar.ts b/src/scalar/scalar.ts index 89b3241..f9720fd 100644 --- a/src/scalar/scalar.ts +++ b/src/scalar/scalar.ts @@ -6,6 +6,7 @@ import { Float64 } from './float64.js'; import { Int16 } from './int16.js'; import { Int32 } from './int32.js'; import { Int64 } from './int64.js'; +import { List } from './list.js'; import { Text } from './text.js'; import { Timestamp } from './timestamp.js'; import { Uint16 } from './uint16.js'; @@ -73,5 +74,10 @@ export const newScalar = (dataType: DataType): Scalar => { return new Timestamp(); } + if (DataType.isList(dataType)) { + const childScalar = newScalar(dataType.valueType); + return new List(childScalar); + } + return new Text(); }; From 9c9477d645790105d9270323c0072eeece1ea3c6 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Fri, 11 Aug 2023 15:25:34 +0100 Subject: [PATCH 9/9] Add date --- src/scalar/date.ts | 68 ++++++++++++++++++++++++++++++++++++++++++++ src/scalar/scalar.ts | 5 ++++ 2 files changed, 73 insertions(+) create mode 100644 src/scalar/date.ts diff --git a/src/scalar/date.ts b/src/scalar/date.ts new file mode 100644 index 0000000..d55df73 --- /dev/null +++ b/src/scalar/date.ts @@ -0,0 +1,68 @@ +import { DataType, Date_ as ArrowDate, DateUnit } from '@apache-arrow/esnext-esm'; +import { DateTime } from 'luxon'; + +import { Scalar } from './scalar.js'; +import { isInvalid, NULL_VALUE } from './util.js'; + +export class Date implements Scalar { + private _valid = false; + private _value: DateTime = DateTime.fromMillis(0); + private _unit: DateUnit; + + public constructor(unit: DateUnit, v?: unknown) { + this._unit = unit; + this.value = v; + return this; + } + + public get dataType(): DataType { + return new ArrowDate(this._unit); + } + + public get valid(): boolean { + return this._valid; + } + + public get value(): DateTime { + return this._value; + } + + public set value(value: unknown) { + if (isInvalid(value)) { + this._valid = false; + return; + } + + if (value instanceof Date && value.dataType === this.dataType) { + this._valid = value.valid; + this._value = value.value; + return; + } + + let dateValue: DateTime | null = null; + + if (typeof value === 'string') { + dateValue = DateTime.fromISO(value, { setZone: true }); + + if (!dateValue.isValid) { + dateValue = DateTime.fromFormat(value, 'yyyy-MM-dd', { zone: 'utc' }); + } + } + + if (dateValue && dateValue.isValid) { + this._value = dateValue; + this._valid = true; + return; + } + + throw new Error(`Unable to set '${value}' as Date`); + } + + public toString(): string { + if (this._valid) { + return this._value.toISO()!; + } + + return NULL_VALUE; + } +} diff --git a/src/scalar/scalar.ts b/src/scalar/scalar.ts index f9720fd..f7a908a 100644 --- a/src/scalar/scalar.ts +++ b/src/scalar/scalar.ts @@ -1,6 +1,7 @@ import { DataType, Precision } from '@apache-arrow/esnext-esm'; import { Bool } from './bool.js'; +import { Date } from './date.js'; import { Float32 } from './float32.js'; import { Float64 } from './float64.js'; import { Int16 } from './int16.js'; @@ -79,5 +80,9 @@ export const newScalar = (dataType: DataType): Scalar => { return new List(childScalar); } + if (DataType.isDate(dataType)) { + return new Date(dataType.unit); + } + return new Text(); };