protected Expression writeCollectionData()

in java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java [778:871]


  protected Expression writeCollectionData(
      Expression buffer, Expression collection, Expression serializer, TypeRef<?> elementType) {
    Invoke onCollectionWrite =
        new Invoke(
            serializer,
            "onCollectionWrite",
            TypeUtils.collectionOf(elementType),
            buffer,
            collection);
    boolean isList = List.class.isAssignableFrom(getRawType(collection.type()));
    collection =
        isList ? new Cast(onCollectionWrite.inline(), LIST_TYPE, "list") : onCollectionWrite;
    Expression size = new Invoke(collection, "size", PRIMITIVE_INT_TYPE);
    walkPath.add(elementType.toString());
    ListExpression builder = new ListExpression();
    Class<?> elemClass = TypeUtils.getRawType(elementType);
    boolean trackingRef = needWriteRef(elementType);
    Tuple2<Expression, Invoke> writeElementsHeader =
        writeElementsHeader(elemClass, trackingRef, serializer, buffer, collection);
    Expression flags = writeElementsHeader.f0;
    builder.add(flags);
    boolean finalType = isMonomorphic(elemClass);
    if (finalType) {
      if (trackingRef) {
        builder.add(
            writeContainerElements(elementType, true, null, null, buffer, collection, size));
      } else {
        Literal hasNullFlag = 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 = 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 = ofInt(CollectionFlags.NOT_DECL_ELEMENT_TYPE);
      Expression isDeclType = neq(new BitAnd(flags, notDeclTypeFlag), notDeclTypeFlag);
      Expression elemSerializer; // make it in scope of `if(sameElementClass)`
      boolean maybeDecl = visitFury(f -> f.getClassResolver().isSerializable(elemClass));
      TypeRef<?> serializerType = getSerializerType(elementType);
      if (maybeDecl) {
        elemSerializer =
            new If(
                isDeclType,
                cast(getOrCreateSerializer(elemClass), serializerType),
                cast(writeElementsHeader.f1.inline(), serializerType),
                false,
                serializerType);
      } else {
        elemSerializer = cast(writeElementsHeader.f1.inline(), serializerType);
      }
      elemSerializer = uninline(elemSerializer);
      Expression action;
      if (trackingRef) {
        ListExpression writeBuilder = new ListExpression(elemSerializer);
        writeBuilder.add(
            writeContainerElements(
                elementType, true, elemSerializer, null, buffer, collection, size));
        Set<Expression> cutPoint = ofHashSet(buffer, collection, size);
        if (maybeDecl) {
          cutPoint.add(flags);
        }
        action =
            new If(
                sameElementClass,
                invokeGenerated(ctx, cutPoint, writeBuilder, "sameElementClassWrite", false),
                writeContainerElements(elementType, true, null, null, buffer, collection, size));
      } else {
        Literal hasNullFlag = ofInt(CollectionFlags.HAS_NULL);
        Expression hasNull = eq(new BitAnd(flags, hasNullFlag), hasNullFlag, "hasNull");
        builder.add(hasNull);
        ListExpression writeBuilder = new ListExpression(elemSerializer);
        writeBuilder.add(
            writeContainerElements(
                elementType, false, elemSerializer, hasNull, buffer, collection, size));
        Set<Expression> cutPoint = ofHashSet(buffer, collection, size, hasNull);
        if (maybeDecl) {
          cutPoint.add(flags);
        }
        action =
            new If(
                sameElementClass,
                invokeGenerated(ctx, cutPoint, writeBuilder, "sameElementClassWrite", false),
                writeContainerElements(
                    elementType, false, null, hasNull, buffer, collection, size));
      }
      builder.add(action);
    }
    walkPath.removeLast();
    return new ListExpression(onCollectionWrite, new If(gt(size, ofInt(0)), builder));
  }