This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new a7f06795 feat(java): store OptionalInt, OptionalLong, OptionalDouble 
same as nullable values (#2338)
a7f06795 is described below

commit a7f06795423906db6dbd371098da1746f4cf1c3d
Author: Steven Schlansker <[email protected]>
AuthorDate: Wed Jun 18 20:21:45 2025 -0700

    feat(java): store OptionalInt, OptionalLong, OptionalDouble same as 
nullable values (#2338)
    
    ## What does this PR do?
    
    currently, optional wrappers are stored as a bean with two fields -
    present and value, taking 32 bytes
    with this change, stored as nullable primitive, taking 8 bytes plus 1
    bit for null
    
    this is a breaking change to the row format, but since support is
    relatively recent, hopefully that is ok?
---
 .../fory/builder/BaseObjectCodecBuilder.java       |  1 +
 .../java/org/apache/fory/builder/CodecBuilder.java | 15 +++--
 .../java/org/apache/fory/codegen/Expression.java   | 15 +++--
 .../main/java/org/apache/fory/type/TypeUtils.java  |  9 +++
 .../apache/fory/codegen/ExpressionVisitorTest.java |  1 +
 .../format/encoder/BaseBinaryEncoderBuilder.java   | 66 +++++++++++++++++++---
 .../fory/format/encoder/RowEncoderBuilder.java     | 31 ++++++++--
 .../apache/fory/format/row/binary/BinaryUtils.java | 24 ++++++--
 .../org/apache/fory/format/type/TypeInference.java |  9 ++-
 9 files changed, 141 insertions(+), 30 deletions(-)

diff --git 
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
 
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
index 8834ab3f..2f8efe1e 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
@@ -1041,6 +1041,7 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
     } else {
       return new ForEach(
           collection,
+          false,
           (i, elem) ->
               writeContainerElement(
                   exprHolder.get("buffer"),
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/builder/CodecBuilder.java 
b/java/fory-core/src/main/java/org/apache/fory/builder/CodecBuilder.java
index 800490c3..cf37d8ff 100644
--- a/java/fory-core/src/main/java/org/apache/fory/builder/CodecBuilder.java
+++ b/java/fory-core/src/main/java/org/apache/fory/builder/CodecBuilder.java
@@ -127,6 +127,10 @@ public abstract class CodecBuilder {
     return ctx.sourcePublicAccessible(cls);
   }
 
+  protected boolean fieldNullable(Descriptor descriptor) {
+    return false;
+  }
+
   protected Expression tryInlineCast(Expression expression, TypeRef<?> 
targetType) {
     return tryCastIfPublic(expression, targetType, true);
   }
@@ -162,9 +166,6 @@ public abstract class CodecBuilder {
     return expression;
   }
 
-  // left null check in sub class encode method to reduce data dependence.
-  private final boolean fieldNullable = false;
-
   protected Reference getRecordCtrHandle() {
     String fieldName = "_record_ctr_";
     Reference fieldRef = fieldMap.get(fieldName);
@@ -192,8 +193,9 @@ public abstract class CodecBuilder {
     TypeRef<?> fieldType = descriptor.getTypeRef();
     Class<?> rawType = descriptor.getRawType();
     String fieldName = descriptor.getName();
+    boolean fieldNullable = fieldNullable(descriptor);
     if (isInterface) {
-      return new Invoke(inputBeanExpr, descriptor.getName(), fieldName, 
fieldType);
+      return new Invoke(inputBeanExpr, descriptor.getName(), fieldName, 
fieldType, fieldNullable);
     }
     if (isRecord) {
       return getRecordFieldValue(inputBeanExpr, descriptor);
@@ -243,6 +245,7 @@ public abstract class CodecBuilder {
       fieldType = OBJECT_TYPE;
     }
     String fieldName = descriptor.getName();
+    boolean fieldNullable = fieldNullable(descriptor);
     if (Modifier.isPublic(beanClass.getModifiers())) {
       Preconditions.checkNotNull(descriptor.getReadMethod());
       return new Invoke(
@@ -280,7 +283,8 @@ public abstract class CodecBuilder {
       Expression inputObject, Class<?> cls, Descriptor descriptor) {
     Reference fieldRef = getReflectField(cls, descriptor.getField());
     // boolean fieldNullable = !descriptor.getTypeToken().isPrimitive();
-    Invoke getObj = new Invoke(fieldRef, "get", OBJECT_TYPE, fieldNullable, 
inputObject);
+    Invoke getObj =
+        new Invoke(fieldRef, "get", OBJECT_TYPE, fieldNullable(descriptor), 
inputObject);
     return new Cast(getObj, descriptor.getTypeRef(), descriptor.getName());
   }
 
@@ -289,6 +293,7 @@ public abstract class CodecBuilder {
       Expression inputObject, Class<?> cls, Descriptor descriptor) {
     String fieldName = descriptor.getName();
     Expression fieldOffsetExpr = getFieldOffset(cls, descriptor);
+    boolean fieldNullable = fieldNullable(descriptor);
     if (descriptor.getTypeRef().isPrimitive()) {
       // ex: Platform.UNSAFE.getFloat(obj, fieldOffset)
       Preconditions.checkArgument(!fieldNullable);
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/codegen/Expression.java 
b/java/fory-core/src/main/java/org/apache/fory/codegen/Expression.java
index 3cd4a771..95592426 100644
--- a/java/fory-core/src/main/java/org/apache/fory/codegen/Expression.java
+++ b/java/fory-core/src/main/java/org/apache/fory/codegen/Expression.java
@@ -891,7 +891,8 @@ public interface Expression {
         String value =
             StringUtils.format(
                 "((${withCast})${target})", "withCast", withCast, "target", 
targetExprCode.value());
-        return new ExprCode(codeBuilder.toString(), FalseLiteral, 
Code.variable(rawType, value));
+        return new ExprCode(
+            codeBuilder.toString(), targetExprCode.isNull(), 
Code.variable(rawType, value));
       } else {
         String castedValue = ctx.newName(castedValueNamePrefix);
         if (StringUtils.isNotBlank(targetExprCode.code())) {
@@ -2243,17 +2244,21 @@ public interface Expression {
     @ClosureVisitable final SerializableBiFunction<Expression, Expression, 
Expression> action;
 
     private final TypeRef<?> elementType;
+    private final boolean elementNullable;
 
     /**
      * inputObject.type() must be multi-dimension array or Collection, not 
allowed to be primitive
      * array
      */
     public ForEach(
-        Expression inputObject, SerializableBiFunction<Expression, Expression, 
Expression> action) {
+        Expression inputObject,
+        boolean elementNullable,
+        SerializableBiFunction<Expression, Expression, Expression> action) {
       super(inputObject);
       this.inputObject = inputObject;
+      this.elementNullable = elementNullable;
       this.action = action;
-      TypeRef elementType;
+      TypeRef<?> elementType;
       if (inputObject.type().isArray()) {
         elementType = inputObject.type().getComponentType();
       } else {
@@ -2265,11 +2270,13 @@ public interface Expression {
     public ForEach(
         Expression inputObject,
         TypeRef<?> beanType,
+        boolean elementNullable,
         SerializableBiFunction<Expression, Expression, Expression> action) {
       super(inputObject);
       this.inputObject = inputObject;
       this.action = action;
       this.elementType = beanType;
+      this.elementNullable = elementNullable;
     }
 
     @Override
@@ -2287,7 +2294,7 @@ public interface Expression {
       String i = ctx.newName("i");
       String elemValue = ctx.newName("elemValue");
       Expression elementExpr =
-          action.apply(new Reference(i), new Reference(elemValue, elementType, 
false));
+          action.apply(new Reference(i), new Reference(elemValue, elementType, 
elementNullable));
       ExprCode elementExprCode = elementExpr.genCode(ctx);
 
       if (inputObject.type().isArray()) {
diff --git a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java 
b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
index 6bc0b4b0..a4af2479 100644
--- a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
+++ b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
@@ -44,6 +44,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.fory.collection.IdentityMap;
@@ -104,6 +107,9 @@ public class TypeUtils {
   public static final TypeRef<?> MAP_ENTRY_TYPE = TypeRef.of(Map.Entry.class);
   public static final TypeRef<?> HASHMAP_TYPE = TypeRef.of(HashMap.class);
   public static final TypeRef<?> OPTIONAL_TYPE = TypeRef.of(Optional.class);
+  public static final TypeRef<?> OPTIONAL_INT_TYPE = 
TypeRef.of(OptionalInt.class);
+  public static final TypeRef<?> OPTIONAL_LONG_TYPE = 
TypeRef.of(OptionalLong.class);
+  public static final TypeRef<?> OPTIONAL_DOUBLE_TYPE = 
TypeRef.of(OptionalDouble.class);
   public static final TypeRef<?> OBJECT_TYPE = TypeRef.of(Object.class);
 
   public static Type ITERATOR_RETURN_TYPE;
@@ -159,6 +165,9 @@ public class TypeUtils {
     SUPPORTED_TYPES.add(TIMESTAMP_TYPE);
     SUPPORTED_TYPES.add(INSTANT_TYPE);
     SUPPORTED_TYPES.add(OPTIONAL_TYPE);
+    SUPPORTED_TYPES.add(OPTIONAL_INT_TYPE);
+    SUPPORTED_TYPES.add(OPTIONAL_LONG_TYPE);
+    SUPPORTED_TYPES.add(OPTIONAL_DOUBLE_TYPE);
   }
 
   static {
diff --git 
a/java/fory-core/src/test/java/org/apache/fory/codegen/ExpressionVisitorTest.java
 
b/java/fory-core/src/test/java/org/apache/fory/codegen/ExpressionVisitorTest.java
index cbbc43e3..0ab92115 100644
--- 
a/java/fory-core/src/test/java/org/apache/fory/codegen/ExpressionVisitorTest.java
+++ 
b/java/fory-core/src/test/java/org/apache/fory/codegen/ExpressionVisitorTest.java
@@ -52,6 +52,7 @@ public class ExpressionVisitorTest {
     Expression.ForEach forLoop =
         new Expression.ForEach(
             list,
+            false,
             (i, expr) -> ((Expression.ListExpression) 
(holder.get("e2"))).add(holder.get("e1")));
     List<Expression> expressions = new ArrayList<>();
     new ExpressionVisitor()
diff --git 
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/BaseBinaryEncoderBuilder.java
 
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/BaseBinaryEncoderBuilder.java
index 7ff21902..640520ac 100644
--- 
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/BaseBinaryEncoderBuilder.java
+++ 
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/BaseBinaryEncoderBuilder.java
@@ -30,6 +30,9 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
 import java.util.Set;
 import org.apache.arrow.vector.types.pojo.Field;
 import org.apache.arrow.vector.types.pojo.Schema;
@@ -164,15 +167,21 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
           serializeFor(
               ordinal, newInputObject, writer, rewrittenType, arrowField, 
visitedCustomTypes);
       return new If(
-          ExpressionUtils.eqNull(inputObject),
+          new Expression.IsNull(inputObject),
           new Invoke(writer, "setNullAt", ordinal),
           doSerialize);
     } else if (rawType == Optional.class) {
       TypeRef<?> elemType = TypeUtils.getTypeArguments(typeRef).get(0);
       Invoke orNull =
-          new Invoke(inputObject, "orElse", TypeUtils.OBJECT_TYPE, new 
Expression.Null(elemType));
+          new Invoke(
+              inputObject,
+              "orElse",
+              "",
+              TypeUtils.OBJECT_TYPE,
+              true,
+              new Expression.Null(elemType));
       Expression unwrapped =
-          new If(ExpressionUtils.eqNull(inputObject), new 
Expression.Null(elemType), orNull);
+          new If(new Expression.IsNull(inputObject), new 
Expression.Null(elemType), orNull);
       return serializeFor(
           ordinal,
           new Expression.Cast(unwrapped, elemType),
@@ -192,6 +201,13 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
     } else if (rawType == java.math.BigInteger.class) {
       Invoke value = new Invoke(inputObject, "toByteArray", 
TypeRef.of(byte[].class));
       return setValueOrNull(writer, ordinal, inputObject, value);
+    } else if (rawType == OptionalInt.class) {
+      return serializeForOptional(ordinal, inputObject, writer, "getAsInt", 
TypeUtils.INT_TYPE);
+    } else if (rawType == OptionalLong.class) {
+      return serializeForOptional(ordinal, inputObject, writer, "getAsLong", 
TypeUtils.LONG_TYPE);
+    } else if (rawType == OptionalDouble.class) {
+      return serializeForOptional(
+          ordinal, inputObject, writer, "getAsDouble", TypeUtils.DOUBLE_TYPE);
     } else if (rawType == java.time.LocalDate.class) {
       StaticInvoke value =
           new StaticInvoke(
@@ -306,6 +322,7 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
         ForEach forEach =
             new ForEach(
                 inputObject,
+                !rawType.getComponentType().isPrimitive(),
                 (i, value) ->
                     serializeFor(
                         i,
@@ -323,6 +340,7 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
       ForEach forEach =
           new ForEach(
               listFromIterable,
+              !TypeUtils.getElementType(typeRef).isPrimitive(),
               (i, value) ->
                   serializeFor(
                       i,
@@ -338,6 +356,7 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
       ForEach forEach =
           new ForEach(
               inputObject,
+              !TypeUtils.getElementType(typeRef).isPrimitive(),
               (i, value) ->
                   serializeFor(
                       i,
@@ -426,7 +445,7 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
     expressions.add(setOffsetAndSize);
 
     return new If(
-        ExpressionUtils.eqNull(inputObject), new Invoke(writer, "setNullAt", 
ordinal), expressions);
+        new Expression.IsNull(inputObject), new Invoke(writer, "setNullAt", 
ordinal), expressions);
   }
 
   /**
@@ -486,7 +505,7 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
             setOffsetAndSize);
 
     return new If(
-        ExpressionUtils.eqNull(inputObject), new Invoke(writer, "setNullAt", 
ordinal), expression);
+        new Expression.IsNull(inputObject), new Invoke(writer, "setNullAt", 
ordinal), expression);
   }
 
   /**
@@ -515,14 +534,34 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
             increaseWriterIndexToAligned,
             setOffsetAndSize);
     return new If(
-        ExpressionUtils.eqNull(inputObject), new Invoke(writer, "setNullAt", 
ordinal), expression);
+        new Expression.IsNull(inputObject), new Invoke(writer, "setNullAt", 
ordinal), expression);
+  }
+
+  protected Expression serializeForOptional(
+      Expression ordinal,
+      Expression inputObject,
+      Expression writer,
+      String getMethod,
+      TypeRef<?> wrapType) {
+    Class<?> primType = TypeUtils.unwrap(wrapType.getRawType());
+    If value =
+        new If(
+            new Expression.LogicalAnd(
+                true,
+                new Expression.Not(new Expression.IsNull(inputObject)),
+                Invoke.inlineInvoke(inputObject, "isPresent", 
TypeUtils.PRIMITIVE_BOOLEAN_TYPE)),
+            new Invoke(inputObject, getMethod, TypeRef.of(primType)),
+            new Expression.Null(wrapType),
+            true,
+            wrapType);
+    return setValueOrNull(writer, ordinal, value, value);
   }
 
   protected Expression setValueOrNull(
       Expression writer, Expression ordinal, Expression inputObject, 
Expression value) {
     Expression action = new Invoke(writer, "write", ordinal, value);
     return new If(
-        ExpressionUtils.eqNull(inputObject), new Invoke(writer, "setNullAt", 
ordinal), action);
+        new Expression.IsNull(inputObject), new Invoke(writer, "setNullAt", 
ordinal), action);
   }
 
   /**
@@ -558,6 +597,10 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
       return value;
     } else if (rawType == java.math.BigInteger.class) {
       return new NewInstance(TypeUtils.BIG_INTEGER_TYPE, value);
+    } else if (rawType == OptionalInt.class
+        || rawType == OptionalLong.class
+        || rawType == OptionalDouble.class) {
+      return deserializeForOptional(value, TypeRef.of(rawType));
     } else if (rawType == java.time.LocalDate.class) {
       return new StaticInvoke(
           DateTimeUtils.class, "daysToLocalDate", TypeUtils.LOCAL_DATE_TYPE, 
false, value);
@@ -654,6 +697,15 @@ public abstract class BaseBinaryEncoderBuilder extends 
CodecBuilder {
     }
   }
 
+  protected Expression deserializeForOptional(Expression value, TypeRef<?> 
type) {
+    return new Expression.If(
+        new Expression.IsNull(value),
+        new Expression.StaticInvoke(type.getRawType(), "empty", type),
+        new Expression.StaticInvoke(type.getRawType(), "of", type, value),
+        false,
+        type);
+  }
+
   /**
    * Create a java collection. Create a {@link ArrayList} if 
<code>typeToken</code> is super class
    * of {@link ArrayList}; Create a {@link HashSet} if <code>typeToken</code> 
is super class of
diff --git 
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
 
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
index 459d5c75..f8c16a38 100644
--- 
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
+++ 
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/RowEncoderBuilder.java
@@ -27,6 +27,9 @@ import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
 import java.util.SortedMap;
 import org.apache.arrow.vector.types.pojo.Field;
 import org.apache.arrow.vector.types.pojo.Schema;
@@ -115,6 +118,11 @@ public class RowEncoderBuilder extends 
BaseBinaryEncoderBuilder {
     return "RowCodec";
   }
 
+  @Override
+  protected boolean fieldNullable(Descriptor descriptor) {
+    return descriptor.isNullable();
+  }
+
   @Override
   public String genCode() {
     ctx.setPackage(CodeGenerator.getPackage(beanClass));
@@ -237,7 +245,13 @@ public class RowEncoderBuilder extends 
BaseBinaryEncoderBuilder {
         values[i] = value;
         expressions.add(value);
         Expression.Invoke isNullAt =
-            new Expression.Invoke(row, "isNullAt", 
TypeUtils.PRIMITIVE_BOOLEAN_TYPE, ordinal);
+            new Expression.Invoke(
+                row,
+                "isNullAt",
+                "f" + i + "_" + d.getName() + "IsNull",
+                TypeUtils.PRIMITIVE_BOOLEAN_TYPE,
+                false,
+                ordinal);
         Expression decode =
             new Expression.If(
                 ExpressionUtils.not(isNullAt),
@@ -271,9 +285,11 @@ public class RowEncoderBuilder extends 
BaseBinaryEncoderBuilder {
 
   private static Expression nullValue(TypeRef<?> fieldType) {
     Class<?> rawType = fieldType.getRawType();
-    if (rawType == Optional.class) {
-      return new Expression.StaticInvoke(
-          Optional.class, "empty", "", TypeUtils.OPTIONAL_TYPE, false, true);
+    if (rawType == Optional.class
+        || rawType == OptionalInt.class
+        || rawType == OptionalLong.class
+        || rawType == OptionalDouble.class) {
+      return new Expression.StaticInvoke(rawType, "empty", "", fieldType, 
false, true);
     }
     return new Expression.Reference(TypeUtils.defaultValue(rawType), 
fieldType);
   }
@@ -359,7 +375,12 @@ public class RowEncoderBuilder extends 
BaseBinaryEncoderBuilder {
           Expression isNotNullAt =
               new Expression.Not(
                   new Expression.Invoke(
-                      row, "isNullAt", TypeUtils.PRIMITIVE_BOOLEAN_TYPE, 
ordinal));
+                      row,
+                      "isNullAt",
+                      fieldName + "IsNull",
+                      TypeUtils.PRIMITIVE_BOOLEAN_TYPE,
+                      false,
+                      ordinal));
           assigner = new Expression.If(isNotNullAt, loadIfFieldIsNull);
         } else {
           assigner = loadIfFieldIsNull;
diff --git 
a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryUtils.java
 
b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryUtils.java
index 345f5f03..29cd2e16 100644
--- 
a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryUtils.java
+++ 
b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryUtils.java
@@ -35,13 +35,19 @@ public class BinaryUtils {
       return "getBoolean";
     } else if (TypeUtils.PRIMITIVE_SHORT_TYPE.equals(type) || 
TypeUtils.SHORT_TYPE.equals(type)) {
       return "getInt16";
-    } else if (TypeUtils.PRIMITIVE_INT_TYPE.equals(type) || 
TypeUtils.INT_TYPE.equals(type)) {
+    } else if (TypeUtils.PRIMITIVE_INT_TYPE.equals(type)
+        || TypeUtils.INT_TYPE.equals(type)
+        || TypeUtils.OPTIONAL_INT_TYPE.equals(type)) {
       return "getInt32";
-    } else if (TypeUtils.PRIMITIVE_LONG_TYPE.equals(type) || 
TypeUtils.LONG_TYPE.equals(type)) {
+    } else if (TypeUtils.PRIMITIVE_LONG_TYPE.equals(type)
+        || TypeUtils.LONG_TYPE.equals(type)
+        || TypeUtils.OPTIONAL_LONG_TYPE.equals(type)) {
       return "getInt64";
     } else if (TypeUtils.PRIMITIVE_FLOAT_TYPE.equals(type) || 
TypeUtils.FLOAT_TYPE.equals(type)) {
       return "getFloat32";
-    } else if (TypeUtils.PRIMITIVE_DOUBLE_TYPE.equals(type) || 
TypeUtils.DOUBLE_TYPE.equals(type)) {
+    } else if (TypeUtils.PRIMITIVE_DOUBLE_TYPE.equals(type)
+        || TypeUtils.DOUBLE_TYPE.equals(type)
+        || TypeUtils.OPTIONAL_DOUBLE_TYPE.equals(type)) {
       return "getFloat64";
     } else if (TypeUtils.BIG_DECIMAL_TYPE.equals(type)) {
       return "getDecimal";
@@ -81,13 +87,19 @@ public class BinaryUtils {
       return TypeUtils.PRIMITIVE_BOOLEAN_TYPE;
     } else if (TypeUtils.PRIMITIVE_SHORT_TYPE.equals(type) || 
TypeUtils.SHORT_TYPE.equals(type)) {
       return TypeUtils.PRIMITIVE_SHORT_TYPE;
-    } else if (TypeUtils.PRIMITIVE_INT_TYPE.equals(type) || 
TypeUtils.INT_TYPE.equals(type)) {
+    } else if (TypeUtils.PRIMITIVE_INT_TYPE.equals(type)
+        || TypeUtils.INT_TYPE.equals(type)
+        || TypeUtils.OPTIONAL_INT_TYPE.equals(type)) {
       return TypeUtils.PRIMITIVE_INT_TYPE;
-    } else if (TypeUtils.PRIMITIVE_LONG_TYPE.equals(type) || 
TypeUtils.LONG_TYPE.equals(type)) {
+    } else if (TypeUtils.PRIMITIVE_LONG_TYPE.equals(type)
+        || TypeUtils.LONG_TYPE.equals(type)
+        || TypeUtils.OPTIONAL_LONG_TYPE.equals(type)) {
       return TypeUtils.PRIMITIVE_LONG_TYPE;
     } else if (TypeUtils.PRIMITIVE_FLOAT_TYPE.equals(type) || 
TypeUtils.FLOAT_TYPE.equals(type)) {
       return TypeUtils.PRIMITIVE_FLOAT_TYPE;
-    } else if (TypeUtils.PRIMITIVE_DOUBLE_TYPE.equals(type) || 
TypeUtils.DOUBLE_TYPE.equals(type)) {
+    } else if (TypeUtils.PRIMITIVE_DOUBLE_TYPE.equals(type)
+        || TypeUtils.DOUBLE_TYPE.equals(type)
+        || TypeUtils.OPTIONAL_DOUBLE_TYPE.equals(type)) {
       return TypeUtils.PRIMITIVE_DOUBLE_TYPE;
     } else if (TypeUtils.BIG_DECIMAL_TYPE.equals(type)) {
       return TypeUtils.BIG_DECIMAL_TYPE;
diff --git 
a/java/fory-format/src/main/java/org/apache/fory/format/type/TypeInference.java 
b/java/fory-format/src/main/java/org/apache/fory/format/type/TypeInference.java
index e7a67ce4..7c529423 100644
--- 
a/java/fory-format/src/main/java/org/apache/fory/format/type/TypeInference.java
+++ 
b/java/fory-format/src/main/java/org/apache/fory/format/type/TypeInference.java
@@ -28,6 +28,9 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
 import org.apache.arrow.vector.complex.MapVector;
 import org.apache.arrow.vector.types.DateUnit;
 import org.apache.arrow.vector.types.FloatingPointPrecision;
@@ -185,14 +188,14 @@ public class TypeInference {
       return field(name, FieldType.nullable((new ArrowType.Int(8, true))));
     } else if (rawType == Short.class) {
       return field(name, FieldType.nullable((new ArrowType.Int(16, true))));
-    } else if (rawType == Integer.class) {
+    } else if (rawType == Integer.class || rawType == OptionalInt.class) {
       return field(name, FieldType.nullable((new ArrowType.Int(32, true))));
-    } else if (rawType == Long.class) {
+    } else if (rawType == Long.class || rawType == OptionalLong.class) {
       return field(name, FieldType.nullable((new ArrowType.Int(64, true))));
     } else if (rawType == Float.class) {
       return field(
           name, FieldType.nullable(new 
ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE)));
-    } else if (rawType == Double.class) {
+    } else if (rawType == Double.class || rawType == OptionalDouble.class) {
       return field(
           name, FieldType.nullable(new 
ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)));
     } else if (rawType == java.math.BigDecimal.class) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to