protected Expression deserializeForMap()

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


  protected Expression deserializeForMap(
      Expression buffer, TypeRef<?> typeRef, Expression serializer, InvokeHint invokeHint) {
    Tuple2<TypeRef<?>, TypeRef<?>> keyValueType = TypeUtils.getMapKeyValueType(typeRef);
    TypeRef<?> keyType = keyValueType.f0;
    TypeRef<?> valueType = keyValueType.f1;
    if (serializer == null) {
      Class<?> cls = getRawType(typeRef);
      if (isMonomorphic(cls)) {
        serializer = getOrCreateSerializer(cls);
      } else {
        Expression classInfo = readClassInfo(cls, buffer);
        serializer = invoke(classInfo, "getSerializer", "mapSerializer", MAP_SERIALIZER_TYPE);
      }
    } else {
      checkArgument(
          AbstractMapSerializer.class.isAssignableFrom(serializer.type().getRawType()),
          "Expected AbstractMapSerializer but got %s",
          serializer.type());
    }
    Expression mapSerializer = serializer;
    Invoke supportHook = inlineInvoke(serializer, "supportCodegenHook", PRIMITIVE_BOOLEAN_TYPE);
    ListExpression expressions = new ListExpression();
    Expression newMap = new Invoke(serializer, "newMap", MAP_TYPE, buffer);
    Expression size = new Invoke(serializer, "getAndClearNumElements", "size", PRIMITIVE_INT_TYPE);
    Expression chunkHeader =
        new If(
            eq(size, ofInt(0)),
            ofInt(0),
            inlineInvoke(buffer, "readUnsignedByte", PRIMITIVE_INT_TYPE));
    expressions.add(newMap, size, chunkHeader);
    Class<?> keyCls = keyType.getRawType();
    Class<?> valueCls = valueType.getRawType();
    boolean keyMonomorphic = isMonomorphic(keyCls);
    boolean valueMonomorphic = isMonomorphic(valueCls);
    boolean refKey = needWriteRef(keyType);
    boolean refValue = needWriteRef(valueType);
    boolean inline = keyMonomorphic && valueMonomorphic && (!refKey || !refValue);
    Tuple2<Expression, Expression> mapKVSerializer = getMapKVSerializer(keyCls, valueCls);
    Expression keySerializer = mapKVSerializer.f0;
    Expression valueSerializer = mapKVSerializer.f1;
    While chunksLoop =
        new While(
            gt(size, ofInt(0)),
            () -> {
              ListExpression exprs = new ListExpression();
              String method = "readJavaNullChunk";
              if (keyMonomorphic && valueMonomorphic) {
                if (!refKey && !refValue) {
                  method = "readNullChunkKVFinalNoRef";
                }
              }
              Expression sizeAndHeader =
                  new Invoke(
                      mapSerializer,
                      method,
                      "sizeAndHeader",
                      PRIMITIVE_LONG_TYPE,
                      false,
                      buffer,
                      newMap,
                      chunkHeader,
                      size,
                      keySerializer,
                      valueSerializer);
              exprs.add(
                  new Assign(
                      chunkHeader, cast(bitand(sizeAndHeader, ofInt(0xff)), PRIMITIVE_INT_TYPE)),
                  new Assign(size, cast(shift(">>>", sizeAndHeader, 8), PRIMITIVE_INT_TYPE)));
              exprs.add(new If(eq(size, ofInt(0)), new Break()));
              Expression sizeAndHeader2 =
                  readChunk(buffer, newMap, size, keyType, valueType, chunkHeader);
              if (inline) {
                exprs.add(sizeAndHeader2);
              } else {
                exprs.add(
                    new Assign(
                        chunkHeader, cast(bitand(sizeAndHeader2, ofInt(0xff)), PRIMITIVE_INT_TYPE)),
                    new Assign(size, cast(shift(">>>", sizeAndHeader2, 8), PRIMITIVE_INT_TYPE)));
              }
              return exprs;
            });
    expressions.add(chunksLoop, newMap);
    // first newMap to create map, last newMap as expr value
    Expression map = inlineInvoke(serializer, "onMapRead", OBJECT_TYPE, expressions);
    Expression action =
        new If(supportHook, map, new Invoke(serializer, "read", OBJECT_TYPE, buffer), false);
    if (invokeHint != null && invokeHint.genNewMethod) {
      invokeHint.add(buffer);
      invokeHint.add(serializer);
      return invokeGenerated(
          ctx,
          invokeHint.cutPoints,
          new ListExpression(action, new Return(action)),
          "readMap",
          false);
    }
    return action;
  }