Skip to content

Conversation

@ayush00git
Copy link
Contributor

@ayush00git ayush00git commented Jan 13, 2026

Why?

Dart doesn't have native unsigned integer types (only a single 64-bit signed int but many other languages (Rust, Go, C++, JavaScript) do. When serializing data across languages, we need to properly handle unsigned integers to ensure correct values and efficient encoding.

For example:

  • A Rust u32 with value 3_000_000_000 cannot be directly represented in Dart without proper unsigned handling
  • Variable-length encoding for unsigned integers can skip zigzag encoding overhead
  • Cross-language compatibility requires proper unsigned type support in the protocol

What does this PR do?

1. Adds Unsigned Integer Type Support (Dart)

New type IDs: UINT8 (40), UINT16 (41), UINT32 (42), VAR_UINT32 (43), UINT64 (44), VAR_UINT64 (45), TAGGED_UINT64 (46)

Unsigned types use the same bit width as signed types but interpret values in the unsigned range.

2. Dart: Adds Wrapper Classes for Fixed-Size Unsigned Integers

Created UInt8 UInt16 and UInt32 wrapper classes that extend FixedNum:

import 'package:fory/src/datatype/uint8.dart';

var value = UInt8(255);
var result = value + UInt8(1);  // Automatically wraps to 0

Features:

  • Automatic overflow/underflow wrapping using bitwise operations
  • Full operator support (arithmetic, bitwise, comparison)
  • Type conversions (toInt, toDouble, toString)

Core wrapping logic:

static int _convert(num value) {
  if (value is int) {
    return value & 0xFF;  // Keeps only lowest 8 bits for UInt8
  }
  return _convert(value.toInt());
}

3. Dart: Adds Serializers for All Unsigned Types

Implemented 7 serializer classes following the existing cache pattern:

final class UInt8Serializer extends Serializer<FixedNum> {
  UInt8 read(ByteReader br, ...) => UInt8(br.readUint8());
  void write(ByteWriter bw, UInt8 v, ...) => bw.writeUint8(v.toInt());
}

ByteReader/Writer methods used:

  • UInt8/16/32: readUint8/16/32(), writeUint8/16/32()
  • VarUInt32: readVarUint32(), writeVarUint32()
  • UInt64: readUint64(), writeUint64()
  • VarUInt64/TaggedUInt64: readVarInt64(), writeVarInt64()

4. Dart: Adds Comprehensive Test Suite

Created test coverage for all unsigned types:

test('wraps on overflow', () {
  var a = UInt8(256);  // Overflow to 0
  var b = UInt8(257);  // Overflow to 1
  var c = UInt8(-1);   // Wraps to 255
  
  expect(a.value, 0);
  expect(b.value, 1);
  expect(c.value, 255);
});

Run tests:

cd dart/packages/fory-test
dart test test/datatype_test/uint_test.dart

Related Issue

Does this PR introduce any user-facing change?

  • Does this PR introduce any public API change?

    • Dart: New data type classes UInt8, UInt16, UInt32
    • Dart: New enum types in ObjType: UINT8, UINT16, UINT32, VAR_UINT32, UINT64, VAR_UINT64, TAGGED_UINT64
    • Dart: New serializers for all 7 unsigned types
  • Does this PR introduce any binary protocol compatibility change?

    • Adds new type IDs for unsigned integers (40-46)
    • Existing signed integer encoding remains compatible
    • Cross-language compatibility maintained with JavaScript implementation

Benchmark

N/A - This PR focuses on correctness and cross-language compatibility. Performance characteristics of unsigned types are similar to their signed counterparts.

@ayush00git
Copy link
Contributor Author

Hey @chaokunyang
Have a look at the PR and do let me know if there are any chnages.
Thanks : )

@chaokunyang
Copy link
Collaborator

chaokunyang commented Jan 14, 2026

@ayush00git It's great to add wrapper with overlaoed numeric compute operator. But protobuf and flatfbuffer use int type instead, could we also support annotation based approach like we did in java:

https://fory.apache.org/docs/next/guide/java/field_configuration#unsigned-integers

Support both approaches will provide maximal flexibility to our users

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for unsigned integer types in Dart to enable cross-language serialization compatibility. Since Dart only has 64-bit signed integers, these wrapper classes provide proper unsigned integer semantics with automatic overflow/underflow wrapping behavior.

Changes:

  • Added UInt8, UInt16, and UInt32 wrapper classes with automatic wrapping and full operator support
  • Implemented 7 new serializers for unsigned types (UINT8, UINT16, UINT32, VAR_UINT32, UINT64, VAR_UINT64, TAGGED_UINT64)
  • Added comprehensive test coverage for all unsigned type behaviors

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
dart/packages/fory/lib/src/datatype/uint8.dart New UInt8 class with 8-bit unsigned integer wrapping logic and operator overloads
dart/packages/fory/lib/src/datatype/uint16.dart New UInt16 class with 16-bit unsigned integer wrapping logic and operator overloads
dart/packages/fory/lib/src/datatype/uint32.dart New UInt32 class with 32-bit unsigned integer wrapping logic and operator overloads
dart/packages/fory/lib/src/const/obj_type.dart Added 7 new unsigned type enum values (UINT8-TAGGED_UINT64) and updated ID range check
dart/packages/fory/lib/src/serializer/primitive_type_serializer.dart Implemented 7 serializers with caching for all unsigned integer types
dart/packages/fory-test/test/datatype_test/uint_test.dart Added comprehensive tests for UInt8, UInt16, UInt32 covering wrapping, operators, and edge cases

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ayush00git
Copy link
Contributor Author

ayush00git commented Jan 14, 2026

@ayush00git It's great to add wrapper with overlaoed numeric compute operator. But protobuf and flatfbuffer use int type instead, could we also support annotation based approach like we did in java:

https://fory.apache.org/docs/next/guide/java/field_configuration#unsigned-integers

Support both approaches will provide maximal flexibility to our users

@chaokunyang
I'll look into and make the desired changes after looking into the reference.
I'll also add the changes suggested by copilot in the next commits.

@ayush00git
Copy link
Contributor Author

Hey @chaokunyang
I've added the annotation definitions (@Uint8Type, @Uint16Type, @Uint16Type) to support the protobuf/flatbuffer style of using native int types with annotations. However, integrating these annotations into the code generation system requires modifying the analyzer and type resolver. Could you provide me guidance on the best approach for this integration, or would you prefer to handle the code generation part since it touches core code?

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.

[Dart] support unsigned number for Dart

2 participants