@@ -44,6 +44,7 @@ type structSerializer struct {
4444 name string
4545 type_ reflect.Type
4646 structHash int32
47+ typeID uint32
4748
4849 // Pre-sorted and categorized fields (embedded for cache locality)
4950 fieldGroup FieldGroup
@@ -2253,14 +2254,64 @@ func (s *structSerializer) Read(ctx *ReadContext, refMode RefMode, readType bool
22532254 }
22542255 }
22552256 if readType {
2256- // Read type info - in compatible mode this returns the serializer with remote fieldDefs
2257+ if ! ctx .Compatible () && s .type_ != nil {
2258+ typeID := buf .ReadVaruint32Small7 (ctxErr )
2259+ if ctxErr .HasError () {
2260+ return
2261+ }
2262+ if s .typeID != 0 && typeID == s .typeID && ! IsNamespacedType (TypeId (typeID )) {
2263+ s .ReadData (ctx , value )
2264+ return
2265+ }
2266+ if IsNamespacedType (TypeId (typeID )) {
2267+ // Expected type is known: skip namespace/type meta and read data directly.
2268+ ctx .TypeResolver ().metaStringResolver .ReadMetaStringBytes (buf , ctxErr )
2269+ ctx .TypeResolver ().metaStringResolver .ReadMetaStringBytes (buf , ctxErr )
2270+ if ctxErr .HasError () {
2271+ return
2272+ }
2273+ s .ReadData (ctx , value )
2274+ return
2275+ }
2276+ internalTypeID := TypeId (typeID & 0xFF )
2277+ if internalTypeID == COMPATIBLE_STRUCT || internalTypeID == STRUCT {
2278+ typeInfo := ctx .TypeResolver ().readTypeInfoWithTypeID (buf , typeID , ctxErr )
2279+ if ctxErr .HasError () {
2280+ return
2281+ }
2282+ if structSer , ok := typeInfo .Serializer .(* structSerializer ); ok && len (structSer .fieldDefs ) > 0 {
2283+ structSer .ReadData (ctx , value )
2284+ return
2285+ }
2286+ if s .typeID != 0 && typeID == s .typeID {
2287+ s .ReadData (ctx , value )
2288+ return
2289+ }
2290+ }
2291+ ctx .SetError (DeserializationError ("unexpected type id for struct" ))
2292+ return
2293+ }
2294+ if s .type_ != nil {
2295+ serializer := ctx .TypeResolver ().ReadTypeInfoForType (buf , s .type_ , ctxErr )
2296+ if ctxErr .HasError () {
2297+ return
2298+ }
2299+ if serializer == nil {
2300+ ctx .SetError (DeserializationError ("unexpected type id for struct" ))
2301+ return
2302+ }
2303+ if structSer , ok := serializer .(* structSerializer ); ok && len (structSer .fieldDefs ) > 0 {
2304+ structSer .ReadData (ctx , value )
2305+ return
2306+ }
2307+ s .ReadData (ctx , value )
2308+ return
2309+ }
2310+ // Fallback: read type info based on typeID when expected type is unknown
22572311 typeID := buf .ReadVaruint32Small7 (ctxErr )
22582312 internalTypeID := TypeId (typeID & 0xFF )
2259- // Check if this is a struct type that needs type meta reading
22602313 if IsNamespacedType (TypeId (typeID )) || internalTypeID == COMPATIBLE_STRUCT || internalTypeID == STRUCT {
2261- // For struct types in compatible mode, use the serializer from TypeInfo
22622314 typeInfo := ctx .TypeResolver ().readTypeInfoWithTypeID (buf , typeID , ctxErr )
2263- // Use the serializer from TypeInfo which has the remote field definitions
22642315 if structSer , ok := typeInfo .Serializer .(* structSerializer ); ok && len (structSer .fieldDefs ) > 0 {
22652316 structSer .ReadData (ctx , value )
22662317 return
@@ -2419,31 +2470,61 @@ func (s *structSerializer) ReadData(ctx *ReadContext, value reflect.Value) {
24192470 // Note: For tagged int64/uint64, we can't use unsafe reads because they need bounds checking
24202471 if len (s .fieldGroup .PrimitiveVarintFields ) > 0 {
24212472 err := ctx .Err ()
2422- for _ , field := range s .fieldGroup .PrimitiveVarintFields {
2423- fieldPtr := unsafe .Add (ptr , field .Offset )
2424- optInfo := optionalInfo {}
2425- if field .Kind == FieldKindOptional && field .Meta != nil {
2426- optInfo = field .Meta .OptionalInfo
2473+ if buf .remaining () >= s .fieldGroup .MaxVarintSize {
2474+ for _ , field := range s .fieldGroup .PrimitiveVarintFields {
2475+ fieldPtr := unsafe .Add (ptr , field .Offset )
2476+ optInfo := optionalInfo {}
2477+ if field .Kind == FieldKindOptional && field .Meta != nil {
2478+ optInfo = field .Meta .OptionalInfo
2479+ }
2480+ switch field .DispatchId {
2481+ case PrimitiveVarint32DispatchId :
2482+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .UnsafeReadVarint32 ())
2483+ case PrimitiveVarint64DispatchId :
2484+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .UnsafeReadVarint64 ())
2485+ case PrimitiveIntDispatchId :
2486+ storeFieldValue (field .Kind , fieldPtr , optInfo , int (buf .UnsafeReadVarint64 ()))
2487+ case PrimitiveVarUint32DispatchId :
2488+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .UnsafeReadVaruint32 ())
2489+ case PrimitiveVarUint64DispatchId :
2490+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .UnsafeReadVaruint64 ())
2491+ case PrimitiveUintDispatchId :
2492+ storeFieldValue (field .Kind , fieldPtr , optInfo , uint (buf .UnsafeReadVaruint64 ()))
2493+ case PrimitiveTaggedInt64DispatchId :
2494+ // Tagged INT64: use buffer's tagged decoding (4 bytes for small, 9 for large)
2495+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadTaggedInt64 (err ))
2496+ case PrimitiveTaggedUint64DispatchId :
2497+ // Tagged UINT64: use buffer's tagged decoding (4 bytes for small, 9 for large)
2498+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadTaggedUint64 (err ))
2499+ }
24272500 }
2428- switch field .DispatchId {
2429- case PrimitiveVarint32DispatchId :
2430- storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadVarint32 (err ))
2431- case PrimitiveVarint64DispatchId :
2432- storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadVarint64 (err ))
2433- case PrimitiveIntDispatchId :
2434- storeFieldValue (field .Kind , fieldPtr , optInfo , int (buf .ReadVarint64 (err )))
2435- case PrimitiveVarUint32DispatchId :
2436- storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadVaruint32 (err ))
2437- case PrimitiveVarUint64DispatchId :
2438- storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadVaruint64 (err ))
2439- case PrimitiveUintDispatchId :
2440- storeFieldValue (field .Kind , fieldPtr , optInfo , uint (buf .ReadVaruint64 (err )))
2441- case PrimitiveTaggedInt64DispatchId :
2442- // Tagged INT64: use buffer's tagged decoding (4 bytes for small, 9 for large)
2443- storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadTaggedInt64 (err ))
2444- case PrimitiveTaggedUint64DispatchId :
2445- // Tagged UINT64: use buffer's tagged decoding (4 bytes for small, 9 for large)
2446- storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadTaggedUint64 (err ))
2501+ } else {
2502+ for _ , field := range s .fieldGroup .PrimitiveVarintFields {
2503+ fieldPtr := unsafe .Add (ptr , field .Offset )
2504+ optInfo := optionalInfo {}
2505+ if field .Kind == FieldKindOptional && field .Meta != nil {
2506+ optInfo = field .Meta .OptionalInfo
2507+ }
2508+ switch field .DispatchId {
2509+ case PrimitiveVarint32DispatchId :
2510+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadVarint32 (err ))
2511+ case PrimitiveVarint64DispatchId :
2512+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadVarint64 (err ))
2513+ case PrimitiveIntDispatchId :
2514+ storeFieldValue (field .Kind , fieldPtr , optInfo , int (buf .ReadVarint64 (err )))
2515+ case PrimitiveVarUint32DispatchId :
2516+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadVaruint32 (err ))
2517+ case PrimitiveVarUint64DispatchId :
2518+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadVaruint64 (err ))
2519+ case PrimitiveUintDispatchId :
2520+ storeFieldValue (field .Kind , fieldPtr , optInfo , uint (buf .ReadVaruint64 (err )))
2521+ case PrimitiveTaggedInt64DispatchId :
2522+ // Tagged INT64: use buffer's tagged decoding (4 bytes for small, 9 for large)
2523+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadTaggedInt64 (err ))
2524+ case PrimitiveTaggedUint64DispatchId :
2525+ // Tagged UINT64: use buffer's tagged decoding (4 bytes for small, 9 for large)
2526+ storeFieldValue (field .Kind , fieldPtr , optInfo , buf .ReadTaggedUint64 (err ))
2527+ }
24472528 }
24482529 }
24492530 }
0 commit comments