diff --git a/dart/packages/fory-test/test/datatype_test/uint_test.dart b/dart/packages/fory-test/test/datatype_test/uint_test.dart new file mode 100644 index 0000000000..3866b3ec42 --- /dev/null +++ b/dart/packages/fory-test/test/datatype_test/uint_test.dart @@ -0,0 +1,232 @@ +/* + * 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/src/datatype/uint8.dart'; +import 'package:fory/src/datatype/uint16.dart'; +import 'package:fory/src/datatype/uint32.dart'; +import 'package:test/test.dart'; + +void main() { + group('UInt8 behaviors', () { + group('range & conversion', () { + test('preserves in-range values', () { + var a = UInt8(0); + var b = UInt8(255); + + expect(a.value, 0); + expect(b.value, 255); + }); + + test('wraps on overflow', () { + var a = UInt8(256); // Overflow to 0 + var b = UInt8(257); // Overflow to 1 + var c = UInt8(512); // Overflow to 0 + var d = UInt8(-1); // Wraps to 255 + + expect(a.value, 0); + expect(b.value, 1); + expect(c.value, 0); + expect(d.value, 255); + }); + + test('truncates float inputs', () { + var a = UInt8(42.7); + var b = UInt8(255.9); + + expect(a.value, 42); + expect(b.value, 255); + }); + + test('min/max constants and instances', () { + expect(UInt8.MIN_VALUE, 0); + expect(UInt8.MAX_VALUE, 255); + expect(UInt8.minValue.value, 0); + expect(UInt8.maxValue.value, 255); + }); + }); + + group('arithmetic operators with overflow', () { + test('addition with overflow', () { + var a = UInt8(200); + var b = UInt8(100); + var result = a + b; + + expect(result, isA()); + expect(result.value, 44); // 200 + 100 = 300, which overflows to 44 + }); + + test('subtraction with underflow', () { + var a = UInt8(50); + var b = UInt8(100); + var result = a - b; + + expect(result, isA()); + expect(result.value, 206); // 50 - 100 = -50, which wraps to 206 + }); + + test('multiplication with overflow', () { + var a = UInt8(20); + var b = UInt8(20); + var result = a * b; + + expect(result, isA()); + expect(result.value, 144); // 20 * 20 = 400, which overflows to 144 + }); + }); + + group('comparison operators', () { + test('less than', () { + var a = UInt8(10); + var b = UInt8(20); + + expect(a < b, isTrue); + expect(b < a, isFalse); + expect(a < 20, isTrue); + }); + + test('greater than', () { + var a = UInt8(200); + var b = UInt8(100); + + expect(a > b, isTrue); + expect(b > a, isFalse); + expect(a > 100, isTrue); + }); + }); + + group('equality & hashCode', () { + test('equality', () { + var a = UInt8(42); + var b = UInt8(42); + var c = UInt8(43); + + expect(a == b, isTrue); + expect(a == c, isFalse); + expect(a == 42, isTrue); + }); + + test('hashCode consistency', () { + var a = UInt8(42); + var b = UInt8(42); + + expect(a.hashCode == b.hashCode, isTrue); + }); + }); + }); + + group('UInt16 behaviors', () { + group('range & conversion', () { + test('preserves in-range values', () { + var a = UInt16(0); + var b = UInt16(65535); + + expect(a.value, 0); + expect(b.value, 65535); + }); + + test('wraps on overflow', () { + var a = UInt16(65536); // Overflow to 0 + var b = UInt16(65537); // Overflow to 1 + var c = UInt16(-1); // Wraps to 65535 + + expect(a.value, 0); + expect(b.value, 1); + expect(c.value, 65535); + }); + + test('min/max constants', () { + expect(UInt16.MIN_VALUE, 0); + expect(UInt16.MAX_VALUE, 65535); + expect(UInt16.minValue.value, 0); + expect(UInt16.maxValue.value, 65535); + }); + }); + + group('arithmetic operators', () { + test('addition with overflow', () { + var a = UInt16(60000); + var b = UInt16(10000); + var result = a + b; + + expect(result, isA()); + expect(result.value, 4464); // 70000 overflows to 4464 + }); + + test('subtraction with underflow', () { + var a = UInt16(1000); + var b = UInt16(2000); + var result = a - b; + + expect(result, isA()); + expect(result.value, 64536); // -1000 wraps to 64536 + }); + }); + }); + + group('UInt32 behaviors', () { + group('range & conversion', () { + test('preserves in-range values', () { + var a = UInt32(0); + var b = UInt32(4294967295); + + expect(a.value, 0); + expect(b.value, 4294967295); + }); + + test('wraps on overflow', () { + var a = UInt32(4294967296); // Overflow to 0 + var b = UInt32(4294967297); // Overflow to 1 + var c = UInt32(-1); // Wraps to 4294967295 + + expect(a.value, 0); + expect(b.value, 1); + expect(c.value, 4294967295); + }); + + test('min/max constants', () { + expect(UInt32.MIN_VALUE, 0); + expect(UInt32.MAX_VALUE, 4294967295); + expect(UInt32.minValue.value, 0); + expect(UInt32.maxValue.value, 4294967295); + }); + }); + + group('arithmetic operators', () { + test('addition with overflow', () { + var a = UInt32(4000000000); + var b = UInt32(500000000); + var result = a + b; + + expect(result, isA()); + expect(result.value, 205032704); // 4500000000 % (2^32) = 205032704 + }); + + test('large value operations', () { + var a = UInt32(2147483648); // Half of max value + var b = UInt32(2147483648); + var result = a + b; + + expect(result, isA()); + expect(result.value, 0); // Exactly overflows to 0 + }); + }); + }); +} diff --git a/dart/packages/fory/lib/fory.dart b/dart/packages/fory/lib/fory.dart index 023277f3f8..a6493e9ad4 100644 --- a/dart/packages/fory/lib/fory.dart +++ b/dart/packages/fory/lib/fory.dart @@ -26,6 +26,7 @@ export 'src/annotation/fory_key.dart'; export 'src/annotation/fory_class.dart'; export 'src/annotation/fory_enum.dart'; export 'src/annotation/fory_constructor.dart'; +export 'src/annotation/uint_types.dart'; // Analysis meta export 'src/meta/specs/class_spec.dart'; @@ -56,6 +57,9 @@ export 'src/datatype/fory_fixed_num.dart'; export 'src/datatype/int8.dart'; export 'src/datatype/int16.dart'; export 'src/datatype/int32.dart'; +export 'src/datatype/uint8.dart'; +export 'src/datatype/uint16.dart'; +export 'src/datatype/uint32.dart'; export 'src/datatype/float32.dart'; export 'src/datatype/local_date.dart'; export 'src/datatype/timestamp.dart'; diff --git a/dart/packages/fory/lib/src/annotation/uint_types.dart b/dart/packages/fory/lib/src/annotation/uint_types.dart new file mode 100644 index 0000000000..a2b0af97a2 --- /dev/null +++ b/dart/packages/fory/lib/src/annotation/uint_types.dart @@ -0,0 +1,105 @@ +/* + * 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; + +/// Annotation to mark a field as unsigned 8-bit integer (0-255). +/// +/// Use this annotation on `int` fields to serialize them as UINT8 type. +/// +/// Example: +/// ```dart +/// class MyStruct { +/// @Uint8Type() +/// int age; // Serialized as UINT8 +/// } +/// ``` +class Uint8Type { + const Uint8Type(); +} + +/// Annotation to mark a field as unsigned 16-bit integer (0-65535). +/// +/// Use this annotation on `int` fields to serialize them as UINT16 type. +/// +/// Example: +/// ```dart +/// class MyStruct { +/// @Uint16Type() +/// int port; // Serialized as UINT16 +/// } +/// ``` +class Uint16Type { + const Uint16Type(); +} + +/// Encoding options for 32-bit and 64-bit unsigned integers. +enum UintEncoding { + /// Fixed-length encoding (4 bytes for uint32, 8 bytes for uint64) + fixed, + + /// Variable-length encoding (VAR_UINT32 or VAR_UINT64) + varint, + + /// Tagged variable-length encoding (only for uint64) + tagged, +} + +/// Annotation to mark a field as unsigned 32-bit integer (0-4294967295). +/// +/// Use this annotation on `int` fields to serialize them as UINT32 or VAR_UINT32 type. +/// +/// Example: +/// ```dart +/// class MyStruct { +/// @Uint32Type() +/// int count; // Serialized as UINT32 (fixed) +/// +/// @Uint32Type(encoding: UintEncoding.varint) +/// int varCount; // Serialized as VAR_UINT32 +/// } +/// ``` +class Uint32Type { + final UintEncoding encoding; + + const Uint32Type({this.encoding = UintEncoding.fixed}); +} + +/// Annotation to mark a field as unsigned 64-bit integer. +/// +/// Use this annotation on `int` fields to serialize them as UINT64, VAR_UINT64, or TAGGED_UINT64 type. +/// +/// Example: +/// ```dart +/// class MyStruct { +/// @Uint64Type() +/// int id; // Serialized as UINT64 (fixed) +/// +/// @Uint64Type(encoding: UintEncoding.varint) +/// int varId; // Serialized as VAR_UINT64 +/// +/// @Uint64Type(encoding: UintEncoding.tagged) +/// int taggedId; // Serialized as TAGGED_UINT64 +/// } +/// ``` +class Uint64Type { + final UintEncoding encoding; + + const Uint64Type({this.encoding = UintEncoding.fixed}); +} diff --git a/dart/packages/fory/lib/src/const/obj_type.dart b/dart/packages/fory/lib/src/const/obj_type.dart index da0c3d3f3a..a7fb48df68 100644 --- a/dart/packages/fory/lib/src/const/obj_type.dart +++ b/dart/packages/fory/lib/src/const/obj_type.dart @@ -148,28 +148,49 @@ enum ObjType { INT8_ARRAY(31, true), // 31 /// One dimensional int16 array. - INT16_ARRAY(32, true), + INT16_ARRAY(32, true), // 32 /// One dimensional int32 array. - INT32_ARRAY(33, true), + INT32_ARRAY(33, true), // 33 /// One dimensional int64 array. - INT64_ARRAY(34, true), + INT64_ARRAY(34, true), // 34 /// One dimensional half_float_16 array. - FLOAT16_ARRAY(35, true), + FLOAT16_ARRAY(35, true), // 35 /// One dimensional float32 array. - FLOAT32_ARRAY(36, true), + FLOAT32_ARRAY(36, true), // 36 /// One dimensional float64 array. - FLOAT64_ARRAY(37, true), + FLOAT64_ARRAY(37, true), // 37 /// An (arrow record batch) object. - ARROW_RECORD_BATCH(38, false), + ARROW_RECORD_BATCH(38, false), // 38 /// An (arrow table) object. - ARROW_TABLE(39, false); + ARROW_TABLE(39, false), // 39 + + /// Unsigned 8-bit integer + UINT8(40, true), // 40 + + /// Unsigned 16-bit little-endian integer + UINT16(41, true), // 41 + + /// Unsigned 32-bit little-endian integer + UINT32(42, true), // 42 + + /// var_uint32: a 32-bit unsigned integer which uses fory var_uint32 encoding. + VAR_UINT32(43, true), // 43 + + /// Unsigned 64-bit little-endian integer + UINT64(44, true), // 44 + + /// var_uint64: a 64-bit unsigned integer which uses fory var_uint64 encoding. + VAR_UINT64(45, true), // 45 + + /// tagged_uint64: a 64-bit unsigned integer which uses fory tagged var_uint64 encoding. + TAGGED_UINT64(46, true); // 46 final int id; final bool independent; @@ -178,7 +199,7 @@ enum ObjType { static ObjType? fromId(int id) { // The current implementation is linear, so it's simpler here. If the id and ordinal become irregular in the future, this won't work. - if (id >= 1 && id <= 39) return ObjType.values[id]; + if (id >= 1 && id <= 46) return ObjType.values[id]; return null; } diff --git a/dart/packages/fory/lib/src/datatype/uint16.dart b/dart/packages/fory/lib/src/datatype/uint16.dart new file mode 100644 index 0000000000..e8aa7be694 --- /dev/null +++ b/dart/packages/fory/lib/src/datatype/uint16.dart @@ -0,0 +1,117 @@ +/* + * 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 'fory_fixed_num.dart'; + +/// UInt16: 16-bit unsigned integer (0 to 65535) +final class UInt16 extends FixedNum { + static const int MIN_VALUE = 0; + static const int MAX_VALUE = 65535; + + static UInt16 get maxValue => UInt16(MAX_VALUE); + static UInt16 get minValue => UInt16(MIN_VALUE); + + final int _value; + + UInt16(num input) : _value = _convert(input); + + static int _convert(num value) { + if (value is int) { + // Apply 16-bit unsigned integer overflow behavior + return value & 0xFFFF; // Keep only the lowest 16 bits (0-65535) + } else { + return _convert(value.toInt()); + } + } + + @override + int get value => _value; + + // Operators + UInt16 operator +(dynamic other) => + UInt16(_value + (other is FixedNum ? other.value : other)); + + UInt16 operator -(dynamic other) => + UInt16(_value - (other is FixedNum ? other.value : other)); + + UInt16 operator *(dynamic other) => + UInt16(_value * (other is FixedNum ? other.value : other)); + + double operator /(dynamic other) => + _value / (other is FixedNum ? other.value : other); + + UInt16 operator ~/(dynamic other) => + UInt16(_value ~/ (other is FixedNum ? other.value : other)); + + UInt16 operator %(dynamic other) => + UInt16(_value % (other is FixedNum ? other.value : other)); + + UInt16 operator -() => UInt16(-_value); + + // Bitwise operations + UInt16 operator &(dynamic other) => + UInt16(_value & (other is FixedNum ? other.value : other).toInt()); + + UInt16 operator |(dynamic other) => + UInt16(_value | (other is FixedNum ? other.value : other).toInt()); + + UInt16 operator ^(dynamic other) => + UInt16(_value ^ (other is FixedNum ? other.value : other).toInt()); + + UInt16 operator ~() => UInt16(~_value); + + UInt16 operator <<(int shiftAmount) => UInt16(_value << shiftAmount); + UInt16 operator >>(int shiftAmount) => UInt16(_value >> shiftAmount); + + // Comparison + bool operator <(dynamic other) => + _value < (other is FixedNum ? other.value : other); + + bool operator <=(dynamic other) => + _value <= (other is FixedNum ? other.value : other); + + bool operator >(dynamic other) => + _value > (other is FixedNum ? other.value : other); + + bool operator >=(dynamic other) => + _value >= (other is FixedNum ? other.value : other); + + // Equality + @override + bool operator ==(Object other) { + if (other is FixedNum) return _value == other.value; + if (other is num) return _value == other; + return false; + } + + @override + int get hashCode => _value.hashCode; + + // Common num methods + int abs() => _value; + int get sign => _value == 0 ? 0 : 1; + bool get isNegative => false; + + // Type conversions + int toInt() => _value; + double toDouble() => _value.toDouble(); + + @override + String toString() => _value.toString(); +} diff --git a/dart/packages/fory/lib/src/datatype/uint32.dart b/dart/packages/fory/lib/src/datatype/uint32.dart new file mode 100644 index 0000000000..f913cd7af8 --- /dev/null +++ b/dart/packages/fory/lib/src/datatype/uint32.dart @@ -0,0 +1,117 @@ +/* + * 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 'fory_fixed_num.dart'; + +/// UInt32: 32-bit unsigned integer (0 to 4294967295) +final class UInt32 extends FixedNum { + static const int MIN_VALUE = 0; + static const int MAX_VALUE = 4294967295; + + static UInt32 get maxValue => UInt32(MAX_VALUE); + static UInt32 get minValue => UInt32(MIN_VALUE); + + final int _value; + + UInt32(num input) : _value = _convert(input); + + static int _convert(num value) { + if (value is int) { + // Apply 32-bit unsigned integer overflow behavior + return value & 0xFFFFFFFF; // Keep only the lowest 32 bits (0-4294967295) + } else { + return _convert(value.toInt()); + } + } + + @override + int get value => _value; + + // Operators + UInt32 operator +(dynamic other) => + UInt32(_value + (other is FixedNum ? other.value : other)); + + UInt32 operator -(dynamic other) => + UInt32(_value - (other is FixedNum ? other.value : other)); + + UInt32 operator *(dynamic other) => + UInt32(_value * (other is FixedNum ? other.value : other)); + + double operator /(dynamic other) => + _value / (other is FixedNum ? other.value : other); + + UInt32 operator ~/(dynamic other) => + UInt32(_value ~/ (other is FixedNum ? other.value : other)); + + UInt32 operator %(dynamic other) => + UInt32(_value % (other is FixedNum ? other.value : other)); + + UInt32 operator -() => UInt32(-_value); + + // Bitwise operations + UInt32 operator &(dynamic other) => + UInt32(_value & (other is FixedNum ? other.value : other).toInt()); + + UInt32 operator |(dynamic other) => + UInt32(_value | (other is FixedNum ? other.value : other).toInt()); + + UInt32 operator ^(dynamic other) => + UInt32(_value ^ (other is FixedNum ? other.value : other).toInt()); + + UInt32 operator ~() => UInt32(~_value); + + UInt32 operator <<(int shiftAmount) => UInt32(_value << shiftAmount); + UInt32 operator >>(int shiftAmount) => UInt32(_value >> shiftAmount); + + // Comparison + bool operator <(dynamic other) => + _value < (other is FixedNum ? other.value : other); + + bool operator <=(dynamic other) => + _value <= (other is FixedNum ? other.value : other); + + bool operator >(dynamic other) => + _value > (other is FixedNum ? other.value : other); + + bool operator >=(dynamic other) => + _value >= (other is FixedNum ? other.value : other); + + // Equality + @override + bool operator ==(Object other) { + if (other is FixedNum) return _value == other.value; + if (other is num) return _value == other; + return false; + } + + @override + int get hashCode => _value.hashCode; + + // Common num methods + int abs() => _value; + int get sign => _value == 0 ? 0 : 1; + bool get isNegative => false; + + // Type conversions + int toInt() => _value; + double toDouble() => _value.toDouble(); + + @override + String toString() => _value.toString(); +} diff --git a/dart/packages/fory/lib/src/datatype/uint8.dart b/dart/packages/fory/lib/src/datatype/uint8.dart new file mode 100644 index 0000000000..be14b87735 --- /dev/null +++ b/dart/packages/fory/lib/src/datatype/uint8.dart @@ -0,0 +1,117 @@ +/* + * 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 'fory_fixed_num.dart'; + +/// UInt8: 8-bit unsigned integer (0 to 255) +final class UInt8 extends FixedNum { + static const int MIN_VALUE = 0; + static const int MAX_VALUE = 255; + + static UInt8 get maxValue => UInt8(MAX_VALUE); + static UInt8 get minValue => UInt8(MIN_VALUE); + + final int _value; + + UInt8(num input) : _value = _convert(input); + + static int _convert(num value) { + if (value is int) { + // Apply 8-bit unsigned integer overflow behavior + return value & 0xFF; // Keep only the lowest 8 bits (0-255) + } else { + return _convert(value.toInt()); + } + } + + @override + int get value => _value; + + // Operators + UInt8 operator +(dynamic other) => + UInt8(_value + (other is FixedNum ? other.value : other)); + + UInt8 operator -(dynamic other) => + UInt8(_value - (other is FixedNum ? other.value : other)); + + UInt8 operator *(dynamic other) => + UInt8(_value * (other is FixedNum ? other.value : other)); + + double operator /(dynamic other) => + _value / (other is FixedNum ? other.value : other); + + UInt8 operator ~/(dynamic other) => + UInt8(_value ~/ (other is FixedNum ? other.value : other)); + + UInt8 operator %(dynamic other) => + UInt8(_value % (other is FixedNum ? other.value : other)); + + UInt8 operator -() => UInt8(-_value); + + // Bitwise operations + UInt8 operator &(dynamic other) => + UInt8(_value & (other is FixedNum ? other.value : other).toInt()); + + UInt8 operator |(dynamic other) => + UInt8(_value | (other is FixedNum ? other.value : other).toInt()); + + UInt8 operator ^(dynamic other) => + UInt8(_value ^ (other is FixedNum ? other.value : other).toInt()); + + UInt8 operator ~() => UInt8(~_value); + + UInt8 operator <<(int shiftAmount) => UInt8(_value << shiftAmount); + UInt8 operator >>(int shiftAmount) => UInt8(_value >> shiftAmount); + + // Comparison + bool operator <(dynamic other) => + _value < (other is FixedNum ? other.value : other); + + bool operator <=(dynamic other) => + _value <= (other is FixedNum ? other.value : other); + + bool operator >(dynamic other) => + _value > (other is FixedNum ? other.value : other); + + bool operator >=(dynamic other) => + _value >= (other is FixedNum ? other.value : other); + + // Equality + @override + bool operator ==(Object other) { + if (other is FixedNum) return _value == other.value; + if (other is num) return _value == other; + return false; + } + + @override + int get hashCode => _value.hashCode; + + // Common num methods + int abs() => _value; + int get sign => _value == 0 ? 0 : 1; + bool get isNegative => false; + + // Type conversions + int toInt() => _value; + double toDouble() => _value.toDouble(); + + @override + String toString() => _value.toString(); +} diff --git a/dart/packages/fory/lib/src/serializer/primitive_type_serializer.dart b/dart/packages/fory/lib/src/serializer/primitive_type_serializer.dart index 1d6ff45b7e..40a13871df 100644 --- a/dart/packages/fory/lib/src/serializer/primitive_type_serializer.dart +++ b/dart/packages/fory/lib/src/serializer/primitive_type_serializer.dart @@ -24,6 +24,9 @@ import 'package:fory/src/datatype/fory_fixed_num.dart'; import 'package:fory/src/datatype/int16.dart'; import 'package:fory/src/datatype/int32.dart'; import 'package:fory/src/datatype/int8.dart'; +import 'package:fory/src/datatype/uint8.dart'; +import 'package:fory/src/datatype/uint16.dart'; +import 'package:fory/src/datatype/uint32.dart'; import 'package:fory/src/deserializer_pack.dart'; import 'package:fory/src/memory/byte_reader.dart'; import 'package:fory/src/memory/byte_writer.dart'; @@ -305,3 +308,234 @@ final class Float64Serializer extends Serializer{ bw.writeFloat64(v); } } + +final class _UInt8SerializerCache extends PrimitiveSerializerCache{ + static UInt8Serializer? serRef; + static UInt8Serializer? serNoRef; + + const _UInt8SerializerCache(); + + @override + Serializer getSerWithRef(bool writeRef) { + if (writeRef){ + serRef ??= UInt8Serializer._(true); + return serRef!; + } else { + serNoRef ??= UInt8Serializer._(false); + return serNoRef!; + } + } +} + +final class UInt8Serializer extends Serializer{ + static const SerializerCache cache = _UInt8SerializerCache(); + UInt8Serializer._(bool writeRef): super(ObjType.UINT8, writeRef); + + @override + UInt8 read(ByteReader br, int refId, DeserializerPack pack) { + return UInt8(br.readUint8()); + } + + @override + void write(ByteWriter bw, covariant UInt8 v, SerializerPack pack) { + bw.writeUint8(v.toInt()); + } +} + +final class _UInt16SerializerCache extends PrimitiveSerializerCache{ + static UInt16Serializer? serRef; + static UInt16Serializer? serNoRef; + + const _UInt16SerializerCache(); + + @override + Serializer getSerWithRef(bool writeRef) { + if (writeRef){ + serRef ??= UInt16Serializer._(true); + return serRef!; + } else { + serNoRef ??= UInt16Serializer._(false); + return serNoRef!; + } + } +} + +final class UInt16Serializer extends Serializer{ + static const SerializerCache cache = _UInt16SerializerCache(); + UInt16Serializer._(bool writeRef): super(ObjType.UINT16, writeRef); + + @override + UInt16 read(ByteReader br, int refId, DeserializerPack pack) { + return UInt16(br.readUint16()); + } + + @override + void write(ByteWriter bw, covariant UInt16 v, SerializerPack pack) { + bw.writeUint16(v.toInt()); + } +} + +final class _UInt32SerializerCache extends PrimitiveSerializerCache{ + static UInt32Serializer? serRef; + static UInt32Serializer? serNoRef; + + const _UInt32SerializerCache(); + + @override + Serializer getSerWithRef(bool writeRef) { + if (writeRef){ + serRef ??= UInt32Serializer._(true); + return serRef!; + } else { + serNoRef ??= UInt32Serializer._(false); + return serNoRef!; + } + } +} + +final class UInt32Serializer extends Serializer{ + static const SerializerCache cache = _UInt32SerializerCache(); + UInt32Serializer._(bool writeRef): super(ObjType.UINT32, writeRef); + + @override + UInt32 read(ByteReader br, int refId, DeserializerPack pack) { + return UInt32(br.readUint32()); + } + + @override + void write(ByteWriter bw, covariant UInt32 v, SerializerPack pack) { + bw.writeUint32(v.toInt()); + } +} + +final class _VarUInt32SerializerCache extends PrimitiveSerializerCache{ + static VarUInt32Serializer? serRef; + static VarUInt32Serializer? serNoRef; + + const _VarUInt32SerializerCache(); + + @override + Serializer getSerWithRef(bool writeRef) { + if (writeRef){ + serRef ??= VarUInt32Serializer._(true); + return serRef!; + } else { + serNoRef ??= VarUInt32Serializer._(false); + return serNoRef!; + } + } +} + +final class VarUInt32Serializer extends Serializer{ + static const SerializerCache cache = _VarUInt32SerializerCache(); + VarUInt32Serializer._(bool writeRef): super(ObjType.VAR_UINT32, writeRef); + + @override + UInt32 read(ByteReader br, int refId, DeserializerPack pack) { + return UInt32(br.readVarUint32()); + } + + @override + void write(ByteWriter bw, covariant UInt32 v, SerializerPack pack) { + bw.writeVarUint32(v.toInt()); + } +} + +final class _UInt64SerializerCache extends PrimitiveSerializerCache{ + static UInt64Serializer? serRef; + static UInt64Serializer? serNoRef; + + const _UInt64SerializerCache(); + + @override + Serializer getSerWithRef(bool writeRef) { + if (writeRef){ + serRef ??= UInt64Serializer._(true); + return serRef!; + } else { + serNoRef ??= UInt64Serializer._(false); + return serNoRef!; + } + } +} + +final class UInt64Serializer extends Serializer { + static const SerializerCache cache = _UInt64SerializerCache(); + UInt64Serializer._(bool writeRef): super(ObjType.UINT64, writeRef); + + @override + int read(ByteReader br, int refId, DeserializerPack pack) { + return br.readUint64(); + } + + @override + void write(ByteWriter bw, int v, SerializerPack pack) { + bw.writeUint64(v); + } +} + +final class _VarUInt64SerializerCache extends PrimitiveSerializerCache{ + static VarUInt64Serializer? serRef; + static VarUInt64Serializer? serNoRef; + + const _VarUInt64SerializerCache(); + + @override + Serializer getSerWithRef(bool writeRef) { + if (writeRef){ + serRef ??= VarUInt64Serializer._(true); + return serRef!; + } else { + serNoRef ??= VarUInt64Serializer._(false); + return serNoRef!; + } + } +} + +final class VarUInt64Serializer extends Serializer { + static const SerializerCache cache = _VarUInt64SerializerCache(); + VarUInt64Serializer._(bool writeRef): super(ObjType.VAR_UINT64, writeRef); + + @override + int read(ByteReader br, int refId, DeserializerPack pack) { + return br.readVarInt64(); + } + + @override + void write(ByteWriter bw, int v, SerializerPack pack) { + bw.writeVarInt64(v); + } +} + +final class _TaggedUInt64SerializerCache extends PrimitiveSerializerCache{ + static TaggedUInt64Serializer? serRef; + static TaggedUInt64Serializer? serNoRef; + + const _TaggedUInt64SerializerCache(); + + @override + Serializer getSerWithRef(bool writeRef) { + if (writeRef){ + serRef ??= TaggedUInt64Serializer._(true); + return serRef!; + } else { + serNoRef ??= TaggedUInt64Serializer._(false); + return serNoRef!; + } + } +} + +final class TaggedUInt64Serializer extends Serializer { + static const SerializerCache cache = _TaggedUInt64SerializerCache(); + TaggedUInt64Serializer._(bool writeRef): super(ObjType.TAGGED_UINT64, writeRef); + + @override + int read(ByteReader br, int refId, DeserializerPack pack) { + return br.readVarInt64(); + } + + @override + void write(ByteWriter bw, int v, SerializerPack pack) { + bw.writeVarInt64(v); + } +}