From cd18b21f8099d21cd6fe7e7636cd917b15f3e15c Mon Sep 17 00:00:00 2001 From: Shawn Yang Date: Mon, 11 Dec 2023 14:37:26 +0800 Subject: [PATCH] [Java] Align string array to collection protocol v2 (#1228) * 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 --- .../fury/builder/BaseObjectCodecBuilder.java | 26 ++-- .../io/fury/serializer/ArraySerializers.java | 56 ++++++-- .../AbstractCollectionSerializer.java | 83 +++++------- .../serializer/collection/ArrayAsList.java | 123 ++++++++++++++++++ .../collection/CollectionFlags.java | 40 ++++++ .../collection/FuryArrayAsListSerializer.java | 46 +++++++ 6 files changed, 295 insertions(+), 79 deletions(-) create mode 100644 java/fury-core/src/main/java/io/fury/serializer/collection/ArrayAsList.java create mode 100644 java/fury-core/src/main/java/io/fury/serializer/collection/CollectionFlags.java create mode 100644 java/fury-core/src/main/java/io/fury/serializer/collection/FuryArrayAsListSerializer.java diff --git a/java/fury-core/src/main/java/io/fury/builder/BaseObjectCodecBuilder.java b/java/fury-core/src/main/java/io/fury/builder/BaseObjectCodecBuilder.java index caaeacbf7e..97e03a774a 100644 --- a/java/fury-core/src/main/java/io/fury/builder/BaseObjectCodecBuilder.java +++ b/java/fury-core/src/main/java/io/fury/builder/BaseObjectCodecBuilder.java @@ -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; @@ -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)` @@ -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); @@ -818,11 +818,8 @@ private Tuple2 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( @@ -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 = @@ -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 diff --git a/java/fury-core/src/main/java/io/fury/serializer/ArraySerializers.java b/java/fury-core/src/main/java/io/fury/serializer/ArraySerializers.java index 5b3e660cb4..817eeec755 100644 --- a/java/fury-core/src/main/java/io/fury/serializer/ArraySerializers.java +++ b/java/fury-core/src/main/java/io/fury/serializer/ArraySerializers.java @@ -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; @@ -560,10 +563,15 @@ public double[] read(MemoryBuffer buffer) { public static final class StringArraySerializer extends Serializer { private final StringSerializer stringSerializer; + private final FuryArrayAsListSerializer collectionSerializer; + private final ArrayAsList 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 @@ -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); + } } } } @@ -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; diff --git a/java/fury-core/src/main/java/io/fury/serializer/collection/AbstractCollectionSerializer.java b/java/fury-core/src/main/java/io/fury/serializer/collection/AbstractCollectionSerializer.java index 93d188b083..854b96ff02 100644 --- a/java/fury-core/src/main/java/io/fury/serializer/collection/AbstractCollectionSerializer.java +++ b/java/fury-core/src/main/java/io/fury/serializer/collection/AbstractCollectionSerializer.java @@ -116,8 +116,8 @@ protected final int writeElementsHeader(MemoryBuffer buffer, Collection value) { boolean trackingRef = elemGenericType.trackingRef(fury.getClassResolver()); if (elemGenericType.isFinal()) { if (trackingRef) { - buffer.writeByte(Flags.TRACKING_REF); - return Flags.TRACKING_REF; + buffer.writeByte(CollectionFlags.TRACKING_REF); + return CollectionFlags.TRACKING_REF; } else { return writeNullabilityHeader(buffer, value); } @@ -132,8 +132,8 @@ protected final int writeElementsHeader(MemoryBuffer buffer, Collection value) { } else { if (elemSerializer != null) { if (elemSerializer.needToWriteRef()) { - buffer.writeByte(Flags.TRACKING_REF); - return Flags.TRACKING_REF; + buffer.writeByte(CollectionFlags.TRACKING_REF); + return CollectionFlags.TRACKING_REF; } else { return writeNullabilityHeader(buffer, value); } @@ -152,8 +152,8 @@ protected final int writeElementsHeader(MemoryBuffer buffer, Collection value) { public int writeNullabilityHeader(MemoryBuffer buffer, Collection value) { for (Object elem : value) { if (elem == null) { - buffer.writeByte(Flags.HAS_NULL); - return Flags.HAS_NULL; + buffer.writeByte(CollectionFlags.HAS_NULL); + return CollectionFlags.HAS_NULL; } } buffer.writeByte(0); @@ -164,7 +164,7 @@ public int writeNullabilityHeader(MemoryBuffer buffer, Collection value) { @CodegenInvoke public int writeTypeHeader( MemoryBuffer buffer, Collection value, Class declareElementType, ClassInfoHolder cache) { - int bitmap = Flags.TRACKING_REF; + int bitmap = CollectionFlags.TRACKING_REF; boolean hasDifferentClass = false; Class elemClass = null; for (Object elem : value) { @@ -180,14 +180,14 @@ public int writeTypeHeader( } } if (hasDifferentClass) { - bitmap |= Flags.NOT_SAME_TYPE | Flags.NOT_DECL_ELEMENT_TYPE; + bitmap |= CollectionFlags.NOT_SAME_TYPE | CollectionFlags.NOT_DECL_ELEMENT_TYPE; buffer.writeByte(bitmap); } else { // Write class in case peer doesn't have this class. if (!fury.getConfig().shareMetaContext() && elemClass == declareElementType) { buffer.writeByte(bitmap); } else { - bitmap |= Flags.NOT_DECL_ELEMENT_TYPE; + bitmap |= CollectionFlags.NOT_DECL_ELEMENT_TYPE; buffer.writeByte(bitmap); // Update classinfo, the caller will use it. ClassResolver classResolver = fury.getClassResolver(); @@ -201,7 +201,7 @@ public int writeTypeHeader( /** Maybe track elements ref, or write elements nullability. */ @CodegenInvoke public int writeTypeHeader(MemoryBuffer buffer, Collection value, ClassInfoHolder cache) { - int bitmap = Flags.NOT_DECL_ELEMENT_TYPE; + int bitmap = CollectionFlags.NOT_DECL_ELEMENT_TYPE; boolean hasDifferentClass = false; Class elemClass = null; boolean containsNull = false; @@ -217,10 +217,10 @@ public int writeTypeHeader(MemoryBuffer buffer, Collection value, ClassInfoHolde } } if (containsNull) { - bitmap |= Flags.HAS_NULL; + bitmap |= CollectionFlags.HAS_NULL; } if (hasDifferentClass) { - bitmap |= Flags.NOT_SAME_TYPE | Flags.TRACKING_REF; + bitmap |= CollectionFlags.NOT_SAME_TYPE | CollectionFlags.TRACKING_REF; buffer.writeByte(bitmap); } else { ClassResolver classResolver = fury.getClassResolver(); @@ -231,7 +231,7 @@ public int writeTypeHeader(MemoryBuffer buffer, Collection value, ClassInfoHolde } ClassInfo classInfo = classResolver.getClassInfo(elemClass, cache); if (classInfo.getSerializer().needToWriteRef()) { - bitmap |= Flags.TRACKING_REF; + bitmap |= CollectionFlags.TRACKING_REF; } buffer.writeByte(bitmap); classResolver.writeClass(buffer, classInfo); @@ -262,11 +262,11 @@ public int writeTypeNullabilityHeader( } } if (containsNull) { - bitmap |= Flags.HAS_NULL; + bitmap |= CollectionFlags.HAS_NULL; } if (hasDifferentClass) { // If collection contains null only, the type header will be meaningless - bitmap |= Flags.NOT_SAME_TYPE | Flags.NOT_DECL_ELEMENT_TYPE; + bitmap |= CollectionFlags.NOT_SAME_TYPE | CollectionFlags.NOT_DECL_ELEMENT_TYPE; buffer.writeByte(bitmap); } else { // When serialize a collection with all elements null directly, the declare type @@ -278,7 +278,7 @@ public int writeTypeNullabilityHeader( if (!fury.getConfig().shareMetaContext() && elemClass == declareElementType) { buffer.writeByte(bitmap); } else { - bitmap |= Flags.NOT_DECL_ELEMENT_TYPE; + bitmap |= CollectionFlags.NOT_DECL_ELEMENT_TYPE; buffer.writeByte(bitmap); ClassResolver classResolver = fury.getClassResolver(); ClassInfo classInfo = classResolver.getClassInfo(elemClass, cache); @@ -323,7 +323,7 @@ private static void compatibleWrite( fury.writeRef(buffer, elem, serializer); } } else { - boolean hasNull = (flags & Flags.HAS_NULL) == Flags.HAS_NULL; + boolean hasNull = (flags & CollectionFlags.HAS_NULL) == CollectionFlags.HAS_NULL; if (hasNull) { for (Object elem : value) { if (elem == null) { @@ -370,9 +370,10 @@ private void generalJavaWrite( Collection collection, GenericType elemGenericType, int flags) { - if ((flags & Flags.NOT_SAME_TYPE) != Flags.NOT_SAME_TYPE) { + if ((flags & CollectionFlags.NOT_SAME_TYPE) != CollectionFlags.NOT_SAME_TYPE) { Serializer serializer; - if ((flags & Flags.NOT_DECL_ELEMENT_TYPE) != Flags.NOT_DECL_ELEMENT_TYPE) { + if ((flags & CollectionFlags.NOT_DECL_ELEMENT_TYPE) + != CollectionFlags.NOT_DECL_ELEMENT_TYPE) { Preconditions.checkNotNull(elemGenericType); serializer = elemGenericType.getSerializer(fury.getClassResolver()); } else { @@ -387,7 +388,7 @@ private void generalJavaWrite( private static void writeSameTypeElements( Fury fury, MemoryBuffer buffer, Serializer serializer, int flags, T collection) { fury.incDepth(1); - if ((flags & Flags.TRACKING_REF) == Flags.TRACKING_REF) { + if ((flags & CollectionFlags.TRACKING_REF) == CollectionFlags.TRACKING_REF) { RefResolver refResolver = fury.getRefResolver(); for (Object elem : collection) { if (!refResolver.writeRefOrNull(buffer, elem)) { @@ -395,7 +396,7 @@ private static void writeSameTypeElements( } } } else { - if ((flags & Flags.HAS_NULL) != Flags.HAS_NULL) { + if ((flags & CollectionFlags.HAS_NULL) != CollectionFlags.HAS_NULL) { for (Object elem : collection) { serializer.write(buffer, elem); } @@ -415,12 +416,12 @@ private static void writeSameTypeElements( private static void writeDifferentTypeElements( Fury fury, MemoryBuffer buffer, int flags, T collection) { - if ((flags & Flags.TRACKING_REF) == Flags.TRACKING_REF) { + if ((flags & CollectionFlags.TRACKING_REF) == CollectionFlags.TRACKING_REF) { for (Object elem : collection) { fury.writeRef(buffer, elem); } } else { - if ((flags & Flags.HAS_NULL) != Flags.HAS_NULL) { + if ((flags & CollectionFlags.HAS_NULL) != CollectionFlags.HAS_NULL) { for (Object elem : collection) { fury.writeNonRef(buffer, elem); } @@ -544,7 +545,7 @@ private static void compatibleRead( collection.add(fury.readRef(buffer, serializer)); } } else { - if ((flags & Flags.HAS_NULL) == Flags.HAS_NULL) { + if ((flags & CollectionFlags.HAS_NULL) == CollectionFlags.HAS_NULL) { for (int i = 0; i < numElements; i++) { if (buffer.readByte() == Fury.NULL_FLAG) { collection.add(null); @@ -591,10 +592,11 @@ private void generalJavaRead( int numElements, int flags, GenericType elemGenericType) { - if ((flags & Flags.NOT_SAME_TYPE) != Flags.NOT_SAME_TYPE) { + if ((flags & CollectionFlags.NOT_SAME_TYPE) != CollectionFlags.NOT_SAME_TYPE) { Serializer serializer; ClassResolver classResolver = fury.getClassResolver(); - if ((flags & Flags.NOT_DECL_ELEMENT_TYPE) == Flags.NOT_DECL_ELEMENT_TYPE) { + if ((flags & CollectionFlags.NOT_DECL_ELEMENT_TYPE) + == CollectionFlags.NOT_DECL_ELEMENT_TYPE) { serializer = classResolver.readClassInfo(buffer, elementClassInfoHolder).getSerializer(); } else { Preconditions.checkNotNull(elemGenericType); @@ -615,12 +617,12 @@ private static void readSameTypeElements( T collection, int numElements) { fury.incDepth(1); - if ((flags & Flags.TRACKING_REF) == Flags.TRACKING_REF) { + if ((flags & CollectionFlags.TRACKING_REF) == CollectionFlags.TRACKING_REF) { for (int i = 0; i < numElements; i++) { collection.add(fury.readRef(buffer, serializer)); } } else { - if ((flags & Flags.HAS_NULL) != Flags.HAS_NULL) { + if ((flags & CollectionFlags.HAS_NULL) != CollectionFlags.HAS_NULL) { for (int i = 0; i < numElements; i++) { collection.add(serializer.read(buffer)); } @@ -640,12 +642,12 @@ private static void readSameTypeElements( /** Read elements whose type are different. */ private static void readDifferentTypeElements( Fury fury, MemoryBuffer buffer, int flags, T collection, int numElements) { - if ((flags & Flags.TRACKING_REF) == Flags.TRACKING_REF) { + if ((flags & CollectionFlags.TRACKING_REF) == CollectionFlags.TRACKING_REF) { for (int i = 0; i < numElements; i++) { collection.add(fury.readRef(buffer)); } } else { - if ((flags & Flags.HAS_NULL) != Flags.HAS_NULL) { + if ((flags & CollectionFlags.HAS_NULL) != CollectionFlags.HAS_NULL) { for (int i = 0; i < numElements; i++) { collection.add(fury.readNonRef(buffer)); } @@ -694,25 +696,4 @@ public void xreadElements( } } } - - /** - * Default unset bitmap flags. - * - *
    - *
  • TRACKING_REF: false - *
  • HAS_NULL: false - *
  • NOT_DECL_ELEMENT_TYPE: false - *
  • NOT_SAME_TYPE: false - *
- */ - public static class Flags { - /** Whether track elements ref. */ - public static int TRACKING_REF = 0b1; - /** Whether collection has null. */ - public static int HAS_NULL = 0b10; - /** Whether collection elements type is not declare type. */ - public static int NOT_DECL_ELEMENT_TYPE = 0b100; - /** Whether collection elements type different. */ - public static int NOT_SAME_TYPE = 0b1000; - } } diff --git a/java/fury-core/src/main/java/io/fury/serializer/collection/ArrayAsList.java b/java/fury-core/src/main/java/io/fury/serializer/collection/ArrayAsList.java new file mode 100644 index 0000000000..d5995b49b2 --- /dev/null +++ b/java/fury-core/src/main/java/io/fury/serializer/collection/ArrayAsList.java @@ -0,0 +1,123 @@ +/* + * Copyright 2023 The Fury Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fury.serializer.collection; + +import io.fury.annotation.Internal; +import java.util.AbstractList; +import java.util.Iterator; +import java.util.Objects; +import java.util.RandomAccess; + +/** + * A List which wrap a Java array like `java.util.Arrays.ArrayList`, but allow to replace wrapped + * array. Used for serialization only, do not use it in other scenarios. + * + * @author chaokunyang + */ +@Internal +public class ArrayAsList extends AbstractList implements RandomAccess, java.io.Serializable { + private E[] array; + private int size; + + @SuppressWarnings("unchecked") + public ArrayAsList(int size) { + array = (E[]) new Object[size]; + } + + public ArrayAsList(E[] array) { + this.array = Objects.requireNonNull(array); + size = array.length; + } + + @Override + public int size() { + return size; + } + + @Override + public boolean add(E e) { + array[size++] = e; + return true; + } + + @Override + public E get(int index) { + return array[index]; + } + + @Override + public E set(int index, E element) { + E prev = array[index]; + array[index] = element; + return prev; + } + + public void setArray(E[] a) { + this.array = a; + } + + public E[] getArray() { + return array; + } + + @Override + public int indexOf(Object o) { + E[] array = this.array; + if (o == null) { + for (int i = 0; i < array.length; i++) { + if (array[i] == null) { + return i; + } + } + } else { + for (int i = 0; i < array.length; i++) { + if (o.equals(array[i])) { + return i; + } + } + } + return -1; + } + + @Override + public boolean contains(Object o) { + return indexOf(o) >= 0; + } + + /** Returns original array without copy. */ + @Override + public Object[] toArray() { + return array; + } + + @Override + public Iterator iterator() { + return new Iterator() { + private int index; + + @Override + public boolean hasNext() { + return index < array.length; + } + + @Override + public E next() { + return array[index++]; + } + }; + } +} diff --git a/java/fury-core/src/main/java/io/fury/serializer/collection/CollectionFlags.java b/java/fury-core/src/main/java/io/fury/serializer/collection/CollectionFlags.java new file mode 100644 index 0000000000..fcaaca1d4e --- /dev/null +++ b/java/fury-core/src/main/java/io/fury/serializer/collection/CollectionFlags.java @@ -0,0 +1,40 @@ +/* + * Copyright 2023 The Fury Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fury.serializer.collection; + +/** + * Default unset bitmap flags. + * + *
    + *
  • TRACKING_REF: false + *
  • HAS_NULL: false + *
  • NOT_DECL_ELEMENT_TYPE: false + *
  • NOT_SAME_TYPE: false + *
+ * + * @author chaokunyang + */ +public class CollectionFlags { + /** Whether track elements ref. */ + public static int TRACKING_REF = 0b1; + /** Whether collection has null. */ + public static int HAS_NULL = 0b10; + /** Whether collection elements type is not declare type. */ + public static int NOT_DECL_ELEMENT_TYPE = 0b100; + /** Whether collection elements type different. */ + public static int NOT_SAME_TYPE = 0b1000; +} diff --git a/java/fury-core/src/main/java/io/fury/serializer/collection/FuryArrayAsListSerializer.java b/java/fury-core/src/main/java/io/fury/serializer/collection/FuryArrayAsListSerializer.java new file mode 100644 index 0000000000..f463ac131a --- /dev/null +++ b/java/fury-core/src/main/java/io/fury/serializer/collection/FuryArrayAsListSerializer.java @@ -0,0 +1,46 @@ +/* + * Copyright 2023 The Fury Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fury.serializer.collection; + +import io.fury.Fury; +import io.fury.annotation.Internal; +import io.fury.memory.MemoryBuffer; +import io.fury.type.Type; +import java.util.Collection; + +/** + * Serializer for {@link ArrayAsList}. Helper for serialization of other classes. + * + * @author chaokunyang + */ +@Internal +@SuppressWarnings("rawtypes") +public final class FuryArrayAsListSerializer extends CollectionSerializer { + public FuryArrayAsListSerializer(Fury fury) { + super(fury, ArrayAsList.class, true); + } + + @Override + public short getXtypeId() { + return (short) -Type.LIST.getId(); + } + + public Collection newCollection(MemoryBuffer buffer) { + numElements = buffer.readPositiveVarInt(); + return new ArrayAsList(numElements); + } +}