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 ff0946e60 refactor(xlang): use 0 for unknow type id (#2985)
ff0946e60 is described below

commit ff0946e60b5702d4d904c3f20d9b1b2f9d60bf07
Author: Shawn Yang <[email protected]>
AuthorDate: Thu Dec 4 13:07:31 2025 +0800

    refactor(xlang): use 0 for unknow type id (#2985)
    
    ## Why?
    
    
    
    ## What does this PR do?
    
    use 0 for unknow type id
    
    ## Related issues
    
    
    
    ## Does this PR introduce any user-facing change?
    
    
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
---
 cpp/fory/type/type.h                                             | 7 ++++---
 .../fory-test/test/codegen_test/struct_codegen_test.dart         | 2 +-
 .../packages/fory/lib/src/codegen/analyze/analysis_wrappers.dart | 2 +-
 dart/packages/fory/lib/src/const/dart_type.dart                  | 4 ++--
 dart/packages/fory/lib/src/const/obj_type.dart                   | 5 +++--
 dart/packages/fory/lib/src/resolver/struct_hash_resolver.dart    | 2 +-
 go/fory/fory.go                                                  | 9 +++++++++
 go/fory/type.go                                                  | 9 +++++----
 .../src/main/java/org/apache/fory/resolver/XtypeResolver.java    | 2 +-
 java/fory-core/src/main/java/org/apache/fory/type/Types.java     | 6 +++++-
 javascript/packages/fory/lib/type.ts                             | 2 ++
 python/pyfory/_registry.py                                       | 2 +-
 python/pyfory/_struct.py                                         | 3 +--
 python/pyfory/includes/libformat.pxd                             | 2 +-
 python/pyfory/type.py                                            | 8 +++-----
 rust/fory-core/src/resolver/type_resolver.rs                     | 8 ++++----
 rust/fory-core/src/types.rs                                      | 9 +++++++--
 17 files changed, 51 insertions(+), 31 deletions(-)

diff --git a/cpp/fory/type/type.h b/cpp/fory/type/type.h
index cface254e..4cf0765ff 100644
--- a/cpp/fory/type/type.h
+++ b/cpp/fory/type/type.h
@@ -23,6 +23,8 @@
 
 namespace fory {
 enum class TypeId : int32_t {
+  // Unknown/polymorphic type marker.
+  UNKNOWN = 0,
   // a boolean value (true or false).
   BOOL = 1,
   // an 8-bit signed integer.
@@ -101,9 +103,8 @@ enum class TypeId : int32_t {
   FLOAT32_ARRAY = 36,
   // one-dimensional float64 array.
   FLOAT64_ARRAY = 37,
-  // Unknown/polymorphic type marker.
-  UNKNOWN = 64,
-  // Bound value, typically used as a sentinel value.
+  // Bound value for range checks (types with id >= BOUND are not internal
+  // types).
   BOUND = 64
 };
 
diff --git a/dart/packages/fory-test/test/codegen_test/struct_codegen_test.dart 
b/dart/packages/fory-test/test/codegen_test/struct_codegen_test.dart
index 93adcfc14..7ea77da5c 100644
--- a/dart/packages/fory-test/test/codegen_test/struct_codegen_test.dart
+++ b/dart/packages/fory-test/test/codegen_test/struct_codegen_test.dart
@@ -34,7 +34,7 @@ void main(){
         [
           FieldSpec(
             'f1',
-            TypeSpec(Object, ObjType.UNKNOWN_YET, false, false, null, const 
[],),
+            TypeSpec(Object, ObjType.UNKNOWN, false, false, null, const [],),
             true,
             true,
             (Object inst) => (inst as ComplexObject2).f1,
diff --git a/dart/packages/fory/lib/src/codegen/analyze/analysis_wrappers.dart 
b/dart/packages/fory/lib/src/codegen/analyze/analysis_wrappers.dart
index 0129767db..3eae799a1 100644
--- a/dart/packages/fory/lib/src/codegen/analyze/analysis_wrappers.dart
+++ b/dart/packages/fory/lib/src/codegen/analyze/analysis_wrappers.dart
@@ -25,7 +25,7 @@ typedef TypeDecision = ({InterfaceType type, bool 
forceNullable});
 class ObjTypeWrapper{
   static const namedEnum = ObjTypeWrapper(ObjType.NAMED_ENUM, true,);
   static const namedStruct = ObjTypeWrapper(ObjType.NAMED_STRUCT, false);
-  static const unknownStruct = ObjTypeWrapper(ObjType.UNKNOWN_YET, false);
+  static const unknownStruct = ObjTypeWrapper(ObjType.UNKNOWN, false);
 
   final ObjType objType; // null means unsupported
   final bool certainForSer;
diff --git a/dart/packages/fory/lib/src/const/dart_type.dart 
b/dart/packages/fory/lib/src/const/dart_type.dart
index 2ec9c7e16..41561402e 100644
--- a/dart/packages/fory/lib/src/const/dart_type.dart
+++ b/dart/packages/fory/lib/src/const/dart_type.dart
@@ -75,7 +75,7 @@ enum DartTypeEnum{
   DECIMAL(Decimal,true, 'Decimal', 'package', 'decimal/decimal.dart', null, 
true, 'package:decimal/decimal.dart@Decimal'),
   DURATION(Duration,true, 'Duration', 'dart', 'core', null, 
true,'dart:core@Duration'),;
   
-  // NUM(num, false, 'num', 'dart', 'core', ObjType.UNKNOWN_YET, 
'dart:core@num'),
+  // NUM(num, false, 'num', 'dart', 'core', ObjType.UNKNOWN, 'dart:core@num'),
 
   final String scheme;
   final String path;
@@ -108,7 +108,7 @@ enum DartTypeEnum{
   @Deprecated('use find')
   // TODO: Using this method requires that all DartTypeEnum names be unique 
and sorted in strict string order
   /// Returning null indicates it is definitely a Dart built-in type, which is 
unsupported
-  /// Returning UNKNOWN_YET means uncertain
+  /// Returning UNKNOWN means uncertain
   // TODO: Attempt to record the Dart analyzer's ID to achieve a numerical 
comparison
   static DartTypeEnum? _findDeprecated(String name, String scheme, String 
path){
     int l = 0;
diff --git a/dart/packages/fory/lib/src/const/obj_type.dart 
b/dart/packages/fory/lib/src/const/obj_type.dart
index 7183875cf..2bedcd7ec 100644
--- a/dart/packages/fory/lib/src/const/obj_type.dart
+++ b/dart/packages/fory/lib/src/const/obj_type.dart
@@ -22,8 +22,9 @@
 library;
 
 enum ObjType {
-  /// A NULL type having no physical storage
-  UNKNOWN_YET(0, false), // This value is not meaningless. For example, a 
field is a parent class/non-specific class, which cannot be analyzed during 
static code generation.
+  /// Unknown/polymorphic type marker. For example, a field is a parent 
class/non-specific class,
+  /// which cannot be analyzed during static code generation.
+  UNKNOWN(0, false),
 
   // x
   /// Boolean as 1 bit, LSB bit-packed ordering
diff --git a/dart/packages/fory/lib/src/resolver/struct_hash_resolver.dart 
b/dart/packages/fory/lib/src/resolver/struct_hash_resolver.dart
index 3debee9e4..bd6a94d67 100644
--- a/dart/packages/fory/lib/src/resolver/struct_hash_resolver.dart
+++ b/dart/packages/fory/lib/src/resolver/struct_hash_resolver.dart
@@ -71,7 +71,7 @@ class StructHashResolver{
       case ObjType.MAP:
         id = ObjType.MAP.id;
         break;
-      case ObjType.UNKNOWN_YET:
+      case ObjType.UNKNOWN:
         id = 0;
         break;
       default:
diff --git a/go/fory/fory.go b/go/fory/fory.go
index c55b26f4f..1d1068217 100644
--- a/go/fory/fory.go
+++ b/go/fory/fory.go
@@ -559,6 +559,15 @@ func (f *Fory) readData(buffer *ByteBuffer, value 
reflect.Value, serializer Seri
                default:
                        concrete = value
                        type_ = concrete.Type()
+                       // For slice types with concrete element types, prefer 
type-specific serializer
+                       // to ensure format compatibility between serialization 
and deserialization.
+                       // This is needed because LIST typeID is shared across 
all slice types,
+                       // but different slice types may use different 
serializers with different formats.
+                       if type_.Kind() == reflect.Slice && 
!isDynamicType(type_.Elem()) {
+                               if typeSpecific, err := 
f.typeResolver.getSerializerByType(type_, false); err == nil && typeSpecific != 
nil {
+                                       serializer = typeSpecific
+                               }
+                       }
                }
                if err := serializer.Read(f, buffer, type_, concrete); err != 
nil {
                        return err
diff --git a/go/fory/type.go b/go/fory/type.go
index 8834dcc5e..384323ec0 100644
--- a/go/fory/type.go
+++ b/go/fory/type.go
@@ -33,8 +33,8 @@ import (
 type TypeId = int16
 
 const (
-       // NA A NullFlag type having no physical storage
-       NA TypeId = iota // NA = 0
+       // UNKNOWN Unknown/polymorphic type marker
+       UNKNOWN = 0
        // BOOL Boolean as 1 bit LSB bit-packed ordering
        BOOL = 1
        // INT8 Signed 8-bit little-endian integer
@@ -113,8 +113,6 @@ const (
        ARROW_RECORD_BATCH = 38
        // ARROW_TABLE an arrow table object
        ARROW_TABLE = 39
-       // UNKNOWN an unknown type
-       UNKNOWN = 63
 
        // UINT8 Unsigned 8-bit little-endian integer
        UINT8 = 100 // Not in mapping table, assign a higher value
@@ -671,6 +669,9 @@ func (r *typeResolver) getTypeInfo(value reflect.Value, 
create bool) (TypeInfo,
        } else if isMultiDimensionaSlice(value) {
                typeID = LIST
                return r.typeIDToTypeInfo[typeID], nil
+       } else if value.Kind() == reflect.Slice {
+               // Regular slices are treated as LIST
+               typeID = LIST
        }
 
        // Register the type with full metadata
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java 
b/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
index 284b31803..60a6ce913 100644
--- a/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
+++ b/java/fory-core/src/main/java/org/apache/fory/resolver/XtypeResolver.java
@@ -494,7 +494,7 @@ public class XtypeResolver extends TypeResolver {
   }
 
   public ClassInfo getUserTypeInfo(int userTypeId) {
-    Preconditions.checkArgument((userTypeId & 0xff) < Types.UNKNOWN);
+    Preconditions.checkArgument((userTypeId & 0xff) < Types.BOUND);
     return xtypeIdToClassMap.get(userTypeId);
   }
 
diff --git a/java/fory-core/src/main/java/org/apache/fory/type/Types.java 
b/java/fory-core/src/main/java/org/apache/fory/type/Types.java
index 88212144d..051a2ea00 100644
--- a/java/fory-core/src/main/java/org/apache/fory/type/Types.java
+++ b/java/fory-core/src/main/java/org/apache/fory/type/Types.java
@@ -26,6 +26,9 @@ import org.apache.fory.util.Preconditions;
 
 public class Types {
 
+  /** Unknown/polymorphic type marker. */
+  public static final int UNKNOWN = 0;
+
   /** bool: a boolean value (true or false). */
   public static final int BOOL = 1;
 
@@ -156,7 +159,8 @@ public class Types {
   /** One dimensional float64 array. */
   public static final int FLOAT64_ARRAY = 37;
 
-  public static final int UNKNOWN = 63;
+  /** Bound value for range checks (types with id >= BOUND are not internal 
types). */
+  public static final int BOUND = 64;
 
   // Helper methods
   public static boolean isNamedType(int value) {
diff --git a/javascript/packages/fory/lib/type.ts 
b/javascript/packages/fory/lib/type.ts
index abd1a27a7..b4aaa0a25 100644
--- a/javascript/packages/fory/lib/type.ts
+++ b/javascript/packages/fory/lib/type.ts
@@ -20,6 +20,8 @@
 import { StructTypeInfo } from "./typeInfo";
 
 export const TypeId = {
+  // Unknown/polymorphic type marker.
+  UNKNOWN: 0,
   // a boolean value (true or false).
   BOOL: 1,
   // a 8-bit signed integer.
diff --git a/python/pyfory/_registry.py b/python/pyfory/_registry.py
index 7590cf238..f37c17830 100644
--- a/python/pyfory/_registry.py
+++ b/python/pyfory/_registry.py
@@ -254,7 +254,7 @@ class TypeResolver:
 
     def _initialize_common(self):
         register = functools.partial(self._register_type, internal=True)
-        register(None, type_id=TypeId.NA, serializer=NoneSerializer)
+        register(None, type_id=TypeId.UNKNOWN, serializer=NoneSerializer)
         register(bool, type_id=TypeId.BOOL, serializer=BooleanSerializer)
         register(int8, type_id=TypeId.INT8, serializer=ByteSerializer)
         register(int16, type_id=TypeId.INT16, serializer=Int16Serializer)
diff --git a/python/pyfory/_struct.py b/python/pyfory/_struct.py
index d31fe5bb5..f5edc9d47 100644
--- a/python/pyfory/_struct.py
+++ b/python/pyfory/_struct.py
@@ -189,8 +189,7 @@ def group_fields(type_resolver, field_names, serializers, 
nullable_map=None):
         }:
             container = other_types
         else:
-            assert TypeId.LOWER_BOUND < type_id < TypeId.UNKNOWN, (type_id,)
-            assert type_id != TypeId.UNKNOWN, serializer
+            assert TypeId.UNKNOWN < type_id < TypeId.BOUND, (type_id,)
             container = internal_types
         container.append((type_id, serializer, field_name))
 
diff --git a/python/pyfory/includes/libformat.pxd 
b/python/pyfory/includes/libformat.pxd
index abb0e3930..8baff7e78 100755
--- a/python/pyfory/includes/libformat.pxd
+++ b/python/pyfory/includes/libformat.pxd
@@ -77,7 +77,7 @@ cdef extern from "fory/type/type.h" namespace "fory" nogil:
         FLOAT16_ARRAY = 35
         FLOAT32_ARRAY = 36
         FLOAT64_ARRAY = 37
-        UNKNOWN = 64
+        UNKNOWN = 0
         BOUND = 64
 
 
diff --git a/python/pyfory/type.py b/python/pyfory/type.py
index 3b842ae89..6df38111b 100644
--- a/python/pyfory/type.py
+++ b/python/pyfory/type.py
@@ -142,9 +142,8 @@ class TypeId:
     See `org.apache.fory.types.Type`
     """
 
-    LOWER_BOUND = 0
-    # null value
-    NA = 0
+    # Unknown/polymorphic type marker.
+    UNKNOWN = 0
     # a boolean value (true or false).
     BOOL = 1
     # a 8-bit signed integer.
@@ -224,9 +223,8 @@ class TypeId:
     FLOAT32_ARRAY = 36
     # one dimensional float64 array.
     FLOAT64_ARRAY = 37
-    UNKNOWN = 63
 
-    # BOUND id remains at 64
+    # Bound value for range checks (types with id >= BOUND are not internal 
types).
     BOUND = 64
 
     @staticmethod
diff --git a/rust/fory-core/src/resolver/type_resolver.rs 
b/rust/fory-core/src/resolver/type_resolver.rs
index d39dde005..22adaed20 100644
--- a/rust/fory-core/src/resolver/type_resolver.rs
+++ b/rust/fory-core/src/resolver/type_resolver.rs
@@ -726,10 +726,10 @@ impl TypeResolver {
 
         // Check if type_id conflicts with any already registered type
         // Skip check for:
-        // 1. Internal types (type_id <= TypeId::UNKNOWN) as they can be shared
+        // 1. Internal types (type_id < TypeId::BOUND) as they can be shared
         // 2. Types registered by name (they use shared type IDs like 
NAMED_STRUCT)
         if !register_by_name
-            && actual_type_id > TypeId::UNKNOWN as u32
+            && actual_type_id >= TypeId::BOUND as u32
             && self.type_info_map_by_id.contains_key(&actual_type_id)
         {
             return Err(Error::type_error(format!(
@@ -917,8 +917,8 @@ impl TypeResolver {
         }
 
         // Check if type_id conflicts with any already registered type
-        // Skip check for internal types (type_id <= TypeId::UNKNOWN) as they 
can be shared
-        if actual_type_id > TypeId::UNKNOWN as u32
+        // Skip check for internal types (type_id < TypeId::BOUND) as they can 
be shared
+        if actual_type_id >= TypeId::BOUND as u32
             && self.type_info_map_by_id.contains_key(&actual_type_id)
         {
             return Err(Error::type_error(format!(
diff --git a/rust/fory-core/src/types.rs b/rust/fory-core/src/types.rs
index 669bb333d..6090a493e 100644
--- a/rust/fory-core/src/types.rs
+++ b/rust/fory-core/src/types.rs
@@ -42,6 +42,8 @@ pub enum RefFlag {
 #[allow(non_camel_case_types)]
 #[repr(i16)]
 pub enum TypeId {
+    // Unknown/polymorphic type marker.
+    UNKNOWN = 0,
     BOOL = 1,
     INT8 = 2,
     INT16 = 3,
@@ -93,7 +95,8 @@ pub enum TypeId {
     U64_ARRAY = 75,
     USIZE_ARRAY = 76,
     U128_ARRAY = 77,
-    UNKNOWN = 78,
+    // Bound value for range checks (types with id >= BOUND are not internal 
types).
+    BOUND = 78,
 }
 
 pub const BOOL: u32 = TypeId::BOOL as u32;
@@ -148,6 +151,7 @@ pub const U64_ARRAY: u32 = TypeId::U64_ARRAY as u32;
 pub const USIZE_ARRAY: u32 = TypeId::USIZE_ARRAY as u32;
 pub const U128_ARRAY: u32 = TypeId::U128_ARRAY as u32;
 pub const UNKNOWN: u32 = TypeId::UNKNOWN as u32;
+pub const BOUND: u32 = TypeId::BOUND as u32;
 
 const MAX_UNT32: u64 = (1 << 31) - 1;
 
@@ -289,9 +293,10 @@ pub const fn is_primitive_type_id(type_id: TypeId) -> bool 
{
 }
 
 /// Keep as const fn for compile time evaluation or constant folding
+/// Internal types are all types in `0 < id < BOUND` that are not 
struct/ext/enum types.
 #[inline(always)]
 pub const fn is_internal_type(type_id: u32) -> bool {
-    if type_id == 0 || type_id >= TypeId::UNKNOWN as u32 {
+    if type_id == UNKNOWN || type_id >= BOUND {
         return false;
     }
     !matches!(


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

Reply via email to