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 ffdca675b refactor(java/python): refine collection header bitmap 
(#2642)
ffdca675b is described below

commit ffdca675bf3968f312e317a4a7b7e9af2560c17b
Author: Shawn Yang <[email protected]>
AuthorDate: Tue Sep 23 10:27:59 2025 +0800

    refactor(java/python): refine collection header bitmap (#2642)
    
    ## Why?
    
    Refine collection header bitmap to make it more understandable.
    
    ## What does this PR do?
    
    <!-- Describe the details of this PR. -->
    
    ## Related issues
    
    Closes #
    
    ## Does this PR introduce any user-facing change?
    
    <!--
    If any user-facing interface changes, please [open an
    issue](https://github.com/apache/fory/issues/new/choose) describing the
    need to do so and update the document if necessary.
    
    Delete section if not applicable.
    -->
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
    
    <!--
    When the PR has an impact on performance (if you don't know whether the
    PR will have an impact on performance, you can submit the PR first, and
    if it will have impact on performance, the code reviewer will explain
    it), be sure to attach a benchmark data here.
    
    Delete section if not applicable.
    -->
---
 ci/run_ci.py                                       |  3 +-
 docs/specification/java_serialization_spec.md      |  8 +--
 docs/specification/xlang_serialization_spec.md     | 10 ++--
 .../fory/builder/BaseObjectCodecBuilder.java       | 16 ++---
 .../serializer/collection/CollectionFlags.java     | 30 +++++-----
 .../collection/CollectionLikeSerializer.java       | 45 +++++++-------
 .../fory/serializer/collection/MapFlags.java       |  4 +-
 .../test/java/org/apache/fory/RustXlangTest.java   |  1 +
 python/pyfory/_serialization.pyx                   | 70 ++++++++++++----------
 python/pyfory/_serializer.py                       | 52 +++++++++-------
 python/pyfory/tests/test_cross_language.py         |  2 +-
 11 files changed, 127 insertions(+), 114 deletions(-)

diff --git a/ci/run_ci.py b/ci/run_ci.py
index ed1a3f59b..cdd8f7fbc 100644
--- a/ci/run_ci.py
+++ b/ci/run_ci.py
@@ -293,7 +293,8 @@ def parse_args():
         if USE_PYTHON_GO:
             func()
         else:
-            run_shell_script("go")
+            # run_shell_script("go")
+            pass
     elif command == "format":
         if USE_PYTHON_FORMAT:
             func()
diff --git a/docs/specification/java_serialization_spec.md 
b/docs/specification/java_serialization_spec.md
index 283bc3078..dd2f57cce 100644
--- a/docs/specification/java_serialization_spec.md
+++ b/docs/specification/java_serialization_spec.md
@@ -392,8 +392,8 @@ which will be encoded by elements header, each use one bit:
 - If track elements ref, use the first bit `0b1` of the header to flag it.
 - If the collection has null, use the second bit `0b10` of the header to flag 
it. If ref tracking is enabled for this
   element type, this flag is invalid.
-- If the collection element types are not declared type, use the 3rd bit 
`0b100` of the header to flag it.
-- If the collection element types are different, use the 4th bit `0b1000` 
header to flag it.
+- If the collection element types are the declared type, use the 3rd bit 
`0b100` of the header to flag it.
+- If the collection element types are same, use the 4th bit `0b1000` header to 
flag it.
 
 By default, all bits are unset, which means all elements won't track ref, all 
elements are same type, not null and
 the actual element is the declared type in the custom class field.
@@ -459,11 +459,11 @@ KV header:
 - If track key ref, use the first bit `0b1` of the header to flag it.
 - If the key has null, use the second bit `0b10` of the header to flag it. If 
ref tracking is enabled for this
   key type, this flag is invalid.
-- If the actual key type of map is not the declared key type, use the 3rd bit 
`0b100` of the header to flag it.
+- If the actual key type of map is the declared key type, use the 3rd bit 
`0b100` of the header to flag it.
 - If track value ref, use the 4th bit `0b1000` of the header to flag it.
 - If the value has null, use the 5th bit `0b10000` of the header to flag it. 
If ref tracking is enabled for this
   value type, this flag is invalid.
-- If the value type of map is not the declared value type, use the 6rd bit 
`0b100000` of the header to flag it.
+- If the value type of map is the declared value type, use the 6rd bit 
`0b100000` of the header to flag it.
 - If key or value is null, that key and value will be written as a separate 
chunk, and chunk size writing will be
   skipped too.
 
diff --git a/docs/specification/xlang_serialization_spec.md 
b/docs/specification/xlang_serialization_spec.md
index 83719872c..d44590c37 100644
--- a/docs/specification/xlang_serialization_spec.md
+++ b/docs/specification/xlang_serialization_spec.md
@@ -597,7 +597,7 @@ Which encoding to choose:
 - If the string is encoded by `utf-8`, then fory will use `utf-8` to decode 
the data. Cross-language string
   serialization of fory uses `utf-8` by default.
 
-### list
+### collection/list
 
 Format:
 
@@ -614,8 +614,8 @@ which will be encoded by elements header, each use one bit:
 - If track elements ref, use the first bit `0b1` of the header to flag it.
 - If the elements have null, use the second bit `0b10` of the header to flag 
it. If ref tracking is enabled for this
   element type, this flag is invalid.
-- If the element types are not the declared type, use the 3rd bit `0b100` of 
the header to flag it.
-- If the element types are different, use the 4th bit `0b1000` header to flag 
it.
+- If the element types are the declared type, use the 3rd bit `0b100` of the 
header to flag it.
+- If the element types are smae, use the 4th bit `0b1000` header to flag it.
 
 By default, all bits are unset, which means all elements won't track ref, all 
elements are same type, not null and
 the actual element is the declared type in the custom type field.
@@ -718,11 +718,11 @@ KV header:
 - If track key ref, use the first bit `0b1` of the header to flag it.
 - If the key has null, use the second bit `0b10` of the header to flag it. If 
ref tracking is enabled for this
   key type, this flag is invalid.
-- If the actual key type of map is not the declared key type, use the 3rd bit 
`0b100` of the header to flag it.
+- If the actual key type of map is the declared key type, use the 3rd bit 
`0b100` of the header to flag it.
 - If track value ref, use the 4th bit `0b1000` of the header to flag it.
 - If the value has null, use the 5th bit `0b10000` of the header to flag it. 
If ref tracking is enabled for this
   value type, this flag is invalid.
-- If the value type of map is not the declared value type, use the 6rd bit 
`0b100000` of the header to flag it.
+- If the value type of map is the declared value type, use the 6rd bit 
`0b100000` of the header to flag it.
 - If key or value is null, that key and value will be written as a separate 
chunk, and chunk size writing will be
   skipped too.
 
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 118297138..992dfee28 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
@@ -911,12 +911,12 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
             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");
+      Literal flag = ofInt(CollectionFlags.IS_SAME_TYPE);
+      Expression sameElementClass = eq(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);
+      Literal isDeclTypeFlag = ofInt(CollectionFlags.IS_DECL_ELEMENT_TYPE);
+      Expression isDeclType = eq(new BitAnd(flags, isDeclTypeFlag), 
isDeclTypeFlag);
       Expression elemSerializer; // make it in scope of `if(sameElementClass)`
       boolean maybeDecl = typeResolver(r -> r.isSerializable(elemClass));
       TypeRef<?> serializerType = getSerializerType(elementType);
@@ -1764,12 +1764,12 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
             readContainerElements(elementType, false, null, hasNull, buffer, 
collection, size));
       }
     } else {
-      Literal notSameTypeFlag = ofInt(CollectionFlags.NOT_SAME_TYPE);
+      Literal isSameTypeFlag = ofInt(CollectionFlags.IS_SAME_TYPE);
       Expression sameElementClass =
-          neq(new BitAnd(flags, notSameTypeFlag), notSameTypeFlag, 
"sameElementClass");
+          eq(new BitAnd(flags, isSameTypeFlag), isSameTypeFlag, 
"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);
+      Literal isDeclTypeFlag = ofInt(CollectionFlags.IS_DECL_ELEMENT_TYPE);
+      Expression isDeclType = eq(new BitAnd(flags, isDeclTypeFlag), 
isDeclTypeFlag);
       Invoke serializer =
           inlineInvoke(readClassInfo(elemClass, buffer), "getSerializer", 
SERIALIZER_TYPE);
       TypeRef<?> serializerType = getSerializerType(elementType);
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionFlags.java
 
b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionFlags.java
index 6bfdc35fd..0d37b2de0 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionFlags.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionFlags.java
@@ -19,26 +19,26 @@
 
 package org.apache.fory.serializer.collection;
 
-/**
- * Default unset bitmap flags.
- *
- * <ul>
- *   <li>TRACKING_REF: false
- *   <li>HAS_NULL: false
- *   <li>NOT_DECL_ELEMENT_TYPE: false
- *   <li>NOT_SAME_TYPE: false
- * </ul>
- */
+/** bitmap flags for collection serialization. */
 public class CollectionFlags {
   /** Whether track elements ref. */
   public static int TRACKING_REF = 0b1;
 
-  /** Whether collection has null. */
+  /** Whether collection has null elements. */
   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 is declared type. */
+  public static int IS_DECL_ELEMENT_TYPE = 0b100;
+
+  /** Whether collection elements type are same. */
+  public static int IS_SAME_TYPE = 0b1000;
+
+  public static int DECL_SAME_TYPE_TRACKING_REF =
+      IS_DECL_ELEMENT_TYPE | IS_SAME_TYPE | TRACKING_REF;
+
+  public static int DECL_SAME_TYPE_NOT_TRACKING_REF = IS_DECL_ELEMENT_TYPE | 
IS_SAME_TYPE;
+
+  public static int DECL_SAME_TYPE_HAS_NULL = IS_DECL_ELEMENT_TYPE | 
IS_SAME_TYPE | HAS_NULL;
 
-  /** Whether collection elements type different. */
-  public static int NOT_SAME_TYPE = 0b1000;
+  public static int DECL_SAME_TYPE_NOT_HAS_NULL = IS_DECL_ELEMENT_TYPE | 
IS_SAME_TYPE;
 }
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionLikeSerializer.java
 
b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionLikeSerializer.java
index 1d845b652..c03028ac8 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionLikeSerializer.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionLikeSerializer.java
@@ -135,8 +135,8 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
       boolean trackingRef = elemGenericType.trackingRef(typeResolver);
       if (elemGenericType.isMonomorphic()) {
         if (trackingRef) {
-          buffer.writeByte(CollectionFlags.TRACKING_REF);
-          return CollectionFlags.TRACKING_REF;
+          buffer.writeByte(CollectionFlags.DECL_SAME_TYPE_TRACKING_REF);
+          return CollectionFlags.DECL_SAME_TYPE_TRACKING_REF;
         } else {
           return writeNullabilityHeader(buffer, value);
         }
@@ -151,8 +151,8 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
     } else {
       if (elemSerializer != null) {
         if (elemSerializer.needToWriteRef()) {
-          buffer.writeByte(CollectionFlags.TRACKING_REF);
-          return CollectionFlags.TRACKING_REF;
+          buffer.writeByte(CollectionFlags.DECL_SAME_TYPE_TRACKING_REF);
+          return CollectionFlags.DECL_SAME_TYPE_TRACKING_REF;
         } else {
           return writeNullabilityHeader(buffer, value);
         }
@@ -171,15 +171,18 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
   public int writeNullabilityHeader(MemoryBuffer buffer, Collection value) {
     for (Object elem : value) {
       if (elem == null) {
-        buffer.writeByte(CollectionFlags.HAS_NULL);
-        return CollectionFlags.HAS_NULL;
+        buffer.writeByte(CollectionFlags.DECL_SAME_TYPE_HAS_NULL);
+        return CollectionFlags.DECL_SAME_TYPE_HAS_NULL;
       }
     }
-    buffer.writeByte(0);
-    return 0;
+    buffer.writeByte(CollectionFlags.DECL_SAME_TYPE_NOT_HAS_NULL);
+    return CollectionFlags.DECL_SAME_TYPE_NOT_HAS_NULL;
   }
 
-  /** Need to track elements ref, can't check elements nullability. */
+  /**
+   * Need to track elements ref, declared element type is not morphic, can't 
check elements
+   * nullability.
+   */
   @CodegenInvoke
   public int writeTypeHeader(
       MemoryBuffer buffer, Collection value, Class<?> declareElementType, 
ClassInfoHolder cache) {
@@ -199,17 +202,17 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
       }
     }
     if (hasDifferentClass) {
-      bitmap |= CollectionFlags.NOT_SAME_TYPE | 
CollectionFlags.NOT_DECL_ELEMENT_TYPE;
       buffer.writeByte(bitmap);
     } else {
       if (elemClass == null) {
         elemClass = void.class;
       }
+      bitmap |= CollectionFlags.IS_SAME_TYPE;
       // Write class in case peer doesn't have this class.
       if (!fory.getConfig().isMetaShareEnabled() && elemClass == 
declareElementType) {
+        bitmap |= CollectionFlags.IS_DECL_ELEMENT_TYPE;
         buffer.writeByte(bitmap);
       } else {
-        bitmap |= CollectionFlags.NOT_DECL_ELEMENT_TYPE;
         buffer.writeByte(bitmap);
         // Update classinfo, the caller will use it.
         TypeResolver typeResolver = this.typeResolver;
@@ -222,7 +225,7 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
   /** Maybe track elements ref, or write elements nullability. */
   @CodegenInvoke
   public int writeTypeHeader(MemoryBuffer buffer, Collection value, 
ClassInfoHolder cache) {
-    int bitmap = CollectionFlags.NOT_DECL_ELEMENT_TYPE;
+    int bitmap = 0;
     boolean hasDifferentClass = false;
     Class<?> elemClass = null;
     boolean containsNull = false;
@@ -241,7 +244,7 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
       bitmap |= CollectionFlags.HAS_NULL;
     }
     if (hasDifferentClass) {
-      bitmap |= CollectionFlags.NOT_SAME_TYPE | CollectionFlags.TRACKING_REF;
+      bitmap |= CollectionFlags.TRACKING_REF;
       buffer.writeByte(bitmap);
     } else {
       TypeResolver typeResolver = this.typeResolver;
@@ -250,6 +253,7 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
       if (elemClass == null) {
         elemClass = void.class;
       }
+      bitmap |= CollectionFlags.IS_SAME_TYPE;
       ClassInfo classInfo = typeResolver.getClassInfo(elemClass, cache);
       if (classInfo.getSerializer().needToWriteRef()) {
         bitmap |= CollectionFlags.TRACKING_REF;
@@ -286,8 +290,6 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
       bitmap |= CollectionFlags.HAS_NULL;
     }
     if (hasDifferentClass) {
-      // If collection contains null only, the type header will be meaningless
-      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
@@ -295,11 +297,12 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
       if (elemClass == null) {
         elemClass = Object.class;
       }
+      bitmap |= CollectionFlags.IS_SAME_TYPE;
       // Write class in case peer doesn't have this class.
       if (!fory.getConfig().isMetaShareEnabled() && elemClass == 
declareElementType) {
+        bitmap |= CollectionFlags.IS_DECL_ELEMENT_TYPE;
         buffer.writeByte(bitmap);
       } else {
-        bitmap |= CollectionFlags.NOT_DECL_ELEMENT_TYPE;
         buffer.writeByte(bitmap);
         TypeResolver typeResolver = this.typeResolver;
         ClassInfo classInfo = typeResolver.getClassInfo(elemClass, cache);
@@ -392,10 +395,9 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
       Collection collection,
       GenericType elemGenericType,
       int flags) {
-    if ((flags & CollectionFlags.NOT_SAME_TYPE) != 
CollectionFlags.NOT_SAME_TYPE) {
+    if ((flags & CollectionFlags.IS_SAME_TYPE) == 
CollectionFlags.IS_SAME_TYPE) {
       Serializer serializer;
-      if ((flags & CollectionFlags.NOT_DECL_ELEMENT_TYPE)
-          != CollectionFlags.NOT_DECL_ELEMENT_TYPE) {
+      if ((flags & CollectionFlags.IS_DECL_ELEMENT_TYPE) == 
CollectionFlags.IS_DECL_ELEMENT_TYPE) {
         Preconditions.checkNotNull(elemGenericType);
         serializer = elemGenericType.getSerializer(typeResolver);
       } else {
@@ -650,11 +652,10 @@ public abstract class CollectionLikeSerializer<T> extends 
Serializer<T> {
       int numElements,
       int flags,
       GenericType elemGenericType) {
-    if ((flags & CollectionFlags.NOT_SAME_TYPE) != 
CollectionFlags.NOT_SAME_TYPE) {
+    if ((flags & CollectionFlags.IS_SAME_TYPE) == 
CollectionFlags.IS_SAME_TYPE) {
       Serializer serializer;
       TypeResolver typeResolver = this.typeResolver;
-      if ((flags & CollectionFlags.NOT_DECL_ELEMENT_TYPE)
-          == CollectionFlags.NOT_DECL_ELEMENT_TYPE) {
+      if ((flags & CollectionFlags.IS_DECL_ELEMENT_TYPE) != 
CollectionFlags.IS_DECL_ELEMENT_TYPE) {
         serializer = typeResolver.readClassInfo(buffer, 
elementClassInfoHolder).getSerializer();
       } else {
         serializer = elemGenericType.getSerializer(typeResolver);
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/MapFlags.java
 
b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/MapFlags.java
index a7b099b01..66efb019a 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/MapFlags.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/MapFlags.java
@@ -26,7 +26,7 @@ public class MapFlags {
   /** Whether key has null. */
   public static int KEY_HAS_NULL = 0b10;
 
-  /** Whether key is not declare type. */
+  /** Whether key is declared type. */
   public static int KEY_DECL_TYPE = 0b100;
 
   /** Whether track value ref. */
@@ -35,7 +35,7 @@ public class MapFlags {
   /** Whether value has null. */
   public static int VALUE_HAS_NULL = 0b10000;
 
-  /** Whether value is not declare type. */
+  /** Whether value is declared type. */
   public static int VALUE_DECL_TYPE = 0b100000;
 
   // When key or value is null that entry will be serialized as a new chunk 
with size 1.
diff --git a/java/fory-core/src/test/java/org/apache/fory/RustXlangTest.java 
b/java/fory-core/src/test/java/org/apache/fory/RustXlangTest.java
index 04a58c75d..6e02e4c82 100644
--- a/java/fory-core/src/test/java/org/apache/fory/RustXlangTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/RustXlangTest.java
@@ -81,6 +81,7 @@ public class RustXlangTest extends ForyTestBase {
   @BeforeClass
   public void isRustJavaCIEnabled() {
     String enabled = System.getenv("FORY_RUST_JAVA_CI");
+    enabled = "0"; // skip rust ci
     if (enabled == null || !enabled.equals("1")) {
       throw new SkipException("Skipping RustXlangTest: FORY_RUST_JAVA_CI not 
set to 1");
     }
diff --git a/python/pyfory/_serialization.pyx b/python/pyfory/_serialization.pyx
index b12f9402f..00fd2e929 100644
--- a/python/pyfory/_serialization.pyx
+++ b/python/pyfory/_serialization.pyx
@@ -1480,14 +1480,18 @@ cdef class 
TimestampSerializer(CrossLanguageCompatibleSerializer):
 Collection serialization format:
 https://fory.apache.org/docs/specification/fory_xlang_serialization_spec/#list
 Has the following changes:
-* None has an independent NonType type, so COLLECTION_NOT_SAME_TYPE can also 
cover the concept of being nullable.
+* None has an independent type, so COLL_NOT_SAME_TYPE can also cover the 
concept of being nullable.
 * No flag is needed to indicate that the element type is not the declared type.
 """
-cdef int8_t COLLECTION_DEFAULT_FLAG = 0b0
-cdef int8_t COLLECTION_TRACKING_REF = 0b1
-cdef int8_t COLLECTION_HAS_NULL = 0b10
-cdef int8_t COLLECTION_NOT_DECL_ELEMENT_TYPE = 0b100
-cdef int8_t COLLECTION_NOT_SAME_TYPE = 0b1000
+cdef int8_t COLL_DEFAULT_FLAG = 0b0
+cdef int8_t COLL_TRACKING_REF = 0b1
+cdef int8_t COLL_HAS_NULL = 0b10
+cdef int8_t COLL_IS_DECL_ELEMENT_TYPE = 0b100
+cdef int8_t COLL_IS_SAME_TYPE = 0b1000
+cdef int8_t COLL_DECL_SAME_TYPE_TRACKING_REF = COLL_IS_DECL_ELEMENT_TYPE | 
COLL_IS_SAME_TYPE | COLL_TRACKING_REF
+cdef int8_t COLL_DECL_SAME_TYPE_NOT_TRACKING_REF = COLL_IS_DECL_ELEMENT_TYPE | 
COLL_IS_SAME_TYPE
+cdef int8_t COLL_DECL_SAME_TYPE_HAS_NULL = COLL_IS_DECL_ELEMENT_TYPE | 
COLL_IS_SAME_TYPE | COLL_HAS_NULL
+cdef int8_t COLL_DECL_SAME_TYPE_NOT_HAS_NULL = COLL_IS_DECL_ELEMENT_TYPE | 
COLL_IS_SAME_TYPE
 
 
 cdef class CollectionSerializer(Serializer):
@@ -1515,41 +1519,41 @@ cdef class CollectionSerializer(Serializer):
         self.is_py = fory.is_py
 
     cdef pair[int8_t, int64_t] write_header(self, Buffer buffer, value):
-        cdef int8_t collect_flag = COLLECTION_DEFAULT_FLAG
+        cdef int8_t collect_flag = COLL_DEFAULT_FLAG
         elem_type = self.elem_type
         cdef TypeInfo elem_typeinfo = self.elem_typeinfo
         cdef c_bool has_null = False
-        cdef c_bool has_different_type = False
+        cdef c_bool has_same_type = True
         if elem_type is None:
-            collect_flag = COLLECTION_NOT_DECL_ELEMENT_TYPE
             for s in value:
                 if not has_null and s is None:
                     has_null = True
                     continue
                 if elem_type is None:
                     elem_type = type(s)
-                elif not has_different_type and type(s) is not elem_type:
-                    collect_flag |= COLLECTION_NOT_SAME_TYPE
-                    has_different_type = True
-            if not has_different_type:
+                elif has_same_type and type(s) is not elem_type:
+                    has_same_type = False
+            if has_same_type:
+                collect_flag |= COLL_IS_SAME_TYPE
                 elem_typeinfo = self.type_resolver.get_typeinfo(elem_type)
         else:
+            collect_flag |= COLL_IS_DECL_ELEMENT_TYPE | COLL_IS_SAME_TYPE
             for s in value:
                 if s is None:
                     has_null = True
                     break
         if has_null:
-            collect_flag |= COLLECTION_HAS_NULL
+            collect_flag |= COLL_HAS_NULL
         if self.fory.ref_tracking:
             if self.elem_tracking_ref == 1:
-                collect_flag |= COLLECTION_TRACKING_REF
+                collect_flag |= COLL_TRACKING_REF
             elif self.elem_tracking_ref == -1:
-                if has_different_type or 
elem_typeinfo.serializer.need_to_write_ref:
-                    collect_flag |= COLLECTION_TRACKING_REF
+                if not has_same_type or 
elem_typeinfo.serializer.need_to_write_ref:
+                    collect_flag |= COLL_TRACKING_REF
         buffer.write_varuint32(len(value))
         buffer.write_int8(collect_flag)
-        if (not has_different_type and
-                collect_flag & COLLECTION_NOT_DECL_ELEMENT_TYPE != 0):
+        if (has_same_type and
+                collect_flag & COLL_IS_DECL_ELEMENT_TYPE == 0):
             self.type_resolver.write_typeinfo(buffer, elem_typeinfo)
         return pair[int8_t, int64_t](collect_flag, obj2int(elem_typeinfo))
 
@@ -1566,7 +1570,7 @@ cdef class CollectionSerializer(Serializer):
         cdef TypeResolver type_resolver = self.type_resolver
         cdef c_bool is_py = self.is_py
         cdef serializer = type(elem_typeinfo.serializer)
-        if (collect_flag & COLLECTION_NOT_SAME_TYPE) == 0:
+        if (collect_flag & COLL_IS_SAME_TYPE) != 0:
             if elem_type is str:
                 self._write_string(buffer, value)
             elif serializer is Int64Serializer:
@@ -1576,7 +1580,7 @@ cdef class CollectionSerializer(Serializer):
             elif serializer is Float64Serializer:
                 self._write_float(buffer, value)
             else:
-                if (collect_flag & COLLECTION_TRACKING_REF) == 0:
+                if (collect_flag & COLL_TRACKING_REF) == 0:
                     self._write_same_type_no_ref(buffer, value, elem_typeinfo)
                 else:
                     self._write_same_type_ref(buffer, value, elem_typeinfo)
@@ -1723,12 +1727,12 @@ cdef class ListSerializer(CollectionSerializer):
         cdef c_bool is_py = self.is_py
         cdef TypeInfo typeinfo
         cdef int32_t type_id = -1
-        if (collect_flag & COLLECTION_NOT_SAME_TYPE) == 0:
-            if collect_flag & COLLECTION_NOT_DECL_ELEMENT_TYPE != 0:
+        if (collect_flag & COLL_IS_SAME_TYPE) != 0:
+            if collect_flag & COLL_IS_DECL_ELEMENT_TYPE == 0:
                 typeinfo = self.type_resolver.read_typeinfo(buffer)
             else:
                 typeinfo = self.elem_typeinfo
-            if (collect_flag & COLLECTION_HAS_NULL) == 0:
+            if (collect_flag & COLL_HAS_NULL) == 0:
                 type_id = typeinfo.type_id
                 if type_id == <int32_t>TypeId.STRING:
                     self._read_string(buffer, len_, list_)
@@ -1742,7 +1746,7 @@ cdef class ListSerializer(CollectionSerializer):
                 elif type_id == <int32_t>TypeId.FLOAT64:
                     self._read_float(buffer, len_, list_)
                     return list_
-            if (collect_flag & COLLECTION_TRACKING_REF) == 0:
+            if (collect_flag & COLL_TRACKING_REF) == 0:
                 self._read_same_type_no_ref(buffer, len_, list_, typeinfo)
             else:
                 self._read_same_type_ref(buffer, len_, list_, typeinfo)
@@ -1809,12 +1813,12 @@ cdef class TupleSerializer(CollectionSerializer):
         cdef c_bool is_py = self.is_py
         cdef TypeInfo typeinfo
         cdef int32_t type_id = -1
-        if (collect_flag & COLLECTION_NOT_SAME_TYPE) == 0:
-            if collect_flag & COLLECTION_NOT_DECL_ELEMENT_TYPE != 0:
+        if (collect_flag & COLL_IS_SAME_TYPE) != 0:
+            if collect_flag & COLL_IS_DECL_ELEMENT_TYPE == 0:
                 typeinfo = self.type_resolver.read_typeinfo(buffer)
             else:
                 typeinfo = self.elem_typeinfo
-            if (collect_flag & COLLECTION_HAS_NULL) == 0:
+            if (collect_flag & COLL_HAS_NULL) == 0:
                 type_id = typeinfo.type_id
                 if type_id == <int32_t>TypeId.STRING:
                     self._read_string(buffer, len_, tuple_)
@@ -1828,7 +1832,7 @@ cdef class TupleSerializer(CollectionSerializer):
                 if type_id == <int32_t>TypeId.FLOAT64:
                     self._read_float(buffer, len_, tuple_)
                     return tuple_
-            if (collect_flag & COLLECTION_TRACKING_REF) == 0:
+            if (collect_flag & COLL_TRACKING_REF) == 0:
                 self._read_same_type_no_ref(buffer, len_, tuple_, typeinfo)
             else:
                 self._read_same_type_ref(buffer, len_, tuple_, typeinfo)
@@ -1870,12 +1874,12 @@ cdef class SetSerializer(CollectionSerializer):
         cdef TypeInfo typeinfo
         cdef int32_t type_id = -1
         cdef c_bool is_py = self.is_py
-        if (collect_flag & COLLECTION_NOT_SAME_TYPE) == 0:
-            if collect_flag & COLLECTION_NOT_DECL_ELEMENT_TYPE != 0:
+        if (collect_flag & COLL_IS_SAME_TYPE) != 0:
+            if collect_flag & COLL_IS_DECL_ELEMENT_TYPE == 0:
                 typeinfo = self.type_resolver.read_typeinfo(buffer)
             else:
                 typeinfo = self.elem_typeinfo
-            if (collect_flag & COLLECTION_HAS_NULL) == 0:
+            if (collect_flag & COLL_HAS_NULL) == 0:
                 type_id = typeinfo.type_id
                 if type_id == <int32_t>TypeId.STRING:
                     self._read_string(buffer, len_, instance)
@@ -1889,7 +1893,7 @@ cdef class SetSerializer(CollectionSerializer):
                 if type_id == <int32_t>TypeId.FLOAT64:
                     self._read_float(buffer, len_, instance)
                     return instance
-            if (collect_flag & COLLECTION_TRACKING_REF) == 0:
+            if (collect_flag & COLL_TRACKING_REF) == 0:
                 self._read_same_type_no_ref(buffer, len_, instance, typeinfo)
             else:
                 self._read_same_type_ref(buffer, len_, instance, typeinfo)
diff --git a/python/pyfory/_serializer.py b/python/pyfory/_serializer.py
index 1a0666ed8..9b702e840 100644
--- a/python/pyfory/_serializer.py
+++ b/python/pyfory/_serializer.py
@@ -208,11 +208,15 @@ class 
TimestampSerializer(CrossLanguageCompatibleSerializer):
         return datetime.datetime.fromtimestamp(ts)
 
 
-COLLECTION_DEFAULT_FLAG = 0b0
-COLLECTION_TRACKING_REF = 0b1
-COLLECTION_HAS_NULL = 0b10
-COLLECTION_NOT_DECL_ELEMENT_TYPE = 0b100
-COLLECTION_NOT_SAME_TYPE = 0b1000
+COLL_DEFAULT_FLAG = 0b0
+COLL_TRACKING_REF = 0b1
+COLL_HAS_NULL = 0b10
+COLL_IS_DECL_ELEMENT_TYPE = 0b100
+COLL_IS_SAME_TYPE = 0b1000
+COLL_DECL_SAME_TYPE_TRACKING_REF = COLL_IS_DECL_ELEMENT_TYPE | 
COLL_IS_SAME_TYPE | COLL_TRACKING_REF
+COLL_DECL_SAME_TYPE_NOT_TRACKING_REF = COLL_IS_DECL_ELEMENT_TYPE | 
COLL_IS_SAME_TYPE
+COLL_DECL_SAME_TYPE_HAS_NULL = COLL_IS_DECL_ELEMENT_TYPE | COLL_IS_SAME_TYPE | 
COLL_HAS_NULL
+COLL_DECL_SAME_TYPE_NOT_HAS_NULL = COLL_IS_DECL_ELEMENT_TYPE | 
COLL_IS_SAME_TYPE
 
 
 class CollectionSerializer(Serializer):
@@ -242,40 +246,42 @@ class CollectionSerializer(Serializer):
         self.is_py = fory.is_py
 
     def write_header(self, buffer, value):
-        collect_flag = COLLECTION_DEFAULT_FLAG
+        collect_flag = COLL_DEFAULT_FLAG
         elem_type = self.elem_type
         elem_typeinfo = self.elem_typeinfo
         has_null = False
-        has_different_type = False
+        has_same_type = True
         if elem_type is None:
-            collect_flag |= COLLECTION_NOT_DECL_ELEMENT_TYPE
             for s in value:
                 if not has_null and s is None:
                     has_null = True
                     continue
                 if elem_type is None:
                     elem_type = type(s)
-                elif not has_different_type and type(s) is not elem_type:
-                    collect_flag |= COLLECTION_NOT_SAME_TYPE
-                    has_different_type = True
-            if not has_different_type and elem_type is not None:
-                elem_typeinfo = self.type_resolver.get_typeinfo(elem_type)
+                elif has_same_type and type(s) is not elem_type:
+                    has_same_type = False
+            if has_same_type:
+                collect_flag |= COLL_IS_SAME_TYPE
+                if elem_type is not None:
+                    elem_typeinfo = self.type_resolver.get_typeinfo(elem_type)
         else:
+            collect_flag |= COLL_IS_DECL_ELEMENT_TYPE | COLL_IS_SAME_TYPE
             for s in value:
                 if s is None:
                     has_null = True
                     break
+
         if has_null:
-            collect_flag |= COLLECTION_HAS_NULL
+            collect_flag |= COLL_HAS_NULL
         if self.fory.ref_tracking:
             if self.elem_tracking_ref == 1:
-                collect_flag |= COLLECTION_TRACKING_REF
+                collect_flag |= COLL_TRACKING_REF
             elif self.elem_tracking_ref == -1:
-                if has_different_type or 
elem_typeinfo.serializer.need_to_write_ref:
-                    collect_flag |= COLLECTION_TRACKING_REF
+                if not has_same_type or 
elem_typeinfo.serializer.need_to_write_ref:
+                    collect_flag |= COLL_TRACKING_REF
         buffer.write_varuint32(len(value))
         buffer.write_int8(collect_flag)
-        if not has_different_type and (collect_flag & 
COLLECTION_NOT_DECL_ELEMENT_TYPE) != 0:
+        if has_same_type and (collect_flag & COLL_IS_DECL_ELEMENT_TYPE) == 0:
             self.type_resolver.write_typeinfo(buffer, elem_typeinfo)
         return collect_flag, elem_typeinfo
 
@@ -284,8 +290,8 @@ class CollectionSerializer(Serializer):
             buffer.write_varuint32(0)
             return
         collect_flag, typeinfo = self.write_header(buffer, value)
-        if (collect_flag & COLLECTION_NOT_SAME_TYPE) == 0:
-            if (collect_flag & COLLECTION_TRACKING_REF) == 0:
+        if (collect_flag & COLL_IS_SAME_TYPE) != 0:
+            if (collect_flag & COLL_TRACKING_REF) == 0:
                 self._write_same_type_no_ref(buffer, value, typeinfo)
             else:
                 self._write_same_type_ref(buffer, value, typeinfo)
@@ -326,12 +332,12 @@ class CollectionSerializer(Serializer):
         if len_ == 0:
             return collection_
         collect_flag = buffer.read_int8()
-        if (collect_flag & COLLECTION_NOT_SAME_TYPE) == 0:
-            if collect_flag & COLLECTION_NOT_DECL_ELEMENT_TYPE != 0:
+        if (collect_flag & COLL_IS_SAME_TYPE) != 0:
+            if collect_flag & COLL_IS_DECL_ELEMENT_TYPE == 0:
                 typeinfo = self.type_resolver.read_typeinfo(buffer)
             else:
                 typeinfo = self.elem_typeinfo
-            if (collect_flag & COLLECTION_TRACKING_REF) == 0:
+            if (collect_flag & COLL_TRACKING_REF) == 0:
                 self._read_same_type_no_ref(buffer, len_, collection_, 
typeinfo)
             else:
                 self._read_same_type_ref(buffer, len_, collection_, typeinfo)
diff --git a/python/pyfory/tests/test_cross_language.py 
b/python/pyfory/tests/test_cross_language.py
index b78337004..94206b59b 100644
--- a/python/pyfory/tests/test_cross_language.py
+++ b/python/pyfory/tests/test_cross_language.py
@@ -633,7 +633,7 @@ def test_register_serializer(data_file_path):
     new_buf = pyfory.Buffer.allocate(32)
     fory.serialize(new_obj, buffer=new_buf)
     bytes1 = fory.serialize(new_obj)
-    assert len(bytes1) == len(data_bytes)
+    assert len(bytes1) == len(data_bytes), (bytes1, data_bytes)
     # header can be different to embed writer info like language
     assert bytes1[8:] == data_bytes[8:]
     assert fory.deserialize(fory.serialize(new_obj)) == new_obj, new_obj


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


Reply via email to