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 370addbfc refactor(dart): aligned dart internal implementation (#3601)
370addbfc is described below

commit 370addbfc59398f0b83a60f6e23213cfb710c24b
Author: Geethapranay1 <[email protected]>
AuthorDate: Wed Apr 22 08:32:04 2026 +0530

    refactor(dart): aligned dart internal implementation (#3601)
    
    ## Why?
    The dart implementation's internal collections and map serializers were
    previously structured differently than the java and c# runtimes, using
    raw hex bitmasks and monolithic methods which made reading the code
    difficult.
    
    
    
    
    ## What does this PR do?
    - extracts chunk/header magic numbers into `MapFlags` and
    `CollectionFlags`.
    - breaks down `ListSerializer.writePayload` into
    `_writeSameTypeElements` and `_writeDifferentTypeElements`.
    - adds identical depth getters to writecontext and readcontext.
    - maintained dart proper `maxDepth` spec enforcement on both read/write
    bounds.
    
    
    
    
    ## Related issues
    Fixes #3595
    
    
    ## AI Contribution Checklist
    
    
    
    - [ ] Substantial AI assistance was used in this PR: `yes` / `no`
    - [ ] If `yes`, I included a completed [AI Contribution
    
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
    in this PR description and the required `AI Usage Disclosure`.
    - [ ] If `yes`, my PR description includes the required `ai_review`
    summary and screenshot evidence of the final clean AI review results
    from both fresh reviewers on the current PR diff or current HEAD after
    the latest code changes.
    
    
    
    ## 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
---
 .../fory/lib/src/context/read_context.dart         |   2 +
 .../fory/lib/src/context/write_context.dart        |   2 +
 .../lib/src/serializer/collection_serializers.dart | 414 +++++++++++----------
 .../fory/lib/src/serializer/map_serializers.dart   |  53 +--
 4 files changed, 260 insertions(+), 211 deletions(-)

diff --git a/dart/packages/fory/lib/src/context/read_context.dart 
b/dart/packages/fory/lib/src/context/read_context.dart
index d2c5a6d54..1945e5ae0 100644
--- a/dart/packages/fory/lib/src/context/read_context.dart
+++ b/dart/packages/fory/lib/src/context/read_context.dart
@@ -124,6 +124,8 @@ final class ReadContext {
     }
     return value;
   }
+  
+  int get depth => _depth;
 
   /// Records entry into one more nested read frame.
   void increaseDepth() {
diff --git a/dart/packages/fory/lib/src/context/write_context.dart 
b/dart/packages/fory/lib/src/context/write_context.dart
index 2808f031d..f5fec0e48 100644
--- a/dart/packages/fory/lib/src/context/write_context.dart
+++ b/dart/packages/fory/lib/src/context/write_context.dart
@@ -105,6 +105,8 @@ final class WriteContext {
   set structWriteSlots(StructWriteSlots? value) {
     _structWriteSlots = value;
   }
+  
+  int get depth => _depth;
 
   /// Records entry into one more nested write frame.
   void increaseDepth() {
diff --git a/dart/packages/fory/lib/src/serializer/collection_serializers.dart 
b/dart/packages/fory/lib/src/serializer/collection_serializers.dart
index 828a6ac77..d4d59a6ea 100644
--- a/dart/packages/fory/lib/src/serializer/collection_serializers.dart
+++ b/dart/packages/fory/lib/src/serializer/collection_serializers.dart
@@ -28,6 +28,13 @@ import 'package:fory/src/serializer/scalar_serializers.dart';
 import 'package:fory/src/serializer/serializer.dart';
 import 'package:fory/src/serializer/serializer_support.dart';
 
+abstract final class CollectionFlags {
+  static const int trackingRef = 0x01;
+  static const int hasNull = 0x02;
+  static const int isDeclaredElementType = 0x04;
+  static const int isSameType = 0x08;
+}
+
 @pragma('vm:prefer-inline')
 void _writeDirectTypeInfoValue(
   WriteContext context,
@@ -277,26 +284,19 @@ final class ListSerializer extends Serializer<List> {
           elementFieldType!,
           declaredTypeInfo,
         );
-    final analysis = _analyzeListHeader(
+    final analysis = _analyzeElementsHeader(
       context,
       values,
       usesDeclaredType: usesDeclaredType,
     );
     final elementTrackRef = (elementFieldType?.ref ?? false) ||
         (elementFieldType == null && trackRef);
-    var header = 0;
-    if (elementTrackRef) {
-      header |= 0x01;
-    }
-    if (analysis.hasNull) {
-      header |= 0x02;
-    }
-    if (usesDeclaredType) {
-      header |= 0x04;
-    }
-    if (analysis.sameType) {
-      header |= 0x08;
-    }
+    final header = _buildCollectionHeader(
+      trackRef: elementTrackRef,
+      hasNull: analysis.hasNull,
+      usesDeclaredType: usesDeclaredType,
+      sameType: analysis.sameType,
+    );
     context.buffer.writeUint8(header);
     final sameTypeInfo =
         !usesDeclaredType && analysis.sameType ? analysis.sameTypeInfo : null;
@@ -309,129 +309,33 @@ final class ListSerializer extends Serializer<List> {
       );
     }
     if (declaredTypeInfo != null) {
-      final tracksDepth = tracksNestedPayloadDepth(declaredTypeInfo);
-      if (tracksDepth) {
-        context.increaseDepth();
-      }
-      for (final value in values) {
-        if (value == null) {
-          context.buffer.writeByte(RefWriter.nullFlag);
-          continue;
-        }
-        if (elementTrackRef) {
-          writeTypeInfoValue(
-            context,
-            declaredTypeInfo,
-            elementFieldType,
-            value as Object,
-            trackRef: true,
-          );
-        } else if (analysis.hasNull) {
-          context.buffer.writeByte(RefWriter.notNullValueFlag);
-          _writeDirectTypeInfoValue(
-            context,
-            declaredTypeInfo,
-            elementFieldType,
-            value as Object,
-          );
-        } else {
-          _writeDirectTypeInfoValue(
-            context,
-            declaredTypeInfo,
-            elementFieldType,
-            value as Object,
-          );
-        }
-      }
-      if (tracksDepth) {
-        context.decreaseDepth();
-      }
+      _writeSameTypeElements(
+        context,
+        values,
+        declaredTypeInfo,
+        elementFieldType,
+        elementTrackRef,
+        analysis.hasNull,
+      );
       return;
     }
     if (sameTypeInfo != null) {
-      final tracksDepth = tracksNestedPayloadDepth(sameTypeInfo);
-      if (tracksDepth) {
-        context.increaseDepth();
-      }
-      for (final value in values) {
-        if (value == null) {
-          context.buffer.writeByte(RefWriter.nullFlag);
-        } else if (elementTrackRef) {
-          writeTypeInfoValue(
-            context,
-            sameTypeInfo,
-            null,
-            value as Object,
-            trackRef: true,
-          );
-        } else if (analysis.hasNull) {
-          context.buffer.writeByte(RefWriter.notNullValueFlag);
-          _writeDirectTypeInfoValue(
-            context,
-            sameTypeInfo,
-            null,
-            value as Object,
-          );
-        } else {
-          _writeDirectTypeInfoValue(
-            context,
-            sameTypeInfo,
-            null,
-            value as Object,
-          );
-        }
-      }
-      if (tracksDepth) {
-        context.decreaseDepth();
-      }
+      _writeSameTypeElements(
+        context,
+        values,
+        sameTypeInfo,
+        usesDeclaredType ? elementFieldType : null,
+        elementTrackRef,
+        analysis.hasNull,
+      );
       return;
     }
-    for (final value in values) {
-      if (analysis.sameType && analysis.sameTypeInfo != null) {
-        if (value == null) {
-          context.buffer.writeByte(RefWriter.nullFlag);
-        } else if (elementTrackRef) {
-          final handled = context.refWriter.writeRefOrNull(
-            context.buffer,
-            value,
-            trackRef: analysis.sameTypeInfo!.supportsRef,
-          );
-          if (!handled) {
-            context.writeResolvedValue(
-              analysis.sameTypeInfo!,
-              value as Object,
-              null,
-            );
-          }
-        } else if (analysis.hasNull) {
-          context.buffer.writeByte(RefWriter.notNullValueFlag);
-          context.writeResolvedValue(
-            analysis.sameTypeInfo!,
-            value as Object,
-            null,
-          );
-        } else {
-          context.writeResolvedValue(
-            analysis.sameTypeInfo!,
-            value as Object,
-            null,
-          );
-        }
-        continue;
-      }
-      if (elementTrackRef) {
-        context.writeRef(value);
-      } else if (analysis.hasNull) {
-        if (value == null) {
-          context.buffer.writeByte(RefWriter.nullFlag);
-        } else {
-          context.buffer.writeByte(RefWriter.notNullValueFlag);
-          context.writeNonRef(value as Object);
-        }
-      } else {
-        context.writeNonRef(value as Object);
-      }
-    }
+    _writeDifferentTypeElements(
+      context,
+      values,
+      analysis,
+      elementTrackRef,
+    );
   }
 
   static List<Object?> readPayload(
@@ -527,6 +431,127 @@ Set<T> readTypedSetPayload<T>(
   return Set<T>.of(readTypedListPayload(context, elementFieldType, convert));
 }
 
+int _buildCollectionHeader({
+  required bool trackRef,
+  required bool hasNull,
+  required bool usesDeclaredType,
+  required bool sameType,
+}) {
+  var header = 0;
+  if (trackRef) {
+    header |= CollectionFlags.trackingRef;
+  }
+  if (hasNull) {
+    header |= CollectionFlags.hasNull;
+  }
+  if (usesDeclaredType) {
+    header |= CollectionFlags.isDeclaredElementType;
+  }
+  if (sameType) {
+    header |= CollectionFlags.isSameType;
+  }
+  return header;
+}
+
+void _writeSameTypeElements(
+  WriteContext context,
+  Iterable values,
+  TypeInfo typeInfo,
+  FieldType? fieldType,
+  bool trackRef,
+  bool hasNull,
+) {
+  final tracksDepth = tracksNestedPayloadDepth(typeInfo);
+  if (tracksDepth) {
+    context.increaseDepth();
+  }
+  for (final value in values) {
+    if (value == null) {
+      context.buffer.writeByte(RefWriter.nullFlag);
+    } else if (trackRef) {
+      writeTypeInfoValue(
+        context,
+        typeInfo,
+        fieldType,
+        value as Object,
+        trackRef: true,
+      );
+    } else if (hasNull) {
+      context.buffer.writeByte(RefWriter.notNullValueFlag);
+      _writeDirectTypeInfoValue(
+        context,
+        typeInfo,
+        fieldType,
+        value as Object,
+      );
+    } else {
+      _writeDirectTypeInfoValue(
+        context,
+        typeInfo,
+        fieldType,
+        value as Object,
+      );
+    }
+  }
+  if (tracksDepth) {
+    context.decreaseDepth();
+  }
+}
+
+void _writeDifferentTypeElements(
+  WriteContext context,
+  Iterable values,
+  _ElementsHeaderAnalysis analysis,
+  bool trackRef,
+) {
+  for (final value in values) {
+    if (analysis.sameType && analysis.sameTypeInfo != null) {
+      if (value == null) {
+        context.buffer.writeByte(RefWriter.nullFlag);
+      } else if (trackRef) {
+        final handled = context.refWriter.writeRefOrNull(
+          context.buffer,
+          value,
+          trackRef: analysis.sameTypeInfo!.supportsRef,
+        );
+        if (!handled) {
+          context.writeResolvedValue(
+            analysis.sameTypeInfo!,
+            value as Object,
+            null,
+          );
+        }
+      } else if (analysis.hasNull) {
+        context.buffer.writeByte(RefWriter.notNullValueFlag);
+        context.writeResolvedValue(
+          analysis.sameTypeInfo!,
+          value as Object,
+          null,
+        );
+      } else {
+        context.writeResolvedValue(
+          analysis.sameTypeInfo!,
+          value as Object,
+          null,
+        );
+      }
+      continue;
+    }
+    if (trackRef) {
+      context.writeRef(value);
+    } else if (analysis.hasNull) {
+      if (value == null) {
+        context.buffer.writeByte(RefWriter.nullFlag);
+      } else {
+        context.buffer.writeByte(RefWriter.notNullValueFlag);
+        context.writeNonRef(value as Object);
+      }
+    } else {
+      context.writeNonRef(value as Object);
+    }
+  }
+}
+
 final class _PreparedListRead {
   final int size;
   final bool trackRef;
@@ -572,10 +597,11 @@ _PreparedListRead _prepareListRead(
     );
   }
   final header = context.buffer.readUint8();
-  final trackRef = (header & 0x01) == 1;
-  final hasNull = (header & 0x02) != 0;
-  final usesDeclaredType = (header & 0x04) != 0;
-  final sameType = (header & 0x08) != 0;
+  final trackRef = (header & CollectionFlags.trackingRef) != 0;
+  final hasNull = (header & CollectionFlags.hasNull) != 0;
+  final usesDeclaredType =
+      (header & CollectionFlags.isDeclaredElementType) != 0;
+  final sameType = (header & CollectionFlags.isSameType) != 0;
   final declaredTypeInfo = usesDeclaredType && elementFieldType != null
       ? context.typeResolver.resolveFieldType(
           elementFieldType.withRootOverrides(nullable: hasNull, ref: trackRef),
@@ -604,58 +630,22 @@ Object? _readPreparedListItem(
   _PreparedListRead state,
 ) {
   if (state.declaredTypeInfo != null) {
-    if (state.hasNull || state.trackRef) {
-      final flag = context.refReader.tryPreserveRefId(context.buffer);
-      final preservedRefId = flag >= RefWriter.refValueFlag ? flag : null;
-      if (flag == RefWriter.nullFlag) {
-        return null;
-      }
-      if (flag == RefWriter.refFlag) {
-        return context.refReader.getReadRef();
-      }
-      final value = readTypeInfoValue(
-        context,
-        state.declaredTypeInfo!,
-        state.elementFieldType,
-        hasPreservedRef: preservedRefId != null,
-      );
-      if (preservedRefId != null &&
-          state.declaredTypeInfo!.supportsRef &&
-          context.refReader.readRefAt(preservedRefId) == null) {
-        context.refReader.setReadRef(preservedRefId, value);
-      }
-      return value;
-    }
-    return readTypeInfoValue(
+    return _readSameTypeElement(
       context,
       state.declaredTypeInfo!,
       state.elementFieldType,
+      state.trackRef,
+      state.hasNull,
     );
   }
   if (state.sameTypeInfo != null) {
-    if (state.hasNull || state.trackRef) {
-      final flag = context.refReader.tryPreserveRefId(context.buffer);
-      final preservedRefId = flag >= RefWriter.refValueFlag ? flag : null;
-      if (flag == RefWriter.nullFlag) {
-        return null;
-      }
-      if (flag == RefWriter.refFlag) {
-        return context.refReader.getReadRef();
-      }
-      final value = readTypeInfoValue(
-        context,
-        state.sameTypeInfo!,
-        null,
-        hasPreservedRef: preservedRefId != null,
-      );
-      if (preservedRefId != null &&
-          state.sameTypeInfo!.supportsRef &&
-          context.refReader.readRefAt(preservedRefId) == null) {
-        context.refReader.setReadRef(preservedRefId, value);
-      }
-      return value;
-    }
-    return readTypeInfoValue(context, state.sameTypeInfo!, null);
+    return _readSameTypeElement(
+      context,
+      state.sameTypeInfo!,
+      null,
+      state.trackRef,
+      state.hasNull,
+    );
   }
   if (state.usesDeclaredType && state.elementFieldType != null) {
     return readFieldTypeValue<Object?>(
@@ -689,10 +679,56 @@ Object? _readPreparedListItem(
     }
     return context.readResolvedValue(state.sameTypeInfo!, null);
   }
-  if (state.trackRef) {
+  return _readDifferentTypeElement(
+    context,
+    state.trackRef,
+    state.hasNull,
+  );
+}
+
+@pragma('vm:prefer-inline')
+Object? _readSameTypeElement(
+  ReadContext context,
+  TypeInfo typeInfo,
+  FieldType? fieldType,
+  bool trackRef,
+  bool hasNull,
+) {
+  if (hasNull || trackRef) {
+    final flag = context.refReader.tryPreserveRefId(context.buffer);
+    final preservedRefId = flag >= RefWriter.refValueFlag ? flag : null;
+    if (flag == RefWriter.nullFlag) {
+      return null;
+    }
+    if (flag == RefWriter.refFlag) {
+      return context.refReader.getReadRef();
+    }
+    final value = readTypeInfoValue(
+      context,
+      typeInfo,
+      fieldType,
+      hasPreservedRef: preservedRefId != null,
+    );
+    if (preservedRefId != null &&
+        typeInfo.supportsRef &&
+        context.refReader.readRefAt(preservedRefId) == null) {
+      context.refReader.setReadRef(preservedRefId, value);
+    }
+    return value;
+  }
+  return readTypeInfoValue(context, typeInfo, fieldType);
+}
+
+@pragma('vm:prefer-inline')
+Object? _readDifferentTypeElement(
+  ReadContext context,
+  bool trackRef,
+  bool hasNull,
+) {
+  if (trackRef) {
     return context.readRef();
   }
-  if (state.hasNull) {
+  if (hasNull) {
     return context.readNullable();
   }
   return context.readNonRef();
@@ -720,7 +756,7 @@ void writeTypeInfoValue(
   }
 }
 
-_ListHeaderAnalysis _analyzeListHeader(
+_ElementsHeaderAnalysis _analyzeElementsHeader(
   WriteContext context,
   Iterable values, {
   required bool usesDeclaredType,
@@ -733,7 +769,7 @@ _ListHeaderAnalysis _analyzeListHeader(
         break;
       }
     }
-    return _ListHeaderAnalysis(
+    return _ElementsHeaderAnalysis(
       hasNull: hasNull,
       sameType: true,
       sameTypeInfo: null,
@@ -762,7 +798,7 @@ _ListHeaderAnalysis _analyzeListHeader(
       sameType = false;
     }
   }
-  return _ListHeaderAnalysis(
+  return _ElementsHeaderAnalysis(
     hasNull: hasNull,
     sameType: sameType,
     sameTypeInfo: sameTypeInfo,
@@ -770,13 +806,13 @@ _ListHeaderAnalysis _analyzeListHeader(
   );
 }
 
-final class _ListHeaderAnalysis {
+final class _ElementsHeaderAnalysis {
   final bool hasNull;
   final bool sameType;
   final TypeInfo? sameTypeInfo;
   final Object? firstNonNull;
 
-  const _ListHeaderAnalysis({
+  const _ElementsHeaderAnalysis({
     required this.hasNull,
     required this.sameType,
     required this.sameTypeInfo,
diff --git a/dart/packages/fory/lib/src/serializer/map_serializers.dart 
b/dart/packages/fory/lib/src/serializer/map_serializers.dart
index 784924b89..57ae79030 100644
--- a/dart/packages/fory/lib/src/serializer/map_serializers.dart
+++ b/dart/packages/fory/lib/src/serializer/map_serializers.dart
@@ -26,6 +26,15 @@ import 'package:fory/src/resolver/type_resolver.dart';
 import 'package:fory/src/serializer/collection_serializers.dart';
 import 'package:fory/src/serializer/serializer.dart';
 
+abstract final class MapFlags {
+  static const int trackingKeyRef = 0x01;
+  static const int keyHasNull = 0x02;
+  static const int keyDeclaredType = 0x04;
+  static const int trackingValueRef = 0x08;
+  static const int valueHasNull = 0x10;
+  static const int valueDeclaredType = 0x20;
+}
+
 final class MapSerializer extends Serializer<Map> {
   const MapSerializer();
 
@@ -272,8 +281,8 @@ Map<K, V> readTypedMapPayload<K, V>(
   }
   while (remaining > 0) {
     final header = context.buffer.readUint8();
-    final keyHasNull = (header & 0x02) != 0;
-    final valueHasNull = (header & 0x10) != 0;
+    final keyHasNull = (header & MapFlags.keyHasNull) != 0;
+    final valueHasNull = (header & MapFlags.valueHasNull) != 0;
     if (keyHasNull || valueHasNull) {
       result[convertKey(
         _readNullChunkKey(
@@ -293,10 +302,10 @@ Map<K, V> readTypedMapPayload<K, V>(
       remaining -= 1;
       continue;
     }
-    final keyTrackRef = (header & 0x01) != 0;
-    final valueTrackRef = (header & 0x08) != 0;
-    final keyDeclared = (header & 0x04) != 0;
-    final valueDeclared = (header & 0x20) != 0;
+    final keyTrackRef = (header & MapFlags.trackingKeyRef) != 0;
+    final valueTrackRef = (header & MapFlags.trackingValueRef) != 0;
+    final keyDeclared = (header & MapFlags.keyDeclaredType) != 0;
+    final valueDeclared = (header & MapFlags.valueDeclaredType) != 0;
     final chunkSize = context.buffer.readUint8();
     final keyTypeInfo = keyDeclared ? null : context.readTypeMetaValue();
     final valueTypeInfo = valueDeclared ? null : context.readTypeMetaValue();
@@ -364,20 +373,20 @@ void _writeNullChunk(
 }) {
   var header = 0;
   if (key == null) {
-    header |= 0x02;
+    header |= MapFlags.keyHasNull;
   } else if (keyDeclared) {
-    header |= 0x04;
+    header |= MapFlags.keyDeclaredType;
   }
   if (keyTrackRef) {
-    header |= 0x01;
+    header |= MapFlags.trackingKeyRef;
   }
   if (value == null) {
-    header |= 0x10;
+    header |= MapFlags.valueHasNull;
   } else if (valueDeclared) {
-    header |= 0x20;
+    header |= MapFlags.valueDeclaredType;
   }
   if (valueTrackRef) {
-    header |= 0x08;
+    header |= MapFlags.trackingValueRef;
   }
   context.buffer.writeUint8(header);
   if (key != null) {
@@ -445,12 +454,12 @@ Object? _readNullChunkKey(
   FieldType? keyFieldType,
   TypeInfo? declaredKeyTypeInfo,
 ) {
-  final keyHasNull = (header & 0x02) != 0;
+  final keyHasNull = (header & MapFlags.keyHasNull) != 0;
   if (keyHasNull) {
     return null;
   }
-  final trackRef = (header & 0x01) != 0;
-  final declared = (header & 0x04) != 0;
+  final trackRef = (header & MapFlags.trackingKeyRef) != 0;
+  final declared = (header & MapFlags.keyDeclaredType) != 0;
   if (declared && keyFieldType != null) {
     return _readDeclaredMapValue(
       context,
@@ -468,12 +477,12 @@ Object? _readNullChunkValue(
   FieldType? valueFieldType,
   TypeInfo? declaredValueTypeInfo,
 ) {
-  final valueHasNull = (header & 0x10) != 0;
+  final valueHasNull = (header & MapFlags.valueHasNull) != 0;
   if (valueHasNull) {
     return null;
   }
-  final trackRef = (header & 0x08) != 0;
-  final declared = (header & 0x20) != 0;
+  final trackRef = (header & MapFlags.trackingValueRef) != 0;
+  final declared = (header & MapFlags.valueDeclaredType) != 0;
   if (declared && valueFieldType != null) {
     return _readDeclaredMapValue(
       context,
@@ -545,16 +554,16 @@ int _mapChunkHeader({
 }) {
   var header = 0;
   if (keyTrackRef) {
-    header |= 0x01;
+    header |= MapFlags.trackingKeyRef;
   }
   if (keyDeclared) {
-    header |= 0x04;
+    header |= MapFlags.keyDeclaredType;
   }
   if (valueTrackRef) {
-    header |= 0x08;
+    header |= MapFlags.trackingValueRef;
   }
   if (valueDeclared) {
-    header |= 0x20;
+    header |= MapFlags.valueDeclaredType;
   }
   return header;
 }


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

Reply via email to