in java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java [1556:1642]
protected Expression readCollectionCodegen(
Expression buffer, Expression collection, Expression size, TypeRef<?> elementType) {
ListExpression builder = new ListExpression();
Invoke flags = new Invoke(buffer, "readByte", "flags", PRIMITIVE_INT_TYPE, false);
builder.add(flags);
Class<?> elemClass = TypeUtils.getRawType(elementType);
walkPath.add(elementType.toString());
boolean finalType = isMonomorphic(elemClass);
boolean trackingRef = visitFury(fury -> fury.getClassResolver().needToWriteRef(elementType));
if (finalType) {
if (trackingRef) {
builder.add(readContainerElements(elementType, true, null, null, buffer, collection, size));
} else {
Literal hasNullFlag = ofInt(CollectionFlags.HAS_NULL);
Expression hasNull = eq(new BitAnd(flags.inline(), hasNullFlag), hasNullFlag, "hasNull");
builder.add(
hasNull,
readContainerElements(elementType, false, null, hasNull, buffer, collection, size));
}
} else {
Literal notSameTypeFlag = 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 = ofInt(CollectionFlags.NOT_DECL_ELEMENT_TYPE);
Expression isDeclType = neq(new BitAnd(flags, notDeclTypeFlag), notDeclTypeFlag);
Invoke serializer =
inlineInvoke(readClassInfo(elemClass, buffer), "getSerializer", SERIALIZER_TYPE);
TypeRef<?> serializerType = getSerializerType(elementType);
Expression elemSerializer; // make it in scope of `if(sameElementClass)`
boolean maybeDecl = visitFury(f -> f.getClassResolver().isSerializable(elemClass));
if (maybeDecl) {
elemSerializer =
new If(
isDeclType,
cast(getOrCreateSerializer(elemClass), serializerType),
cast(serializer.inline(), serializerType),
false,
serializerType);
} else {
elemSerializer = cast(serializer.inline(), serializerType);
}
elemSerializer = uninline(elemSerializer);
builder.add(sameElementClass);
Expression action;
if (trackingRef) {
// Same element class read start
ListExpression readBuilder = new ListExpression(elemSerializer);
readBuilder.add(
readContainerElements(
elementType, true, elemSerializer, null, buffer, collection, size));
// Same element class read end
Set<Expression> cutPoint = ofHashSet(buffer, collection, size);
Expression differentElemTypeRead =
invokeGenerated(
ctx,
cutPoint,
readContainerElements(elementType, true, null, null, buffer, collection, size),
"differentTypeElemsRead",
false);
action = new If(sameElementClass, readBuilder, differentElemTypeRead);
} else {
Literal hasNullFlag = ofInt(CollectionFlags.HAS_NULL);
Expression hasNull = eq(new BitAnd(flags, hasNullFlag), hasNullFlag, "hasNull");
builder.add(hasNull);
// Same element class read start
ListExpression readBuilder = new ListExpression(elemSerializer);
readBuilder.add(
readContainerElements(
elementType, false, elemSerializer, hasNull, buffer, collection, size));
// Same element class read end
Set<Expression> cutPoint = ofHashSet(buffer, collection, size, hasNull);
Expression differentTypeElemsRead =
invokeGenerated(
ctx,
cutPoint,
readContainerElements(elementType, false, null, hasNull, buffer, collection, size),
"differentTypeElemsRead",
false);
action = new If(sameElementClass, readBuilder, differentTypeElemsRead);
}
builder.add(action);
}
walkPath.removeLast();
// place newCollection as last as expr value
return new ListExpression(size, collection, new If(gt(size, ofInt(0)), builder), collection);
}