Skip to content

feat(dart): add uint annotation types to the fory's codegen system#3181

Merged
chaokunyang merged 11 commits intoapache:mainfrom
ayush00git:feat/dart-codegen
Jan 22, 2026
Merged

feat(dart): add uint annotation types to the fory's codegen system#3181
chaokunyang merged 11 commits intoapache:mainfrom
ayush00git:feat/dart-codegen

Conversation

@ayush00git
Copy link
Contributor

Why?

While unsigned integer type annotations (@Uint8Type, @Uint16Type, @Uint32Type, @Uint64Type) were added in PR #3144, they were not integrated into the code generation system. This meant:

  • The annotation definitions existed but were not recognized by the code generator
  • No support for annotation-based type specification like @Uint8Type() int age in struct fields
  • Users couldn't use the protobuf/flatbuffer-style ergonomic API that was intended
  • No way to specify encoding variants (fixed vs varint) for uint32/uint64 via annotations during code generation

What does this PR do?

1. Created Uint Annotation Analyzer

Added uint_annotation_analyzer.dart to detect and parse uint type annotations during code generation:

class UintAnnotationAnalyzer {
  UintAnnotationResult analyze(
    List<ElementAnnotation> metadata,
    LocationMark locationMark,
  ) {
    // Detects @Uint8Type, @Uint16Type, @Uint32Type, @Uint64Type
    // Extracts encoding options (fixed, varint, tagged)
    // Returns appropriate ObjType
  }
}

Supported annotations:

  • @Uint8Type()ObjType.UINT8
  • @Uint16Type()ObjType.UINT16
  • @Uint32Type()ObjType.UINT32
  • @Uint32Type(encoding: UintEncoding.varint)ObjType.VAR_UINT32
  • @Uint64Type()ObjType.UINT64
  • @Uint64Type(encoding: UintEncoding.varint)ObjType.VAR_UINT64
  • @Uint64Type(encoding: UintEncoding.tagged)ObjType.TAGGED_UINT64

2. Extended Type Identifier System

Updated analysis_type_identifier.dart to recognize uint annotation types:

static final List<Type3StringKey> _keys = [
  // ... existing annotations
  Type3StringKey('Uint8Type', 'package', 'fory/src/annotation/uint_types.dart'),
  Type3StringKey('Uint16Type', 'package', 'fory/src/annotation/uint_types.dart'),
  Type3StringKey('Uint32Type', 'package', 'fory/src/annotation/uint_types.dart'),
  Type3StringKey('Uint64Type', 'package', 'fory/src/annotation/uint_types.dart'),
];

3. Integrated Annotation-Based Type Override

Modified type_analyzer_impl.dart to support annotation-based type override:

TypeSpecGen getTypeImmutableAndTagWithOverride(
  TypeDecision typeDecision,
  LocationMark locationMark,
  ObjType objTypeOverride,
) {
  // Uses annotation-specified ObjType instead of default type resolution
}

4. Updated Field Analyzer

Modified field_analyzer_impl.dart to check for uint annotations:

// Check for uint annotations
final uintAnnotationResult = Analyzer.uintAnnotationAnalyzer.analyze(
  element.metadata,
  locationMark,
);

if (uintAnnotationResult.hasAnnotation) {
  // Use annotation-based type override
  fieldType = Analyzer.typeAnalyzer.getTypeImmutableAndTagWithOverride(
    typeDecision, locationMark, uintAnnotationResult.objType!,
  );
}

Related issues

Completes the unsigned integer annotation types support initiated in PR #3144 by integrating the annotations into the code generation system.

Does this PR introduce any user-facing change?

  • Does this PR introduce any public API change?

    • Dart: Users can now use @Uint8Type(), @Uint16Type(), @Uint32Type(), @Uint64Type() annotations on native int fields in @ForyClass structs
    • Enables encoding variant specification via encoding parameter for uint32/uint64
    • Provides more ergonomic API: @Uint8Type() int age instead of UInt8 age
  • Does this PR introduce any binary protocol compatibility change?

    • No changes to binary encoding format
    • Uses existing ObjType mappings and serializers
    • Type IDs remain the same: UINT8 (40), UINT16 (41), UINT32 (42), VAR_UINT32 (43), UINT64 (44), VAR_UINT64 (45), TAGGED_UINT64 (46)

Benchmark

N/A - This PR only adds annotation processing during code generation (build-time). No runtime performance impact.

@ayush00git
Copy link
Contributor Author

Hey @chaokunyang
I have added the uint annotations to the codegen system. Now fory serializes the dart uint as well, have a look at the PR and let me know the changes...

@chaokunyang
Copy link
Collaborator

chaokunyang commented Jan 21, 2026

@ayush00git Please add tests for feature pull request.

@ayush00git
Copy link
Contributor Author

Hey @chaokunyang
I've added the tests...

@ayush00git
Copy link
Contributor Author

Hey @chaokunyang
I've made the changes, and added a separate class ConstaintViolationException for handling the type exceptions.
Give it a review and let me know your opinions.

Copy link
Collaborator

@chaokunyang chaokunyang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@chaokunyang chaokunyang merged commit 8ef0bf5 into apache:main Jan 22, 2026
55 checks passed
@ayush00git
Copy link
Contributor Author

Hey @chaokunyang
I am working on a PR for adding the struct uint to the codegen as well, my os just got crashed, as i'm back to a new linux, i'll start on it.

@ayush00git ayush00git deleted the feat/dart-codegen branch January 22, 2026 13:53
chaokunyang pushed a commit that referenced this pull request Jan 23, 2026
## Why?

While the uint annotation types were integrated into the code generation
system in the PR #3181 , there were two remaining issues:

1. **No annotated struct support and test coverage for annotated
structs**: The annotation system was integrated but not tested with
actual struct fields using the annotations
2. **Null check error in key_annotation_analyzer**: When fields didn't
have `@ForyKey` annotations, the code generator crashed with a null
check error at `key_annotation_analyzer.dart`

## What does this PR do?

### 1. Created Test Entity with Annotated Uint Fields

Added `uint_annotated_struct.dart` demonstrating all uint annotation
variants:

```dart
@ForyClass(promiseAcyclic: true)
class UIntAnnotatedStruct with _$UIntAnnotatedStructFory {
  @uint8type()
  final int age;

  @Uint16Type()
  final int port;

  @Uint32Type()
  final int count;

  @Uint32Type(encoding: UintEncoding.varint)
  final int varCount;

  @Uint64Type()
  final int id;

  @Uint64Type(encoding: UintEncoding.varint)
  final int varId;

  @Uint64Type(encoding: UintEncoding.tagged)
  final int taggedId;
}
```

### 2. Added Comprehensive Test Suite

Created `uint_annotated_struct_test.dart` with test coverage for:
* Basic serialization/deserialization with annotated fields
* Max value handling for uint8 (255), uint16 (65535), uint32
(4294967295)
* Min value handling (0 for all types)
* Varint encoding efficiency verification

**Run tests:**

```bash
cd dart/packages/fory-test
dart run build_runner build --delete-conflicting-outputs
dart test test/struct_test/uint_annotated_struct_test.dart
```

### 3. Fixed Null Check Error in Key Annotation Analyzer

**Problem:** The `key_annotation_analyzer.dart` was attempting to access
annotation fields even when no `@ForyKey` annotation was present,
causing a null check operator error.

**Solution:** Added additional check to ensure we only access annotation
fields when a `@ForyKey` annotation is actually found:

Before
```dart
if (anno != null){
```
After
```dart
if (getMeta && anno != null){
```

This ensures that:
- We only try to read annotation fields when `getMeta` is true (meaning
we found a `@ForyKey` annotation)
- Fields without `@ForyKey` annotations correctly default to
`includeFromFory: true` and `includeToFory: true`
- Code generation no longer crashes on structs with unannotated fields

## Related issues

Completes the uint annotation testing and fixes a critical bug that
prevented code generation from working with fields lacking `@ForyKey`
annotations.

## Does this PR introduce any user-facing change?

* [ ] Does this PR introduce any public API change?
  * No new APIs - only adds test coverage and fixes a bug

* [ ] Does this PR introduce any binary protocol compatibility change?
  * No changes to binary encoding format
  * Bug fix only affects code generation, not runtime serialization

## Benchmark

N/A - This PR adds test coverage and fixes a code generation bug. No
runtime performance impact.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants