Skip to content

Commit

Permalink
[Java] Align string array to collection protocol v2 (#1228)
Browse files Browse the repository at this point in the history
* move collection elem flags as an upper level class

* add ArrayAsList serializer helper

* align string array to collection serialization

* lint code

* clean code

* fix string array write/read

* add missing header

* lint code
  • Loading branch information
chaokunyang authored Dec 11, 2023
1 parent f47e95e commit cd18b21
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import io.fury.serializer.StringSerializer;
import io.fury.serializer.collection.AbstractCollectionSerializer;
import io.fury.serializer.collection.AbstractMapSerializer;
import io.fury.serializer.collection.CollectionFlags;
import io.fury.type.TypeUtils;
import io.fury.util.GraalvmSupport;
import io.fury.util.Preconditions;
Expand Down Expand Up @@ -732,19 +733,18 @@ protected Expression writeCollectionData(
builder.add(
writeContainerElements(elementType, true, null, null, buffer, collection, size));
} else {
Literal hasNullFlag = Literal.ofInt(AbstractCollectionSerializer.Flags.HAS_NULL);
Literal hasNullFlag = Literal.ofInt(CollectionFlags.HAS_NULL);
Expression hasNull = eq(new BitAnd(flags, hasNullFlag), hasNullFlag, "hasNull");
builder.add(
hasNull,
writeContainerElements(elementType, false, null, hasNull, buffer, collection, size));
}
} else {
Literal flag = Literal.ofInt(AbstractCollectionSerializer.Flags.NOT_SAME_TYPE);
Literal flag = Literal.ofInt(CollectionFlags.NOT_SAME_TYPE);
Expression sameElementClass = neq(new BitAnd(flags, flag), flag, "sameElementClass");
builder.add(sameElementClass);
// if ((flags & Flags.NOT_DECL_ELEMENT_TYPE) == Flags.NOT_DECL_ELEMENT_TYPE)
Literal notDeclTypeFlag =
Literal.ofInt(AbstractCollectionSerializer.Flags.NOT_DECL_ELEMENT_TYPE);
Literal notDeclTypeFlag = Literal.ofInt(CollectionFlags.NOT_DECL_ELEMENT_TYPE);
Expression isDeclType =
neq(new BitAnd(flags, notDeclTypeFlag), notDeclTypeFlag, "isDeclType");
Expression elemSerializer; // make it in scope of `if(sameElementClass)`
Expand Down Expand Up @@ -777,7 +777,7 @@ protected Expression writeCollectionData(
invokeGenerated(ctx, cutPoint, writeBuilder, "sameElementClassWrite", false),
writeContainerElements(elementType, true, null, null, buffer, collection, size));
} else {
Literal hasNullFlag = Literal.ofInt(AbstractCollectionSerializer.Flags.HAS_NULL);
Literal hasNullFlag = Literal.ofInt(CollectionFlags.HAS_NULL);
Expression hasNull = eq(new BitAnd(flags, hasNullFlag), hasNullFlag, "hasNull");
builder.add(hasNull);
ListExpression writeBuilder = new ListExpression(elemSerializer);
Expand Down Expand Up @@ -818,11 +818,8 @@ private Tuple2<Expression, Invoke> writeElementsHeader(
if (trackingRef) {
bitmap =
new ListExpression(
new Invoke(
buffer,
"writeByte",
Literal.ofInt(AbstractCollectionSerializer.Flags.TRACKING_REF)),
Literal.ofInt(AbstractCollectionSerializer.Flags.TRACKING_REF));
new Invoke(buffer, "writeByte", Literal.ofInt(CollectionFlags.TRACKING_REF)),
Literal.ofInt(CollectionFlags.TRACKING_REF));
} else {
bitmap =
new Invoke(
Expand Down Expand Up @@ -1250,19 +1247,18 @@ protected Expression readCollectionCodegen(
if (trackingRef) {
builder.add(readContainerElements(elementType, true, null, null, buffer, collection, size));
} else {
Literal hasNullFlag = Literal.ofInt(AbstractCollectionSerializer.Flags.HAS_NULL);
Literal hasNullFlag = Literal.ofInt(CollectionFlags.HAS_NULL);
Expression hasNull = eq(new BitAnd(flags, hasNullFlag), hasNullFlag, "hasNull");
builder.add(
hasNull,
readContainerElements(elementType, false, null, hasNull, buffer, collection, size));
}
} else {
Literal notSameTypeFlag = Literal.ofInt(AbstractCollectionSerializer.Flags.NOT_SAME_TYPE);
Literal notSameTypeFlag = Literal.ofInt(CollectionFlags.NOT_SAME_TYPE);
Expression sameElementClass =
neq(new BitAnd(flags, notSameTypeFlag), notSameTypeFlag, "sameElementClass");
// if ((flags & Flags.NOT_DECL_ELEMENT_TYPE) == Flags.NOT_DECL_ELEMENT_TYPE)
Literal notDeclTypeFlag =
Literal.ofInt(AbstractCollectionSerializer.Flags.NOT_DECL_ELEMENT_TYPE);
Literal notDeclTypeFlag = Literal.ofInt(CollectionFlags.NOT_DECL_ELEMENT_TYPE);
Expression isDeclType =
neq(new BitAnd(flags, notDeclTypeFlag), notDeclTypeFlag, "isDeclType");
Invoke serializer =
Expand Down Expand Up @@ -1303,7 +1299,7 @@ protected Expression readCollectionCodegen(
sameElementClassRead,
readContainerElements(elementType, true, null, null, buffer, collection, size));
} else {
Literal hasNullFlag = Literal.ofInt(AbstractCollectionSerializer.Flags.HAS_NULL);
Literal hasNullFlag = Literal.ofInt(CollectionFlags.HAS_NULL);
Expression hasNull = eq(new BitAnd(flags, hasNullFlag), hasNullFlag, "hasNull");
builder.add(hasNull);
// Same element class read start
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import io.fury.resolver.ClassInfoHolder;
import io.fury.resolver.ClassResolver;
import io.fury.resolver.RefResolver;
import io.fury.serializer.collection.ArrayAsList;
import io.fury.serializer.collection.CollectionFlags;
import io.fury.serializer.collection.FuryArrayAsListSerializer;
import io.fury.type.Type;
import io.fury.type.TypeUtils;
import io.fury.util.Platform;
Expand Down Expand Up @@ -560,10 +563,15 @@ public double[] read(MemoryBuffer buffer) {

public static final class StringArraySerializer extends Serializer<String[]> {
private final StringSerializer stringSerializer;
private final FuryArrayAsListSerializer collectionSerializer;
private final ArrayAsList<String> list;

public StringArraySerializer(Fury fury) {
super(fury, String[].class);
stringSerializer = new StringSerializer(fury);
collectionSerializer = new FuryArrayAsListSerializer(fury);
collectionSerializer.setElementSerializer(stringSerializer);
list = new ArrayAsList<>(0);
}

@Override
Expand All @@ -575,13 +583,27 @@ public short getXtypeId() {
public void write(MemoryBuffer buffer, String[] value) {
int len = value.length;
buffer.writePositiveVarInt(len);
for (String elem : value) {
// TODO reference support
if (elem != null) {
buffer.writeByte(Fury.REF_VALUE_FLAG);
stringSerializer.writeJavaString(buffer, elem);
} else {
buffer.writeByte(Fury.NULL_FLAG);
if (len == 0) {
return;
}
list.setArray(value);
// TODO reference support
// this method won't throw exception.
int flags = collectionSerializer.writeNullabilityHeader(buffer, list);
list.setArray(null); // clear for gc
StringSerializer stringSerializer = this.stringSerializer;
if ((flags & CollectionFlags.HAS_NULL) != CollectionFlags.HAS_NULL) {
for (String elem : value) {
stringSerializer.write(buffer, elem);
}
} else {
for (String elem : value) {
if (elem == null) {
buffer.writeByte(Fury.NULL_FLAG);
} else {
buffer.writeByte(Fury.NOT_NULL_VALUE_FLAG);
stringSerializer.write(buffer, elem);
}
}
}
}
Expand All @@ -590,12 +612,20 @@ public void write(MemoryBuffer buffer, String[] value) {
public String[] read(MemoryBuffer buffer) {
int numElements = buffer.readPositiveVarInt();
String[] value = new String[numElements];
fury.getRefResolver().reference(value);
for (int i = 0; i < numElements; i++) {
if (buffer.readByte() == Fury.REF_VALUE_FLAG) {
value[i] = stringSerializer.readJavaString(buffer);
} else {
value[i] = null;
if (numElements == 0) {
return value;
}
int flags = buffer.readByte();
StringSerializer serializer = this.stringSerializer;
if ((flags & CollectionFlags.HAS_NULL) != CollectionFlags.HAS_NULL) {
for (int i = 0; i < numElements; i++) {
value[i] = serializer.readJavaString(buffer);
}
} else {
for (int i = 0; i < numElements; i++) {
if (buffer.readByte() != Fury.NULL_FLAG) {
value[i] = serializer.readJavaString(buffer);
}
}
}
return value;
Expand Down
Loading

0 comments on commit cd18b21

Please sign in to comment.