mirror of
https://github.com/enso-org/enso.git
synced 2024-11-26 08:52:58 +03:00
Arrow builder is not an Array (#9358)
Follow up on #9150 - making sure that Arrow builder is not accidentally treated as an Array by disallowing reading elements. # Important Notes Also making sure that the length of the resulting Arrow Array is consistent with what user requested.
This commit is contained in:
parent
2322b40a22
commit
f82e8020fe
@ -14,6 +14,7 @@ import com.oracle.truffle.api.library.CachedLibrary;
|
|||||||
import com.oracle.truffle.api.library.ExportLibrary;
|
import com.oracle.truffle.api.library.ExportLibrary;
|
||||||
import com.oracle.truffle.api.library.ExportMessage;
|
import com.oracle.truffle.api.library.ExportMessage;
|
||||||
import org.enso.interpreter.arrow.LogicalLayout;
|
import org.enso.interpreter.arrow.LogicalLayout;
|
||||||
|
import org.graalvm.collections.Pair;
|
||||||
|
|
||||||
@ExportLibrary(InteropLibrary.class)
|
@ExportLibrary(InteropLibrary.class)
|
||||||
public class ArrowCastToFixedSizeArrayFactory implements TruffleObject {
|
public class ArrowCastToFixedSizeArrayFactory implements TruffleObject {
|
||||||
@ -43,7 +44,8 @@ public class ArrowCastToFixedSizeArrayFactory implements TruffleObject {
|
|||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
||||||
var unit = LogicalLayout.Date32;
|
var unit = LogicalLayout.Date32;
|
||||||
return new ArrowFixedArrayDate(pointer(args, iop, unit), unit);
|
var pair = pointer(args, iop, unit);
|
||||||
|
return new ArrowFixedArrayDate(pair.getLeft(), pair.getRight(), unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getLayout() == Date64")
|
@Specialization(guards = "receiver.getLayout() == Date64")
|
||||||
@ -53,7 +55,8 @@ public class ArrowCastToFixedSizeArrayFactory implements TruffleObject {
|
|||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
||||||
var unit = LogicalLayout.Date64;
|
var unit = LogicalLayout.Date64;
|
||||||
return new ArrowFixedArrayDate(pointer(args, iop, unit), unit);
|
var pair = pointer(args, iop, unit);
|
||||||
|
return new ArrowFixedArrayDate(pair.getLeft(), pair.getRight(), unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getLayout() == Int8")
|
@Specialization(guards = "receiver.getLayout() == Int8")
|
||||||
@ -63,7 +66,8 @@ public class ArrowCastToFixedSizeArrayFactory implements TruffleObject {
|
|||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
||||||
var unit = LogicalLayout.Int8;
|
var unit = LogicalLayout.Int8;
|
||||||
return new ArrowFixedArrayInt(pointer(args, iop, unit), unit);
|
var pair = pointer(args, iop, unit);
|
||||||
|
return new ArrowFixedArrayInt(pair.getLeft(), pair.getRight(), unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getLayout() == Int16")
|
@Specialization(guards = "receiver.getLayout() == Int16")
|
||||||
@ -73,7 +77,8 @@ public class ArrowCastToFixedSizeArrayFactory implements TruffleObject {
|
|||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
||||||
var unit = LogicalLayout.Int16;
|
var unit = LogicalLayout.Int16;
|
||||||
return new ArrowFixedArrayInt(pointer(args, iop, unit), unit);
|
var pair = pointer(args, iop, unit);
|
||||||
|
return new ArrowFixedArrayInt(pair.getLeft(), pair.getRight(), unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getLayout() == Int32")
|
@Specialization(guards = "receiver.getLayout() == Int32")
|
||||||
@ -83,7 +88,8 @@ public class ArrowCastToFixedSizeArrayFactory implements TruffleObject {
|
|||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
||||||
var unit = LogicalLayout.Int32;
|
var unit = LogicalLayout.Int32;
|
||||||
return new ArrowFixedArrayInt(pointer(args, iop, unit), unit);
|
var pair = pointer(args, iop, unit);
|
||||||
|
return new ArrowFixedArrayInt(pair.getLeft(), pair.getRight(), unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getLayout() == Int64")
|
@Specialization(guards = "receiver.getLayout() == Int64")
|
||||||
@ -93,11 +99,13 @@ public class ArrowCastToFixedSizeArrayFactory implements TruffleObject {
|
|||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
||||||
var unit = LogicalLayout.Int64;
|
var unit = LogicalLayout.Int64;
|
||||||
return new ArrowFixedArrayInt(pointer(args, iop, unit), unit);
|
var pair = pointer(args, iop, unit);
|
||||||
|
return new ArrowFixedArrayInt(pair.getLeft(), pair.getRight(), unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
private static ByteBufferDirect pointer(Object[] args, InteropLibrary interop, SizeInBytes unit)
|
private static Pair<ByteBufferDirect, Integer> pointer(
|
||||||
|
Object[] args, InteropLibrary interop, SizeInBytes unit)
|
||||||
throws ArityException, UnsupportedTypeException, UnsupportedMessageException {
|
throws ArityException, UnsupportedTypeException, UnsupportedMessageException {
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
throw ArityException.create(2, 3, args.length);
|
throw ArityException.create(2, 3, args.length);
|
||||||
@ -117,10 +125,13 @@ public class ArrowCastToFixedSizeArrayFactory implements TruffleObject {
|
|||||||
throw UnsupportedTypeException.create(
|
throw UnsupportedTypeException.create(
|
||||||
new Object[] {args[2]}, "Address of non-null bitmap is invalid");
|
new Object[] {args[2]}, "Address of non-null bitmap is invalid");
|
||||||
}
|
}
|
||||||
return ByteBufferDirect.fromAddress(
|
return Pair.create(
|
||||||
interop.asLong(args[0]), interop.asLong(args[2]), capacity, unit);
|
ByteBufferDirect.fromAddress(
|
||||||
|
interop.asLong(args[0]), interop.asLong(args[2]), capacity, unit),
|
||||||
|
capacity);
|
||||||
} else {
|
} else {
|
||||||
return ByteBufferDirect.fromAddress(interop.asLong(args[0]), capacity, unit);
|
return Pair.create(
|
||||||
|
ByteBufferDirect.fromAddress(interop.asLong(args[0]), capacity, unit), capacity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,9 +27,8 @@ public final class ArrowFixedArrayDate implements TruffleObject {
|
|||||||
this.buffer = ByteBufferDirect.forSize(size, unit);
|
this.buffer = ByteBufferDirect.forSize(size, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrowFixedArrayDate(ByteBufferDirect buffer, LogicalLayout unit)
|
public ArrowFixedArrayDate(ByteBufferDirect buffer, int size, LogicalLayout unit) {
|
||||||
throws UnsupportedMessageException {
|
this.size = size;
|
||||||
this.size = buffer.capacity() / unit.sizeInBytes();
|
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
}
|
}
|
||||||
@ -164,7 +163,7 @@ public final class ArrowFixedArrayDate implements TruffleObject {
|
|||||||
|
|
||||||
static final ZoneId UTC = ZoneId.of("UTC");
|
static final ZoneId UTC = ZoneId.of("UTC");
|
||||||
|
|
||||||
static int typeAdjustedIndex(long index, int daySizeInBytes) {
|
public static int typeAdjustedIndex(long index, int daySizeInBytes) {
|
||||||
return Math.toIntExact(index * daySizeInBytes);
|
return Math.toIntExact(index * daySizeInBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,8 @@ public final class ArrowFixedArrayInt implements TruffleObject {
|
|||||||
private final ByteBufferDirect buffer;
|
private final ByteBufferDirect buffer;
|
||||||
private final LogicalLayout unit;
|
private final LogicalLayout unit;
|
||||||
|
|
||||||
public ArrowFixedArrayInt(ByteBufferDirect buffer, LogicalLayout unit)
|
public ArrowFixedArrayInt(ByteBufferDirect buffer, int size, LogicalLayout unit) {
|
||||||
throws UnsupportedMessageException {
|
this.size = size;
|
||||||
this.size = buffer.capacity() / unit.sizeInBytes();
|
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
package org.enso.interpreter.arrow.runtime;
|
package org.enso.interpreter.arrow.runtime;
|
||||||
|
|
||||||
import com.oracle.truffle.api.CompilerDirectives;
|
|
||||||
import com.oracle.truffle.api.dsl.Cached;
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
import com.oracle.truffle.api.dsl.Fallback;
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
import com.oracle.truffle.api.dsl.ImportStatic;
|
import com.oracle.truffle.api.interop.TruffleObject;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.interop.UnknownIdentifierException;
|
||||||
import com.oracle.truffle.api.interop.*;
|
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||||
import com.oracle.truffle.api.library.CachedLibrary;
|
import com.oracle.truffle.api.interop.UnsupportedTypeException;
|
||||||
import com.oracle.truffle.api.library.ExportLibrary;
|
import com.oracle.truffle.api.library.ExportLibrary;
|
||||||
import com.oracle.truffle.api.library.ExportMessage;
|
import com.oracle.truffle.api.library.ExportMessage;
|
||||||
import java.time.*;
|
|
||||||
import org.enso.interpreter.arrow.LogicalLayout;
|
import org.enso.interpreter.arrow.LogicalLayout;
|
||||||
|
|
||||||
@ExportLibrary(InteropLibrary.class)
|
@ExportLibrary(InteropLibrary.class)
|
||||||
@ -18,9 +16,11 @@ public final class ArrowFixedSizeArrayBuilder implements TruffleObject {
|
|||||||
private final LogicalLayout unit;
|
private final LogicalLayout unit;
|
||||||
private final int size;
|
private final int size;
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
private boolean sealed;
|
private boolean sealed;
|
||||||
|
|
||||||
|
private static final String APPEND_OP = "append";
|
||||||
|
private static final String BUILD_OP = "build";
|
||||||
|
|
||||||
public ArrowFixedSizeArrayBuilder(int size, LogicalLayout unit) {
|
public ArrowFixedSizeArrayBuilder(int size, LogicalLayout unit) {
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
@ -33,9 +33,16 @@ public final class ArrowFixedSizeArrayBuilder implements TruffleObject {
|
|||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExportMessage
|
public boolean isSealed() {
|
||||||
public boolean hasArrayElements() {
|
return sealed;
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
public ByteBufferDirect getBuffer() {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExportMessage
|
@ExportMessage
|
||||||
@ -46,8 +53,8 @@ public final class ArrowFixedSizeArrayBuilder implements TruffleObject {
|
|||||||
@ExportMessage
|
@ExportMessage
|
||||||
public boolean isMemberInvocable(String member) {
|
public boolean isMemberInvocable(String member) {
|
||||||
return switch (member) {
|
return switch (member) {
|
||||||
case "append" -> !this.sealed;
|
case APPEND_OP -> !this.sealed;
|
||||||
case "build" -> true;
|
case BUILD_OP -> true;
|
||||||
default -> false;
|
default -> false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -61,25 +68,22 @@ public final class ArrowFixedSizeArrayBuilder implements TruffleObject {
|
|||||||
Object invokeMember(
|
Object invokeMember(
|
||||||
String name,
|
String name,
|
||||||
Object[] args,
|
Object[] args,
|
||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
@Cached(value = "buildWriterOrNull(name)", neverDefault = true)
|
||||||
|
WriteToBuilderNode writeToBuilderNode)
|
||||||
throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
|
throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "build":
|
case BUILD_OP:
|
||||||
sealed = true;
|
sealed = true;
|
||||||
return switch (unit) {
|
return switch (unit) {
|
||||||
case Date32, Date64 -> new ArrowFixedArrayDate(buffer, unit);
|
case Date32, Date64 -> new ArrowFixedArrayDate(buffer, size, unit);
|
||||||
case Int8, Int16, Int32, Int64 -> new ArrowFixedArrayInt(buffer, unit);
|
case Int8, Int16, Int32, Int64 -> new ArrowFixedArrayInt(buffer, size, unit);
|
||||||
};
|
};
|
||||||
case "append":
|
case APPEND_OP:
|
||||||
if (sealed) {
|
if (sealed) {
|
||||||
throw UnsupportedMessageException.create();
|
throw UnsupportedMessageException.create();
|
||||||
}
|
}
|
||||||
var current = index;
|
var current = index;
|
||||||
try {
|
writeToBuilderNode.executeWrite(this, current, args[0]);
|
||||||
iop.writeArrayElement(this, current, args[0]);
|
|
||||||
} catch (InvalidArrayIndexException e) {
|
|
||||||
throw UnsupportedMessageException.create(e);
|
|
||||||
}
|
|
||||||
index += 1;
|
index += 1;
|
||||||
return NullValue.get();
|
return NullValue.get();
|
||||||
default:
|
default:
|
||||||
@ -87,242 +91,7 @@ public final class ArrowFixedSizeArrayBuilder implements TruffleObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExportMessage
|
static WriteToBuilderNode buildWriterOrNull(String op) {
|
||||||
@ImportStatic(LogicalLayout.class)
|
return APPEND_OP.equals(op) ? WriteToBuilderNode.build() : WriteToBuilderNodeGen.getUncached();
|
||||||
static class ReadArrayElement {
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Date32")
|
|
||||||
static Object doDay(ArrowFixedSizeArrayBuilder receiver, long index)
|
|
||||||
throws UnsupportedMessageException {
|
|
||||||
return ArrowFixedArrayDate.readDay(receiver.buffer, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Date64")
|
|
||||||
static Object doMilliseconds(ArrowFixedSizeArrayBuilder receiver, long index)
|
|
||||||
throws UnsupportedMessageException {
|
|
||||||
return ArrowFixedArrayDate.readMilliseconds(receiver.buffer, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Int8")
|
|
||||||
public static Object doByte(ArrowFixedSizeArrayBuilder receiver, long index)
|
|
||||||
throws UnsupportedMessageException, InvalidArrayIndexException {
|
|
||||||
var at =
|
|
||||||
ArrowFixedArrayInt.adjustedIndex(receiver.buffer, receiver.unit, receiver.size, index);
|
|
||||||
if (receiver.buffer.isNull((int) index)) {
|
|
||||||
return NullValue.get();
|
|
||||||
}
|
|
||||||
return receiver.buffer.get(at);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Int16")
|
|
||||||
public static Object doShort(ArrowFixedSizeArrayBuilder receiver, long index)
|
|
||||||
throws UnsupportedMessageException, InvalidArrayIndexException {
|
|
||||||
var at =
|
|
||||||
ArrowFixedArrayInt.adjustedIndex(receiver.buffer, receiver.unit, receiver.size, index);
|
|
||||||
if (receiver.buffer.isNull((int) index)) {
|
|
||||||
return NullValue.get();
|
|
||||||
}
|
|
||||||
return receiver.buffer.getShort(at);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Int32")
|
|
||||||
public static Object doInt(ArrowFixedSizeArrayBuilder receiver, long index)
|
|
||||||
throws UnsupportedMessageException, InvalidArrayIndexException {
|
|
||||||
var at =
|
|
||||||
ArrowFixedArrayInt.adjustedIndex(receiver.buffer, receiver.unit, receiver.size, index);
|
|
||||||
if (receiver.buffer.isNull((int) index)) {
|
|
||||||
return NullValue.get();
|
|
||||||
}
|
|
||||||
return receiver.buffer.getInt(at);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Int64")
|
|
||||||
public static Object doLong(ArrowFixedSizeArrayBuilder receiver, long index)
|
|
||||||
throws UnsupportedMessageException, InvalidArrayIndexException {
|
|
||||||
var at =
|
|
||||||
ArrowFixedArrayInt.adjustedIndex(receiver.buffer, receiver.unit, receiver.size, index);
|
|
||||||
if (receiver.buffer.isNull((int) index)) {
|
|
||||||
return NullValue.get();
|
|
||||||
}
|
|
||||||
return receiver.buffer.getLong(at);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExportMessage
|
|
||||||
@ImportStatic(LogicalLayout.class)
|
|
||||||
static class WriteArrayElement {
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Date32")
|
|
||||||
static void doDay(
|
|
||||||
ArrowFixedSizeArrayBuilder receiver,
|
|
||||||
long index,
|
|
||||||
Object value,
|
|
||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
|
||||||
throws UnsupportedMessageException, UnsupportedTypeException {
|
|
||||||
if (receiver.sealed) {
|
|
||||||
throw UnsupportedMessageException.create();
|
|
||||||
}
|
|
||||||
if (!iop.isDate(value)) {
|
|
||||||
throw UnsupportedTypeException.create(new Object[] {value}, "value is not a date");
|
|
||||||
}
|
|
||||||
var at = ArrowFixedArrayDate.typeAdjustedIndex(index, 4);
|
|
||||||
var time = iop.asDate(value).toEpochDay();
|
|
||||||
receiver.buffer.putInt(at, Math.toIntExact(time));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = {"receiver.getUnit() == Date64", "!iop.isNull(value)"})
|
|
||||||
static void doMilliseconds(
|
|
||||||
ArrowFixedSizeArrayBuilder receiver,
|
|
||||||
long index,
|
|
||||||
Object value,
|
|
||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
|
||||||
throws UnsupportedMessageException, UnsupportedTypeException {
|
|
||||||
if (receiver.sealed) {
|
|
||||||
throw UnsupportedMessageException.create();
|
|
||||||
}
|
|
||||||
if (!iop.isDate(value) || !iop.isTime(value)) {
|
|
||||||
throw UnsupportedTypeException.create(
|
|
||||||
new Object[] {value}, "value is not a date and a time");
|
|
||||||
}
|
|
||||||
|
|
||||||
var at = ArrowFixedArrayDate.typeAdjustedIndex(index, 8);
|
|
||||||
if (iop.isTimeZone(value)) {
|
|
||||||
var zoneDateTimeInstant =
|
|
||||||
instantForZone(
|
|
||||||
iop.asDate(value),
|
|
||||||
iop.asTime(value),
|
|
||||||
iop.asTimeZone(value),
|
|
||||||
ArrowFixedArrayDate.UTC);
|
|
||||||
var secondsPlusNano =
|
|
||||||
zoneDateTimeInstant.getEpochSecond() * ArrowFixedArrayDate.NANO_DIV
|
|
||||||
+ zoneDateTimeInstant.getNano();
|
|
||||||
receiver.buffer.putLong(at, secondsPlusNano);
|
|
||||||
} else {
|
|
||||||
var dateTime = instantForOffset(iop.asDate(value), iop.asTime(value), ZoneOffset.UTC);
|
|
||||||
var secondsPlusNano =
|
|
||||||
dateTime.getEpochSecond() * ArrowFixedArrayDate.NANO_DIV + dateTime.getNano();
|
|
||||||
receiver.buffer.putLong(at, secondsPlusNano);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@CompilerDirectives.TruffleBoundary
|
|
||||||
private static Instant instantForZone(
|
|
||||||
LocalDate date, LocalTime time, ZoneId zone, ZoneId target) {
|
|
||||||
return date.atTime(time).atZone(zone).withZoneSameLocal(target).toInstant();
|
|
||||||
}
|
|
||||||
|
|
||||||
@CompilerDirectives.TruffleBoundary
|
|
||||||
private static Instant instantForOffset(LocalDate date, LocalTime time, ZoneOffset offset) {
|
|
||||||
return date.atTime(time).toInstant(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "iop.isNull(value)")
|
|
||||||
static void doNull(
|
|
||||||
ArrowFixedSizeArrayBuilder receiver,
|
|
||||||
long index,
|
|
||||||
Object value,
|
|
||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
|
||||||
throws UnsupportedMessageException {
|
|
||||||
if (receiver.sealed) {
|
|
||||||
throw UnsupportedMessageException.create();
|
|
||||||
}
|
|
||||||
receiver.buffer.setNull((int) index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Int8")
|
|
||||||
public static void doByte(
|
|
||||||
ArrowFixedSizeArrayBuilder receiver,
|
|
||||||
long index,
|
|
||||||
Object value,
|
|
||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
|
||||||
throws UnsupportedMessageException, InvalidArrayIndexException, UnsupportedTypeException {
|
|
||||||
validAccess(receiver, index);
|
|
||||||
if (!iop.fitsInByte(value)) {
|
|
||||||
throw UnsupportedTypeException.create(new Object[] {value}, "value does not fit a byte");
|
|
||||||
}
|
|
||||||
receiver.buffer.put(typeAdjustedIndex(index, receiver.unit), (iop.asByte(value)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Int16")
|
|
||||||
public static void doShort(
|
|
||||||
ArrowFixedSizeArrayBuilder receiver,
|
|
||||||
long index,
|
|
||||||
Object value,
|
|
||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
|
||||||
throws UnsupportedMessageException, InvalidArrayIndexException, UnsupportedTypeException {
|
|
||||||
validAccess(receiver, index);
|
|
||||||
if (!iop.fitsInShort(value)) {
|
|
||||||
throw UnsupportedTypeException.create(
|
|
||||||
new Object[] {value}, "value does not fit a 2 byte short");
|
|
||||||
}
|
|
||||||
receiver.buffer.putShort(typeAdjustedIndex(index, receiver.unit), (iop.asShort(value)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Int32")
|
|
||||||
public static void doInt(
|
|
||||||
ArrowFixedSizeArrayBuilder receiver,
|
|
||||||
long index,
|
|
||||||
int value,
|
|
||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
|
||||||
throws UnsupportedMessageException, InvalidArrayIndexException, UnsupportedTypeException {
|
|
||||||
validAccess(receiver, index);
|
|
||||||
if (!iop.fitsInInt(value)) {
|
|
||||||
throw UnsupportedTypeException.create(
|
|
||||||
new Object[] {value}, "value does not fit a 4 byte int");
|
|
||||||
}
|
|
||||||
receiver.buffer.putInt(typeAdjustedIndex(index, receiver.unit), (iop.asInt(value)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Specialization(guards = "receiver.getUnit() == Int64")
|
|
||||||
public static void doLong(ArrowFixedSizeArrayBuilder receiver, long index, long value)
|
|
||||||
throws UnsupportedMessageException, InvalidArrayIndexException {
|
|
||||||
validAccess(receiver, index);
|
|
||||||
receiver.buffer.putLong(typeAdjustedIndex(index, receiver.unit), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Fallback
|
|
||||||
public static void doOther(
|
|
||||||
ArrowFixedSizeArrayBuilder receiver,
|
|
||||||
long index,
|
|
||||||
Object value,
|
|
||||||
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
|
||||||
throws UnsupportedTypeException {
|
|
||||||
throw UnsupportedTypeException.create(
|
|
||||||
new Object[] {index, value}, "unknown type of receiver");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void validAccess(ArrowFixedSizeArrayBuilder receiver, long index)
|
|
||||||
throws InvalidArrayIndexException, UnsupportedMessageException {
|
|
||||||
if (receiver.sealed) {
|
|
||||||
throw UnsupportedMessageException.create();
|
|
||||||
}
|
|
||||||
if (index >= receiver.size || index < 0) {
|
|
||||||
throw InvalidArrayIndexException.create(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExportMessage
|
|
||||||
long getArraySize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExportMessage
|
|
||||||
boolean isArrayElementReadable(long index) {
|
|
||||||
return index >= 0 && index < size && !buffer.isNull((int) index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExportMessage
|
|
||||||
boolean isArrayElementModifiable(long index) {
|
|
||||||
return !sealed && index >= 0 && index < size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExportMessage
|
|
||||||
boolean isArrayElementInsertable(long index) {
|
|
||||||
return !sealed && index >= 0 && index < size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int typeAdjustedIndex(long index, SizeInBytes unit) {
|
|
||||||
return ArrowFixedArrayDate.typeAdjustedIndex(index, unit.sizeInBytes());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ final class ByteBufferDirect implements AutoCloseable {
|
|||||||
private ByteBufferDirect(int valueCount, SizeInBytes unit) {
|
private ByteBufferDirect(int valueCount, SizeInBytes unit) {
|
||||||
var padded = RoundingUtil.forValueCount(valueCount, unit);
|
var padded = RoundingUtil.forValueCount(valueCount, unit);
|
||||||
var buffer = ByteBuffer.allocate(padded.getTotalSizeInBytes());
|
var buffer = ByteBuffer.allocate(padded.getTotalSizeInBytes());
|
||||||
|
|
||||||
this.allocated = buffer;
|
this.allocated = buffer;
|
||||||
this.dataBuffer = buffer.slice(0, padded.getDataBufferSizeInBytes());
|
this.dataBuffer = buffer.slice(0, padded.getDataBufferSizeInBytes());
|
||||||
this.bitmapBuffer = buffer.slice(dataBuffer.capacity(), padded.getValidityBitmapSizeInBytes());
|
this.bitmapBuffer = buffer.slice(dataBuffer.capacity(), padded.getValidityBitmapSizeInBytes());
|
||||||
@ -129,7 +130,7 @@ final class ByteBufferDirect implements AutoCloseable {
|
|||||||
return dataBuffer.getInt(index);
|
return dataBuffer.getInt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putInt(int index, int value) throws UnsupportedMessageException {
|
public void putInt(int index, int value) {
|
||||||
setValidityBitmap(index, 4);
|
setValidityBitmap(index, 4);
|
||||||
dataBuffer.putInt(index, value);
|
dataBuffer.putInt(index, value);
|
||||||
}
|
}
|
||||||
@ -143,7 +144,7 @@ final class ByteBufferDirect implements AutoCloseable {
|
|||||||
return dataBuffer.getLong(index);
|
return dataBuffer.getLong(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putLong(int index, long value) throws UnsupportedMessageException {
|
public void putLong(int index, long value) {
|
||||||
setValidityBitmap(index, 8);
|
setValidityBitmap(index, 8);
|
||||||
dataBuffer.putLong(index, value);
|
dataBuffer.putLong(index, value);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,217 @@
|
|||||||
|
package org.enso.interpreter.arrow.runtime;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.dsl.*;
|
||||||
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
|
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||||
|
import com.oracle.truffle.api.interop.UnsupportedTypeException;
|
||||||
|
import com.oracle.truffle.api.library.CachedLibrary;
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import org.enso.interpreter.arrow.LogicalLayout;
|
||||||
|
|
||||||
|
@ImportStatic(LogicalLayout.class)
|
||||||
|
@GenerateUncached
|
||||||
|
@GenerateInline(value = false)
|
||||||
|
abstract class WriteToBuilderNode extends Node {
|
||||||
|
|
||||||
|
public abstract void executeWrite(ArrowFixedSizeArrayBuilder receiver, long index, Object value)
|
||||||
|
throws UnsupportedTypeException;
|
||||||
|
|
||||||
|
@NeverDefault
|
||||||
|
static WriteToBuilderNode build() {
|
||||||
|
return WriteToBuilderNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = "receiver.getUnit() == Date32")
|
||||||
|
void doWriteDay(
|
||||||
|
ArrowFixedSizeArrayBuilder receiver,
|
||||||
|
long index,
|
||||||
|
Object value,
|
||||||
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
|
throws UnsupportedTypeException {
|
||||||
|
validAccess(receiver, index);
|
||||||
|
if (iop.isNull(value)) {
|
||||||
|
receiver.getBuffer().setNull((int) index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!iop.isDate(value)) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {value}, "value is not a date");
|
||||||
|
}
|
||||||
|
var at = ArrowFixedArrayDate.typeAdjustedIndex(index, 4);
|
||||||
|
long time;
|
||||||
|
try {
|
||||||
|
time = iop.asDate(value).toEpochDay();
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {value}, "value is not a date");
|
||||||
|
}
|
||||||
|
receiver.getBuffer().putInt(at, Math.toIntExact(time));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = {"receiver.getUnit() == Date64"})
|
||||||
|
void doWriteMilliseconds(
|
||||||
|
ArrowFixedSizeArrayBuilder receiver,
|
||||||
|
long index,
|
||||||
|
Object value,
|
||||||
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
|
throws UnsupportedTypeException {
|
||||||
|
validAccess(receiver, index);
|
||||||
|
if (iop.isNull(value)) {
|
||||||
|
receiver.getBuffer().setNull((int) index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!iop.isDate(value) || !iop.isTime(value)) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {value}, "value is not a date and a time");
|
||||||
|
}
|
||||||
|
|
||||||
|
var at = ArrowFixedArrayDate.typeAdjustedIndex(index, 8);
|
||||||
|
if (iop.isTimeZone(value)) {
|
||||||
|
Instant zoneDateTimeInstant;
|
||||||
|
try {
|
||||||
|
zoneDateTimeInstant =
|
||||||
|
instantForZone(
|
||||||
|
iop.asDate(value),
|
||||||
|
iop.asTime(value),
|
||||||
|
iop.asTimeZone(value),
|
||||||
|
ArrowFixedArrayDate.UTC);
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {value}, "value is not a date");
|
||||||
|
}
|
||||||
|
var secondsPlusNano =
|
||||||
|
zoneDateTimeInstant.getEpochSecond() * ArrowFixedArrayDate.NANO_DIV
|
||||||
|
+ zoneDateTimeInstant.getNano();
|
||||||
|
receiver.getBuffer().putLong(at, secondsPlusNano);
|
||||||
|
} else {
|
||||||
|
Instant dateTime;
|
||||||
|
try {
|
||||||
|
dateTime = instantForOffset(iop.asDate(value), iop.asTime(value), ZoneOffset.UTC);
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {value}, "value is not a date");
|
||||||
|
}
|
||||||
|
var secondsPlusNano =
|
||||||
|
dateTime.getEpochSecond() * ArrowFixedArrayDate.NANO_DIV + dateTime.getNano();
|
||||||
|
receiver.getBuffer().putLong(at, secondsPlusNano);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
private static Instant instantForZone(
|
||||||
|
LocalDate date, LocalTime time, ZoneId zone, ZoneId target) {
|
||||||
|
return date.atTime(time).atZone(zone).withZoneSameLocal(target).toInstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
private static Instant instantForOffset(LocalDate date, LocalTime time, ZoneOffset offset) {
|
||||||
|
return date.atTime(time).toInstant(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = "receiver.getUnit() == Int8")
|
||||||
|
void doWriteByte(
|
||||||
|
ArrowFixedSizeArrayBuilder receiver,
|
||||||
|
long index,
|
||||||
|
Object value,
|
||||||
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
|
throws UnsupportedTypeException {
|
||||||
|
validAccess(receiver, index);
|
||||||
|
if (iop.isNull(value)) {
|
||||||
|
receiver.getBuffer().setNull((int) index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!iop.fitsInByte(value)) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {value}, "value does not fit a byte");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
receiver.getBuffer().put(typeAdjustedIndex(index, receiver.getUnit()), (iop.asByte(value)));
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {value}, "value is not a byte");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = "receiver.getUnit() == Int16")
|
||||||
|
void doWriteShort(
|
||||||
|
ArrowFixedSizeArrayBuilder receiver,
|
||||||
|
long index,
|
||||||
|
Object value,
|
||||||
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
|
throws UnsupportedTypeException {
|
||||||
|
validAccess(receiver, index);
|
||||||
|
if (iop.isNull(value)) {
|
||||||
|
receiver.getBuffer().setNull((int) index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!iop.fitsInShort(value)) {
|
||||||
|
throw UnsupportedTypeException.create(
|
||||||
|
new Object[] {value}, "value does not fit a 2 byte short");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
receiver
|
||||||
|
.getBuffer()
|
||||||
|
.putShort(typeAdjustedIndex(index, receiver.getUnit()), (iop.asShort(value)));
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {value}, "value is not a short");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = "receiver.getUnit() == Int32")
|
||||||
|
void doWriteInt(
|
||||||
|
ArrowFixedSizeArrayBuilder receiver,
|
||||||
|
long index,
|
||||||
|
int value,
|
||||||
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
|
throws UnsupportedTypeException {
|
||||||
|
validAccess(receiver, index);
|
||||||
|
if (iop.isNull(value)) {
|
||||||
|
receiver.getBuffer().setNull((int) index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!iop.fitsInInt(value)) {
|
||||||
|
throw UnsupportedTypeException.create(
|
||||||
|
new Object[] {value}, "value does not fit a 4 byte int");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
receiver.getBuffer().putInt(typeAdjustedIndex(index, receiver.getUnit()), (iop.asInt(value)));
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {value}, "value is not an int");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = "receiver.getUnit() == Int64")
|
||||||
|
public static void doWriteLong(
|
||||||
|
ArrowFixedSizeArrayBuilder receiver,
|
||||||
|
long index,
|
||||||
|
long value,
|
||||||
|
@Cached.Shared("interop") @CachedLibrary(limit = "1") InteropLibrary iop)
|
||||||
|
throws UnsupportedTypeException {
|
||||||
|
validAccess(receiver, index);
|
||||||
|
if (iop.isNull(value)) {
|
||||||
|
receiver.getBuffer().setNull((int) index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
receiver.getBuffer().putLong(typeAdjustedIndex(index, receiver.getUnit()), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Fallback
|
||||||
|
void doWriteOther(ArrowFixedSizeArrayBuilder receiver, long index, Object value)
|
||||||
|
throws UnsupportedTypeException {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {index, value}, "unknown type of receiver");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validAccess(ArrowFixedSizeArrayBuilder receiver, long index)
|
||||||
|
throws UnsupportedTypeException {
|
||||||
|
if (receiver.isSealed()) {
|
||||||
|
throw UnsupportedTypeException.create(
|
||||||
|
new Object[] {receiver}, "receiver is not an unsealed buffer");
|
||||||
|
}
|
||||||
|
if (index >= receiver.getSize() || index < 0) {
|
||||||
|
throw UnsupportedTypeException.create(new Object[] {index}, "index is out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int typeAdjustedIndex(long index, SizeInBytes unit) {
|
||||||
|
return ArrowFixedArrayDate.typeAdjustedIndex(index, unit.sizeInBytes());
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ import java.time.ZonedDateTime;
|
|||||||
import java.time.temporal.Temporal;
|
import java.time.temporal.Temporal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.logging.Formatter;
|
import java.util.logging.Formatter;
|
||||||
import java.util.logging.Handler;
|
import java.util.logging.Handler;
|
||||||
import java.util.logging.LogRecord;
|
import java.util.logging.LogRecord;
|
||||||
@ -55,11 +56,12 @@ public class VerifyArrowTest {
|
|||||||
assertNotNull("Arrow is available", arrow);
|
assertNotNull("Arrow is available", arrow);
|
||||||
var date32Constr = ctx.eval("arrow", "new[Date32]");
|
var date32Constr = ctx.eval("arrow", "new[Date32]");
|
||||||
|
|
||||||
Value date32ArrayBuilder = date32Constr.newInstance(10);
|
var arrLength = 10;
|
||||||
|
Value date32ArrayBuilder = date32Constr.newInstance(arrLength);
|
||||||
assertNotNull("allocated value should not be null", date32ArrayBuilder);
|
assertNotNull("allocated value should not be null", date32ArrayBuilder);
|
||||||
assertTrue("allocated value should be an array", date32ArrayBuilder.hasArrayElements());
|
assertTrue("allocated value should not be an array", !date32ArrayBuilder.hasArrayElements());
|
||||||
var startDate = LocalDate.now();
|
var startDate = LocalDate.now();
|
||||||
populateArrayWithConsecutiveDays(date32ArrayBuilder, startDate);
|
populateBuilderWithConsecutiveDays(date32ArrayBuilder, startDate, arrLength, Set.of());
|
||||||
Value date32Array = date32ArrayBuilder.invokeMember("build");
|
Value date32Array = date32ArrayBuilder.invokeMember("build");
|
||||||
var rawDayPlus2 = date32Array.getArrayElement(2);
|
var rawDayPlus2 = date32Array.getArrayElement(2);
|
||||||
var dayPlus2 = rawDayPlus2.asDate();
|
var dayPlus2 = rawDayPlus2.asDate();
|
||||||
@ -68,7 +70,7 @@ public class VerifyArrowTest {
|
|||||||
|
|
||||||
date32ArrayBuilder = date32Constr.newInstance(10);
|
date32ArrayBuilder = date32Constr.newInstance(10);
|
||||||
var startDateTime = ZonedDateTime.now();
|
var startDateTime = ZonedDateTime.now();
|
||||||
populateArrayWithConsecutiveDays(date32ArrayBuilder, startDateTime);
|
populateBuilderWithConsecutiveDays(date32ArrayBuilder, startDateTime, arrLength, Set.of());
|
||||||
date32Array = date32ArrayBuilder.invokeMember("build");
|
date32Array = date32ArrayBuilder.invokeMember("build");
|
||||||
rawDayPlus2 = date32Array.getArrayElement(2);
|
rawDayPlus2 = date32Array.getArrayElement(2);
|
||||||
assertFalse(rawDayPlus2.isTime());
|
assertFalse(rawDayPlus2.isTime());
|
||||||
@ -93,12 +95,13 @@ public class VerifyArrowTest {
|
|||||||
assertNotNull("Arrow is available", arrow);
|
assertNotNull("Arrow is available", arrow);
|
||||||
var date64Constr = ctx.eval("arrow", "new[Date64]");
|
var date64Constr = ctx.eval("arrow", "new[Date64]");
|
||||||
|
|
||||||
Value date64ArrayBuilder = date64Constr.newInstance(10);
|
var arrLength = 10;
|
||||||
|
Value date64ArrayBuilder = date64Constr.newInstance(arrLength);
|
||||||
assertNotNull("allocated value should not be null", date64ArrayBuilder);
|
assertNotNull("allocated value should not be null", date64ArrayBuilder);
|
||||||
assertTrue("allocated value should be an array", date64ArrayBuilder.hasArrayElements());
|
assertTrue("allocated value should not be an array", !date64ArrayBuilder.hasArrayElements());
|
||||||
var startDate = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
|
var startDate = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
|
||||||
var startDateZone = startDate.getZone();
|
var startDateZone = startDate.getZone();
|
||||||
populateArrayWithConsecutiveDays(date64ArrayBuilder, startDate);
|
populateBuilderWithConsecutiveDays(date64ArrayBuilder, startDate, arrLength, Set.of());
|
||||||
Value date64Array = date64ArrayBuilder.invokeMember("build");
|
Value date64Array = date64ArrayBuilder.invokeMember("build");
|
||||||
var rawZonedDateTime = date64Array.getArrayElement(2);
|
var rawZonedDateTime = date64Array.getArrayElement(2);
|
||||||
var dayPlus2 =
|
var dayPlus2 =
|
||||||
@ -111,9 +114,7 @@ public class VerifyArrowTest {
|
|||||||
var startDate2 = ZonedDateTime.parse("2023-11-01T02:00:01+01:00[Europe/Paris]");
|
var startDate2 = ZonedDateTime.parse("2023-11-01T02:00:01+01:00[Europe/Paris]");
|
||||||
var startDate2Zone = startDate2.getZone();
|
var startDate2Zone = startDate2.getZone();
|
||||||
var startDate2Pnf = ZonedDateTime.parse("2023-11-01T02:00:01-07:00[US/Pacific]");
|
var startDate2Pnf = ZonedDateTime.parse("2023-11-01T02:00:01-07:00[US/Pacific]");
|
||||||
populateArrayWithConsecutiveDays(date64ArrayBuilder, startDate2);
|
populateBuilderWithConsecutiveDays(date64ArrayBuilder, startDate2, arrLength, Set.of(5, 9));
|
||||||
date64ArrayBuilder.setArrayElement(5, null);
|
|
||||||
date64ArrayBuilder.setArrayElement(9, null);
|
|
||||||
assertTrue(date64ArrayBuilder.canInvokeMember("append"));
|
assertTrue(date64ArrayBuilder.canInvokeMember("append"));
|
||||||
date64Array = date64ArrayBuilder.invokeMember("build");
|
date64Array = date64ArrayBuilder.invokeMember("build");
|
||||||
rawZonedDateTime = date64Array.getArrayElement(2);
|
rawZonedDateTime = date64Array.getArrayElement(2);
|
||||||
@ -137,18 +138,19 @@ public class VerifyArrowTest {
|
|||||||
var int8Constr = ctx.eval("arrow", "new[Int8]");
|
var int8Constr = ctx.eval("arrow", "new[Int8]");
|
||||||
assertNotNull(int8Constr);
|
assertNotNull(int8Constr);
|
||||||
|
|
||||||
Value int8ArrayBuilder = int8Constr.newInstance(10);
|
var arrLength = 10;
|
||||||
|
Value int8ArrayBuilder = int8Constr.newInstance(arrLength);
|
||||||
assertNotNull(int8ArrayBuilder);
|
assertNotNull(int8ArrayBuilder);
|
||||||
populateIntArray(int8ArrayBuilder, (byte) 42, int8ArrayBuilder.getArraySize() - 1);
|
populateIntBuilder(int8ArrayBuilder, (byte) 42, arrLength - 1);
|
||||||
assertThrows(RuntimeException.class, () -> int8ArrayBuilder.setArrayElement(5, 300));
|
assertThrows(RuntimeException.class, () -> int8ArrayBuilder.setArrayElement(5, 300));
|
||||||
assertThrows(RuntimeException.class, () -> int8ArrayBuilder.invokeMember("append", 300));
|
assertThrows(RuntimeException.class, () -> int8ArrayBuilder.invokeMember("append", 300));
|
||||||
int8ArrayBuilder.setArrayElement(5, 4);
|
assertThrows(UnsupportedOperationException.class, () -> int8ArrayBuilder.getArrayElement(5));
|
||||||
var int8Array = int8ArrayBuilder.invokeMember("build");
|
var int8Array = int8ArrayBuilder.invokeMember("build");
|
||||||
var v = int8Array.getArrayElement(5);
|
var v = int8Array.getArrayElement(5);
|
||||||
assertEquals((byte) 4, v.asByte());
|
assertEquals((byte) 5, v.asByte());
|
||||||
assertThrows(UnsupportedOperationException.class, () -> int8Array.setArrayElement(5, 21));
|
assertThrows(UnsupportedOperationException.class, () -> int8Array.setArrayElement(5, 21));
|
||||||
v = int8Array.getArrayElement(5);
|
v = int8Array.getArrayElement(5);
|
||||||
assertEquals((byte) 4, v.asByte());
|
assertEquals((byte) 5, v.asByte());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -262,21 +264,18 @@ public class VerifyArrowTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateArrayWithConsecutiveDays(Value arr, Temporal startDate) {
|
private void populateBuilderWithConsecutiveDays(
|
||||||
var len = arr.getArraySize();
|
Value builder, Temporal startDate, int len, Set<Integer> skip) {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
arr.invokeMember("append", startDate.plus(2, java.time.temporal.ChronoUnit.DAYS));
|
var date = skip.contains(i) ? null : startDate.plus(i, java.time.temporal.ChronoUnit.DAYS);
|
||||||
|
builder.invokeMember("append", date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateIntArray(Value arr, byte startValue) {
|
private void populateIntBuilder(Value builder, byte startValue, long until) {
|
||||||
populateIntArray(arr, startValue, arr.getArraySize());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateIntArray(Value arr, byte startValue, long until) {
|
|
||||||
for (int i = 0; i < until; i++) {
|
for (int i = 0; i < until; i++) {
|
||||||
var v = startValue + i;
|
var v = startValue + i;
|
||||||
arr.setArrayElement(i, (byte) v);
|
builder.invokeMember("append", i, (byte) v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,17 +19,19 @@ add_specs suite_builder =
|
|||||||
arrow_array_constructor = new_arrow
|
arrow_array_constructor = new_arrow
|
||||||
builder = arrow_array_constructor.new 10
|
builder = arrow_array_constructor.new 10
|
||||||
|
|
||||||
builder.length . should_equal 10
|
Test.expect_panic_with (builder.length) No_Such_Method
|
||||||
builder.at 1 . should_equal Nothing
|
Test.expect_panic_with (builder.at 1) No_Such_Method
|
||||||
builder.at 10 . should_fail_with Index_Out_Of_Bounds
|
|
||||||
builder.append 2
|
builder.append 2
|
||||||
builder.append 10
|
builder.append 10
|
||||||
builder.at 1 . should_equal 10
|
|
||||||
builder.append 127
|
builder.append 127
|
||||||
|
|
||||||
# Check that the value that will not fit into a byte is rejected
|
# Check that the value that will not fit into a byte is rejected
|
||||||
Test.expect_panic_with (builder.append 128) Unsupported_Argument_Types
|
Test.expect_panic_with (builder.append 128) Unsupported_Argument_Types
|
||||||
v = builder.build
|
v = builder.build
|
||||||
|
v.length . should_equal 10
|
||||||
|
v.at 1 . should_equal 10
|
||||||
|
v.at 11 . should_fail_with Index_Out_Of_Bounds
|
||||||
|
v.at 25 . should_fail_with Index_Out_Of_Bounds # Capacity of data buffer after padding will be 24
|
||||||
v.at 2 . should_equal 127
|
v.at 2 . should_equal 127
|
||||||
Test.expect_panic_with (builder.append 21) No_Such_Method
|
Test.expect_panic_with (builder.append 21) No_Such_Method
|
||||||
v.at 4 . should_equal Nothing
|
v.at 4 . should_equal Nothing
|
||||||
|
Loading…
Reference in New Issue
Block a user