diff --git a/dart/packages/fory-test/lib/entity/uint_annotated_struct.dart b/dart/packages/fory-test/lib/entity/uint_annotated_struct.dart new file mode 100644 index 0000000000..dcc8b05959 --- /dev/null +++ b/dart/packages/fory-test/lib/entity/uint_annotated_struct.dart @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import 'package:fory/fory.dart'; + +part '../generated/uint_annotated_struct.g.dart'; + +/// Test struct for uint type annotations. +/// Uses native int types with annotations to specify serialization format. +@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; + + const UIntAnnotatedStruct({ + required this.age, + required this.port, + required this.count, + required this.varCount, + required this.id, + required this.varId, + required this.taggedId, + }); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other is UIntAnnotatedStruct && + runtimeType == other.runtimeType && + age == other.age && + port == other.port && + count == other.count && + varCount == other.varCount && + id == other.id && + varId == other.varId && + taggedId == other.taggedId); + } + + @override + int get hashCode => + age.hashCode ^ + port.hashCode ^ + count.hashCode ^ + varCount.hashCode ^ + id.hashCode ^ + varId.hashCode ^ + taggedId.hashCode; +} diff --git a/dart/packages/fory-test/test/struct_test/uint_annotated_struct_test.dart b/dart/packages/fory-test/test/struct_test/uint_annotated_struct_test.dart new file mode 100644 index 0000000000..91fad5f988 --- /dev/null +++ b/dart/packages/fory-test/test/struct_test/uint_annotated_struct_test.dart @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +library; + +import 'package:fory/fory.dart'; +import 'package:fory_test/entity/uint_annotated_struct.dart'; +import 'package:test/test.dart'; + +void main() { + group('UInt annotated struct serialization', () { + test('serializes and deserializes annotated uint fields correctly', () { + // Create test instance with native int types + var original = UIntAnnotatedStruct( + age: 25, + port: 8080, + count: 1000000, + varCount: 500000, + id: 9223372036854775807, + varId: 4611686018427387903, + taggedId: 1152921504606846975, + ); + + // Serialize + var fory = Fory(); + fory.register($UIntAnnotatedStruct); + var bytes = fory.toFory(original); + + expect(bytes.isNotEmpty, isTrue); + + // Deserialize + var decoded = fory.fromFory(bytes) as UIntAnnotatedStruct; + + // Verify values + expect(decoded.age, 25); + expect(decoded.port, 8080); + expect(decoded.count, 1000000); + expect(decoded.varCount, 500000); + expect(decoded.id, 9223372036854775807); + expect(decoded.varId, 4611686018427387903); + expect(decoded.taggedId, 1152921504606846975); + }); + + test('handles uint8 max value correctly', () { + var original = UIntAnnotatedStruct( + age: 255, // Max UInt8 + port: 100, + count: 100, + varCount: 100, + id: 100, + varId: 100, + taggedId: 100, + ); + + var fory = Fory(); + fory.register($UIntAnnotatedStruct); + var bytes = fory.toFory(original); + var decoded = fory.fromFory(bytes) as UIntAnnotatedStruct; + + expect(decoded.age, 255); + }); + + test('handles uint16 max value correctly', () { + var original = UIntAnnotatedStruct( + age: 100, + port: 65535, // Max UInt16 + count: 100, + varCount: 100, + id: 100, + varId: 100, + taggedId: 100, + ); + + var fory = Fory(); + fory.register($UIntAnnotatedStruct); + var bytes = fory.toFory(original); + var decoded = fory.fromFory(bytes) as UIntAnnotatedStruct; + + expect(decoded.port, 65535); + }); + + test('handles uint32 max value correctly', () { + var original = UIntAnnotatedStruct( + age: 100, + port: 100, + count: 4294967295, // Max UInt32 + varCount: 4294967295, // Max UInt32 + id: 100, + varId: 100, + taggedId: 100, + ); + + var fory = Fory(); + fory.register($UIntAnnotatedStruct); + var bytes = fory.toFory(original); + var decoded = fory.fromFory(bytes) as UIntAnnotatedStruct; + + expect(decoded.count, 4294967295); + expect(decoded.varCount, 4294967295); + }); + + test('handles min values correctly', () { + var original = UIntAnnotatedStruct( + age: 0, + port: 0, + count: 0, + varCount: 0, + id: 0, + varId: 0, + taggedId: 0, + ); + + var fory = Fory(); + fory.register($UIntAnnotatedStruct); + var bytes = fory.toFory(original); + var decoded = fory.fromFory(bytes) as UIntAnnotatedStruct; + + expect(decoded.age, 0); + expect(decoded.port, 0); + expect(decoded.count, 0); + expect(decoded.varCount, 0); + expect(decoded.id, 0); + expect(decoded.varId, 0); + expect(decoded.taggedId, 0); + }); + + test('varint encoding uses less space for small values', () { + var smallValues = UIntAnnotatedStruct( + age: 1, + port: 1, + count: 1, + varCount: 1, + id: 1, + varId: 1, + taggedId: 1, + ); + + var largeValues = UIntAnnotatedStruct( + age: 1, + port: 1, + count: 4294967295, + varCount: 4294967295, + id: 1, + varId: 1, + taggedId: 1, + ); + + var fory = Fory(); + fory.register($UIntAnnotatedStruct); + + var smallBytes = fory.toFory(smallValues); + var largeBytes = fory.toFory(largeValues); + + // Varint should use less space for small values + // Fixed-length uint32 always uses 4 bytes regardless of value + expect(smallBytes.length, lessThan(largeBytes.length)); + }); + }); +} diff --git a/dart/packages/fory/lib/src/codegen/analyze/impl/annotation/key_annotation_analyzer.dart b/dart/packages/fory/lib/src/codegen/analyze/impl/annotation/key_annotation_analyzer.dart index 3e5c3344fc..d89ec47ae5 100644 --- a/dart/packages/fory/lib/src/codegen/analyze/impl/annotation/key_annotation_analyzer.dart +++ b/dart/packages/fory/lib/src/codegen/analyze/impl/annotation/key_annotation_analyzer.dart @@ -57,7 +57,7 @@ class KeyAnnotationAnalyzer { // If there is no annotation, both includeFromFory and includeToFory default to true. bool includeFromFory = true; bool includeToFory = true; - if (anno != null){ + if (getMeta && anno != null){ includeFromFory = anno.getField("includeFromFory")!.toBoolValue()!; includeToFory = anno.getField("includeToFory")!.toBoolValue()!; // serializeToVar = anno.getField("serializeTo")?.variable;