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 632e916b2 fix(xlang): fix xlang type system (#3646)
632e916b2 is described below
commit 632e916b2a8c790026acc96abc0c8acce9a2b8b2
Author: Shawn Yang <[email protected]>
AuthorDate: Mon May 4 22:16:10 2026 +0800
fix(xlang): fix xlang type system (#3646)
## Why?
## What does this PR do?
## Related issues
#3644
## 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
---
benchmarks/python/README.md | 2 +-
compiler/fory_compiler/ir/validator.py | 38 ++++-
.../fory_compiler/tests/test_xlang_type_system.py | 39 ++++-
cpp/fory/serialization/temporal_serializers.h | 4 +
cpp/fory/serialization/union_serializer.h | 2 +-
dart/packages/fory/lib/src/fory.dart | 22 +--
.../scalar_and_typed_array_serializer_test.dart | 15 ++
docs/compiler/schema-idl.md | 10 +-
docs/specification/xlang_serialization_spec.md | 3 +-
go/fory/field_spec.go | 2 -
go/fory/tag_test.go | 8 --
integration_tests/idl_tests/cpp/main.cc | 159 ++++++++++++++++++---
.../idl_tests/csharp/IdlTests/RoundtripTests.cs | 95 +++++++++---
.../idl_tests/dart/test/idl_roundtrip_test.dart | 133 ++++++++++++++---
.../idl_tests/go/idl_roundtrip_test.go | 28 ++++
integration_tests/idl_tests/idl/example.fdl | 42 ++++++
.../apache/fory/idl_tests/IdlRoundTripTest.java | 114 ++++++++-------
.../idl_tests/javascript/roundtrip.ts | 36 ++++-
.../idl_tests/javascript/test/roundtrip.test.ts | 31 +++-
.../idl_tests/python/idl_tests/roundtrip.py | 25 ++++
.../idl_tests/rust/tests/idl_roundtrip.rs | 49 +++++--
.../IdlRoundTripTests/IdlRoundTripTests.swift | 44 +++++-
.../serializer/kotlin/TypeUseAnnotationTest.kt | 45 ++++++
rust/fory/src/lib.rs | 2 +-
.../serializer/scala/TypeUseAnnotationTest.scala | 42 ++++++
25 files changed, 807 insertions(+), 183 deletions(-)
diff --git a/benchmarks/python/README.md b/benchmarks/python/README.md
index 5a968f8fc..c2da3f807 100644
--- a/benchmarks/python/README.md
+++ b/benchmarks/python/README.md
@@ -7,7 +7,7 @@ This directory contains two benchmark entrypoints:
- `StructList`, `SampleList`, `MediaContentList`
- operations: `serialize`, `deserialize`
- serializers: `fory`, `pickle`, `protobuf`
-2. `fory_benchmark.py`: CPython microbench script using the current 1.0
annotation surface.
+2. `fory_benchmark.py`: CPython microbench script using the current annotation
surface.
## Quick Start (Comprehensive Suite)
diff --git a/compiler/fory_compiler/ir/validator.py
b/compiler/fory_compiler/ir/validator.py
index 439f65f35..eccd99ce8 100644
--- a/compiler/fory_compiler/ir/validator.py
+++ b/compiler/fory_compiler/ir/validator.py
@@ -37,6 +37,18 @@ from fory_compiler.ir.ast import (
from fory_compiler.ir.types import ARRAY_ELEMENT_KINDS, PrimitiveKind
from fory_compiler.ir.type_id import compute_registered_type_id
+INVALID_MAP_KEY_KINDS = {
+ PrimitiveKind.BYTES,
+ PrimitiveKind.FLOAT16,
+ PrimitiveKind.BFLOAT16,
+ PrimitiveKind.FLOAT32,
+ PrimitiveKind.FLOAT64,
+ PrimitiveKind.DECIMAL,
+}
+INVALID_MAP_KEY_MESSAGE = (
+ "map keys do not support binary, float, decimal, list, map, or array types"
+)
+
@dataclass
class ValidationIssue:
@@ -69,7 +81,7 @@ class SchemaValidator:
self._check_messages()
self._check_type_references()
self._check_services()
- self._check_array_rules()
+ self._check_collection_type_rules()
if not self.allow_nested_collections:
self._check_collection_nesting()
self._check_ref_rules()
@@ -524,13 +536,17 @@ class SchemaValidator:
for f in union.fields:
check_field(f, None)
- def _check_array_rules(self) -> None:
+ def _check_collection_type_rules(self) -> None:
+ def invalid_map_key(field_type: FieldType) -> bool:
+ if isinstance(field_type, PrimitiveType):
+ return field_type.kind in INVALID_MAP_KEY_KINDS
+ return isinstance(field_type, (ListType, ArrayType, MapType))
+
def check_type(field_type: FieldType, field: Field, in_map_key: bool =
False):
if isinstance(field_type, ArrayType):
if in_map_key:
- self._error(
- "array<T> is not valid as a map key type",
field.location
- )
+ self._error(INVALID_MAP_KEY_MESSAGE, field.location)
+ return
element_type = field_type.element_type
if not isinstance(element_type, PrimitiveType):
self._error(
@@ -551,9 +567,19 @@ class SchemaValidator:
)
return
if isinstance(field_type, ListType):
+ if in_map_key:
+ self._error(INVALID_MAP_KEY_MESSAGE, field.location)
+ return
check_type(field_type.element_type, field)
elif isinstance(field_type, MapType):
- check_type(field_type.key_type, field, in_map_key=True)
+ if in_map_key:
+ self._error(INVALID_MAP_KEY_MESSAGE, field.location)
+ return
+ key_type = field_type.key_type
+ if invalid_map_key(key_type):
+ self._error(INVALID_MAP_KEY_MESSAGE, field.location)
+ else:
+ check_type(key_type, field, in_map_key=True)
check_type(field_type.value_type, field)
def check_message_fields(message: Message) -> None:
diff --git a/compiler/fory_compiler/tests/test_xlang_type_system.py
b/compiler/fory_compiler/tests/test_xlang_type_system.py
index 49a4be789..b03be3699 100644
--- a/compiler/fory_compiler/tests/test_xlang_type_system.py
+++ b/compiler/fory_compiler/tests/test_xlang_type_system.py
@@ -108,12 +108,24 @@ def test_array_type_is_distinct_from_list_type():
"any",
"date",
"timestamp",
+ "duration",
"decimal",
+ "ExampleState",
"Child",
+ "ChildUnion",
],
)
def test_array_rejects_non_fixed_width_number_and_bool_elements(element):
source = f"""
+ enum ExampleState {{
+ UNKNOWN = 0;
+ READY = 1;
+ }}
+
+ union ChildUnion {{
+ string note = 1;
+ }}
+
message Child {{
string name = 1;
}}
@@ -151,18 +163,33 @@ def
test_array_rejects_optional_or_ref_elements_at_parse_time():
)
-def test_array_is_not_valid_as_map_key():
[email protected](
+ "key_type",
+ [
+ "bytes",
+ "float16",
+ "bfloat16",
+ "float32",
+ "float64",
+ "decimal",
+ "list<int32>",
+ "array<uint8>",
+ "map<string, int32>",
+ ],
+)
+def test_map_rejects_non_portable_key_types(key_type):
_schema, validator, ok = validate_schema(
- """
- message InvalidMap {
- map<array<uint8>, string> values = 1;
- }
+ f"""
+ message InvalidMap {{
+ map<{key_type}, string> values = 1;
+ }}
"""
)
assert not ok
assert any(
- "array<T> is not valid as a map key type" in err.message
+ "map keys do not support binary, float, decimal, list, map, or array
types"
+ in err.message
for err in validator.errors
)
diff --git a/cpp/fory/serialization/temporal_serializers.h
b/cpp/fory/serialization/temporal_serializers.h
index 86737059e..978809c6b 100644
--- a/cpp/fory/serialization/temporal_serializers.h
+++ b/cpp/fory/serialization/temporal_serializers.h
@@ -51,6 +51,10 @@ public:
bool operator!=(const Date &other) const { return !(*this == other); }
+ bool operator<(const Date &other) const {
+ return days_since_epoch_ < other.days_since_epoch_;
+ }
+
private:
int32_t days_since_epoch_; // Days since Jan 1, 1970 UTC
};
diff --git a/cpp/fory/serialization/union_serializer.h
b/cpp/fory/serialization/union_serializer.h
index 2367fde88..2fda11fac 100644
--- a/cpp/fory/serialization/union_serializer.h
+++ b/cpp/fory/serialization/union_serializer.h
@@ -40,7 +40,7 @@
namespace fory {
namespace serialization {
-// Union metadata specializations generated by compiler (legacy).
+// Compiler-generated union metadata specializations.
template <typename T, typename Enable = void> struct UnionCaseIds;
template <typename T, uint32_t CaseId> struct UnionCaseMeta;
diff --git a/dart/packages/fory/lib/src/fory.dart
b/dart/packages/fory/lib/src/fory.dart
index f082a4eab..80d819048 100644
--- a/dart/packages/fory/lib/src/fory.dart
+++ b/dart/packages/fory/lib/src/fory.dart
@@ -43,7 +43,8 @@ final class Fory {
static const int _xlangHeaderFlag = 0x02;
static const int _outOfBandHeaderFlag = 0x04;
- late final Buffer _buffer;
+ late final Buffer _readBuffer;
+ late final Buffer _writeBuffer;
late final WriteContext _writeContext;
late final ReadContext _readContext;
late final TypeResolver _typeResolver;
@@ -66,7 +67,8 @@ final class Fory {
maxCollectionSize: maxCollectionSize,
maxBinarySize: maxBinarySize,
);
- _buffer = Buffer();
+ _readBuffer = Buffer();
+ _writeBuffer = Buffer();
_typeResolver = TypeResolver(config);
_writeContext = WriteContext(
config,
@@ -88,9 +90,9 @@ final class Fory {
/// that needs shared-reference tracking and there is no field metadata to
/// request it. Annotated fields should still use `@ForyField(ref: true)`.
Uint8List serialize(Object? value, {bool trackRef = false}) {
- _buffer.clear();
- serializeTo(value, _buffer, trackRef: trackRef);
- return Uint8List.fromList(_buffer.toBytes());
+ _writeBuffer.clear();
+ serializeTo(value, _writeBuffer, trackRef: trackRef);
+ return Uint8List.fromList(_writeBuffer.toBytes());
}
/// Serializes a non-null builtin [value] using the explicit xlang
@@ -104,14 +106,14 @@ final class Fory {
required int wireTypeId,
bool trackRef = false,
}) {
- _buffer.clear();
+ _writeBuffer.clear();
serializeBuiltinTo(
value,
- _buffer,
+ _writeBuffer,
wireTypeId: wireTypeId,
trackRef: trackRef,
);
- return Uint8List.fromList(_buffer.toBytes());
+ return Uint8List.fromList(_writeBuffer.toBytes());
}
/// Serializes [value] into [buffer].
@@ -163,8 +165,8 @@ final class Fory {
/// The payload is decoded from its wire metadata first. `T` is used as a
/// post-read type check, not as an alternate schema.
T deserialize<T>(Uint8List bytes) {
- _buffer.wrap(bytes);
- return deserializeFrom<T>(_buffer);
+ _readBuffer.wrap(bytes);
+ return deserializeFrom<T>(_readBuffer);
}
/// Deserializes a value from [buffer] and checks that it is assignable to
diff --git
a/dart/packages/fory/test/scalar_and_typed_array_serializer_test.dart
b/dart/packages/fory/test/scalar_and_typed_array_serializer_test.dart
index c58b902a1..5d61240ab 100644
--- a/dart/packages/fory/test/scalar_and_typed_array_serializer_test.dart
+++ b/dart/packages/fory/test/scalar_and_typed_array_serializer_test.dart
@@ -389,6 +389,21 @@ void main() {
);
});
+ test('reuses Fory after typed-array reads without corrupting views', () {
+ final fory = Fory();
+ final values = <Int32List>[
+ Int32List.fromList(<int>[1, 2]),
+ Int32List.fromList(<int>[3, 4]),
+ ];
+
+ final decoded = fory.deserialize<List<Object?>>(fory.serialize(values));
+ final encodedAgain = fory.serialize(decoded);
+ final roundTrip = fory.deserialize<List<Object?>>(encodedAgain);
+
+ expect((roundTrip[0] as Int32List).toList(), orderedEquals(<int>[1, 2]));
+ expect((roundTrip[1] as Int32List).toList(), orderedEquals(<int>[3, 4]));
+ });
+
test('round-trips empty binary and typed array payloads', () {
final fory = Fory();
diff --git a/docs/compiler/schema-idl.md b/docs/compiler/schema-idl.md
index 68bcf70d8..63a6e3ef3 100644
--- a/docs/compiler/schema-idl.md
+++ b/docs/compiler/schema-idl.md
@@ -1274,7 +1274,7 @@ Generated carriers are language-specific, but the schema
kind is not:
| ----------------- | ---------------------------- | ---------------------- |
-------------- | ------------------------ |
| `list<bool>` | `BoolList` / `List<Boolean>` | `List[bool]` |
`List<bool>` | `Type.list(Type.bool())` |
| `array<bool>` | `boolean[]` | `pyfory.BoolArray` |
`BoolList` | `Type.boolArray()` |
-| `array<int8>` | `byte[]` | `pyfory.Int8Array` |
`Int8List` | `Type.int8Array()` |
+| `array<int8>` | `@Int8Type byte[]` | `pyfory.Int8Array` |
`Int8List` | `Type.int8Array()` |
| `array<int16>` | `short[]` | `pyfory.Int16Array` |
`Int16List` | `Type.int16Array()` |
| `array<int32>` | `int[]` | `pyfory.Int32Array` |
`Int32List` | `Type.int32Array()` |
| `array<int64>` | `long[]` | `pyfory.Int64Array` |
`Int64List` | `Type.int64Array()` |
@@ -1316,10 +1316,14 @@ message Config {
**Key Type Restrictions:**
- `string` (most common)
-- Integer types (`int8`, `int16`, `int32`, `int64`)
- `bool`
+- Integer types (`int8`, `int16`, `int32`, `int64`, `uint8`, `uint16`,
`uint32`, `uint64`)
+- Temporal scalar types (`date`, `timestamp`, `duration`)
+- Enums
-Avoid using messages or complex types as keys.
+Map keys do not support binary `bytes`, floating-point types, `decimal`,
`list<T>`, `array<T>`,
+or nested `map<K, V>` types. Put those types in map values or wrap them in a
message with a
+portable scalar or enum key.
### Type Compatibility Matrix
diff --git a/docs/specification/xlang_serialization_spec.md
b/docs/specification/xlang_serialization_spec.md
index 37a196801..24adbe333 100644
--- a/docs/specification/xlang_serialization_spec.md
+++ b/docs/specification/xlang_serialization_spec.md
@@ -63,7 +63,8 @@ This specification defines the Fory xlang binary format. The
format is dynamic r
- named_ext: an `ext` type whose type mapping will be encoded as a name.
- list: a sequence of objects.
- set: an unordered set of unique elements.
-- map: a map of key-value pairs. Mutable types such as `list/map/set/array`
are not allowed as key of map.
+- map: a map of key-value pairs. Map keys do not allow binary values,
floating-point values,
+ decimal values, or collection-shaped values such as `list`, `map`, `set`,
and `array`.
- duration: an absolute length of time, independent of any calendar/timezone,
as a count of nanoseconds.
- timestamp: a point in time, independent of any calendar/timezone, encoded as
seconds (int64) and nanoseconds
(uint32) since the epoch at UTC midnight on January 1, 1970.
diff --git a/go/fory/field_spec.go b/go/fory/field_spec.go
index cd7e59b20..68f15a69b 100644
--- a/go/fory/field_spec.go
+++ b/go/fory/field_spec.go
@@ -558,8 +558,6 @@ func parseFieldTag(field reflect.StructField)
(parsedFieldTag, error) {
}
parsed.typeHintSet = true
parsed.typeHint = hint
- case "compress", "nested_ref":
- return parsedFieldTag{}, InvalidTagErrorf("unsupported
legacy fory tag key %q on field %s", key, field.Name)
default:
return parsedFieldTag{}, InvalidTagErrorf("unknown fory
tag key %q on field %s", key, field.Name)
}
diff --git a/go/fory/tag_test.go b/go/fory/tag_test.go
index aeeb551dd..11382d6f7 100644
--- a/go/fory/tag_test.go
+++ b/go/fory/tag_test.go
@@ -220,12 +220,6 @@ func TestParseFieldSpecRejectsInvalidTags(t *testing.T) {
type UnknownKey struct {
Value int32 `fory:"id=0,unknown=true"`
}
- type LegacyCompress struct {
- Value uint32 `fory:"compress=true"`
- }
- type LegacyNestedRef struct {
- Value []int32 `fory:"nested_ref=[[]]"`
- }
type BadDSL struct {
Value []int32 `fory:"type=list(element=int32(encoding=fixed)"`
}
@@ -254,8 +248,6 @@ func TestParseFieldSpecRejectsInvalidTags(t *testing.T) {
}{
{name: "duplicate keys", typ: reflect.TypeOf(DuplicateKeys{})},
{name: "unknown key", typ: reflect.TypeOf(UnknownKey{})},
- {name: "legacy compress", typ:
reflect.TypeOf(LegacyCompress{})},
- {name: "legacy nested_ref", typ:
reflect.TypeOf(LegacyNestedRef{})},
{name: "bad dsl", typ: reflect.TypeOf(BadDSL{})},
{name: "impossible override", typ:
reflect.TypeOf(ImpossibleOverride{})},
{name: "encoding conflict", typ: reflect.TypeOf(Conflict{})},
diff --git a/integration_tests/idl_tests/cpp/main.cc
b/integration_tests/idl_tests/cpp/main.cc
index b97bd857d..8e41bd1d5 100644
--- a/integration_tests/idl_tests/cpp/main.cc
+++ b/integration_tests/idl_tests/cpp/main.cc
@@ -433,7 +433,7 @@ struct ExampleMessageLists {
fory::F(132).list(fory::T::inner(fory::T::uint64().varint()))));
};
-struct ExampleMessageArraysMaps {
+struct ExampleMessageArrays {
std::vector<bool> bool_array;
std::vector<int8_t> int8_array;
std::vector<int16_t> int16_array;
@@ -449,6 +449,28 @@ struct ExampleMessageArraysMaps {
std::vector<double> float64_array;
std::vector<std::vector<int32_t>> int32_array_list;
std::vector<std::vector<uint8_t>> uint8_array_list;
+
+ FORY_STRUCT(ExampleMessageArrays,
+ (bool_array, fory::F(301).array(fory::T::boolean())),
+ (int8_array, fory::F(302).array(fory::T::int8())),
+ (int16_array, fory::F(303).array(fory::T::int16())),
+ (int32_array, fory::F(304).array(fory::T::int32())),
+ (int64_array, fory::F(305).array(fory::T::int64())),
+ (uint8_array, fory::F(306).array(fory::T::uint8())),
+ (uint16_array, fory::F(307).array(fory::T::uint16())),
+ (uint32_array, fory::F(308).array(fory::T::uint32())),
+ (uint64_array, fory::F(309).array(fory::T::uint64())),
+ (float16_array, fory::F(310).array(fory::T::float16())),
+ (bfloat16_array, fory::F(311).array(fory::T::bfloat16())),
+ (float32_array, fory::F(312).array(fory::T::float32())),
+ (float64_array, fory::F(313).array(fory::T::float64())),
+ (int32_array_list,
+ fory::F(314).list(fory::T::array(fory::T::int32()))),
+ (uint8_array_list,
+ fory::F(315).list(fory::T::array(fory::T::uint8()))));
+};
+
+struct ExampleMessageMaps {
std::map<bool, std::string> string_values_by_bool;
std::map<int8_t, std::string> string_values_by_int8;
std::map<int16_t, std::string> string_values_by_int16;
@@ -482,24 +504,31 @@ struct ExampleMessageArraysMaps {
std::map<std::string, std::vector<uint8_t>> uint8_array_values_by_name;
std::map<std::string, std::vector<float>> float32_array_values_by_name;
std::map<std::string, std::vector<int32_t>> int32_array_values_by_name;
+ std::map<fory::serialization::Date, std::string> string_values_by_date;
+ std::map<std::string, bool> bool_values_by_name;
+ std::map<std::string, int8_t> int8_values_by_name;
+ std::map<std::string, int16_t> int16_values_by_name;
+ std::map<std::string, int32_t> fixed_i32_values_by_name;
+ std::map<std::string, int32_t> varint_i32_values_by_name;
+ std::map<std::string, int64_t> fixed_i64_values_by_name;
+ std::map<std::string, int64_t> varint_i64_values_by_name;
+ std::map<std::string, int64_t> tagged_i64_values_by_name;
+ std::map<std::string, uint8_t> uint8_values_by_name;
+ std::map<std::string, uint16_t> uint16_values_by_name;
+ std::map<std::string, uint32_t> fixed_u32_values_by_name;
+ std::map<std::string, uint32_t> varint_u32_values_by_name;
+ std::map<std::string, uint64_t> fixed_u64_values_by_name;
+ std::map<std::string, uint64_t> varint_u64_values_by_name;
+ std::map<std::string, uint64_t> tagged_u64_values_by_name;
+ std::map<std::string, float> float32_values_by_name;
+ std::map<std::string, double> float64_values_by_name;
+ std::map<std::string, fory::serialization::Timestamp>
+ timestamp_values_by_name;
+ std::map<std::string, fory::serialization::Duration> duration_values_by_name;
+ std::map<std::string, ExampleState> enum_values_by_name;
FORY_STRUCT(
- ExampleMessageArraysMaps,
- (bool_array, fory::F(301).array(fory::T::boolean())),
- (int8_array, fory::F(302).array(fory::T::int8())),
- (int16_array, fory::F(303).array(fory::T::int16())),
- (int32_array, fory::F(304).array(fory::T::int32())),
- (int64_array, fory::F(305).array(fory::T::int64())),
- (uint8_array, fory::F(306).array(fory::T::uint8())),
- (uint16_array, fory::F(307).array(fory::T::uint16())),
- (uint32_array, fory::F(308).array(fory::T::uint32())),
- (uint64_array, fory::F(309).array(fory::T::uint64())),
- (float16_array, fory::F(310).array(fory::T::float16())),
- (bfloat16_array, fory::F(311).array(fory::T::bfloat16())),
- (float32_array, fory::F(312).array(fory::T::float32())),
- (float64_array, fory::F(313).array(fory::T::float64())),
- (int32_array_list, fory::F(314).list(fory::T::array(fory::T::int32()))),
- (uint8_array_list, fory::F(315).list(fory::T::array(fory::T::uint8()))),
+ ExampleMessageMaps,
(string_values_by_bool,
fory::F(201).map(fory::T::boolean(), fory::T::string())),
(string_values_by_int8,
@@ -562,12 +591,55 @@ struct ExampleMessageArraysMaps {
(float32_array_values_by_name,
fory::F(232).map(fory::T::string(),
fory::T::array(fory::T::float32()))),
(int32_array_values_by_name,
- fory::F(233).map(fory::T::string(), fory::T::array(fory::T::int32()))));
+ fory::F(233).map(fory::T::string(), fory::T::array(fory::T::int32()))),
+ (string_values_by_date,
+ fory::F(234).map(fory::FieldNodeSpec{}, fory::T::string())),
+ (bool_values_by_name,
+ fory::F(236).map(fory::T::string(), fory::T::boolean())),
+ (int8_values_by_name,
+ fory::F(237).map(fory::T::string(), fory::T::int8())),
+ (int16_values_by_name,
+ fory::F(238).map(fory::T::string(), fory::T::int16())),
+ (fixed_i32_values_by_name,
+ fory::F(239).map(fory::T::string(), fory::T::int32().fixed())),
+ (varint_i32_values_by_name,
+ fory::F(240).map(fory::T::string(), fory::T::int32().varint())),
+ (fixed_i64_values_by_name,
+ fory::F(241).map(fory::T::string(), fory::T::int64().fixed())),
+ (varint_i64_values_by_name,
+ fory::F(242).map(fory::T::string(), fory::T::int64().varint())),
+ (tagged_i64_values_by_name,
+ fory::F(243).map(fory::T::string(), fory::T::int64().tagged())),
+ (uint8_values_by_name,
+ fory::F(244).map(fory::T::string(), fory::T::uint8())),
+ (uint16_values_by_name,
+ fory::F(245).map(fory::T::string(), fory::T::uint16())),
+ (fixed_u32_values_by_name,
+ fory::F(246).map(fory::T::string(), fory::T::uint32().fixed())),
+ (varint_u32_values_by_name,
+ fory::F(247).map(fory::T::string(), fory::T::uint32().varint())),
+ (fixed_u64_values_by_name,
+ fory::F(248).map(fory::T::string(), fory::T::uint64().fixed())),
+ (varint_u64_values_by_name,
+ fory::F(249).map(fory::T::string(), fory::T::uint64().varint())),
+ (tagged_u64_values_by_name,
+ fory::F(250).map(fory::T::string(), fory::T::uint64().tagged())),
+ (float32_values_by_name,
+ fory::F(251).map(fory::T::string(), fory::T::float32())),
+ (float64_values_by_name,
+ fory::F(252).map(fory::T::string(), fory::T::float64())),
+ (timestamp_values_by_name,
+ fory::F(253).map(fory::T::string(), fory::FieldNodeSpec{})),
+ (duration_values_by_name,
+ fory::F(254).map(fory::T::string(), fory::FieldNodeSpec{})),
+ (enum_values_by_name,
+ fory::F(255).map(fory::T::string(), fory::FieldNodeSpec{})));
};
struct ExampleMessage : ExampleMessageScalars,
ExampleMessageLists,
- ExampleMessageArraysMaps {
+ ExampleMessageArrays,
+ ExampleMessageMaps {
bool operator==(const ExampleMessage &other) const {
return std::tie(
@@ -605,7 +677,17 @@ struct ExampleMessage : ExampleMessageScalars,
date_values_by_name, decimal_values_by_name,
message_values_by_name, union_values_by_name,
uint8_array_values_by_name, float32_array_values_by_name,
- int32_array_values_by_name) ==
+ int32_array_values_by_name, string_values_by_date,
+ bool_values_by_name, int8_values_by_name, int16_values_by_name,
+ fixed_i32_values_by_name, varint_i32_values_by_name,
+ fixed_i64_values_by_name, varint_i64_values_by_name,
+ tagged_i64_values_by_name, uint8_values_by_name,
+ uint16_values_by_name, fixed_u32_values_by_name,
+ varint_u32_values_by_name, fixed_u64_values_by_name,
+ varint_u64_values_by_name, tagged_u64_values_by_name,
+ float32_values_by_name, float64_values_by_name,
+ timestamp_values_by_name, duration_values_by_name,
+ enum_values_by_name) ==
std::tie(
other.bool_value, other.int8_value, other.int16_value,
other.fixed_i32_value, other.varint_i32_value,
@@ -656,12 +738,22 @@ struct ExampleMessage : ExampleMessageScalars,
other.message_values_by_name, other.union_values_by_name,
other.uint8_array_values_by_name,
other.float32_array_values_by_name,
- other.int32_array_values_by_name);
+ other.int32_array_values_by_name, other.string_values_by_date,
+ other.bool_values_by_name, other.int8_values_by_name,
+ other.int16_values_by_name, other.fixed_i32_values_by_name,
+ other.varint_i32_values_by_name, other.fixed_i64_values_by_name,
+ other.varint_i64_values_by_name,
other.tagged_i64_values_by_name,
+ other.uint8_values_by_name, other.uint16_values_by_name,
+ other.fixed_u32_values_by_name, other.varint_u32_values_by_name,
+ other.fixed_u64_values_by_name, other.varint_u64_values_by_name,
+ other.tagged_u64_values_by_name, other.float32_values_by_name,
+ other.float64_values_by_name, other.timestamp_values_by_name,
+ other.duration_values_by_name, other.enum_values_by_name);
}
FORY_STRUCT(ExampleMessage, FORY_BASE(ExampleMessageScalars),
- FORY_BASE(ExampleMessageLists),
- FORY_BASE(ExampleMessageArraysMaps));
+ FORY_BASE(ExampleMessageLists), FORY_BASE(ExampleMessageArrays),
+ FORY_BASE(ExampleMessageMaps));
};
FORY_ENUM(ExampleState, UNKNOWN, READY, FAILED);
@@ -835,6 +927,27 @@ example_peer::ExampleMessage BuildExampleMessage() {
{"u8", {static_cast<uint8_t>(201), static_cast<uint8_t>(202)}}};
message.float32_array_values_by_name = {{"f32", {1.25F, 2.5F}}};
message.int32_array_values_by_name = {{"i32", {101, 202}}};
+ message.string_values_by_date = {{Date(19850), "date-key"}};
+ message.bool_values_by_name = {{"bool", true}};
+ message.int8_values_by_name = {{"int8", -8}};
+ message.int16_values_by_name = {{"int16", -16}};
+ message.fixed_i32_values_by_name = {{"fixed-i32", -32}};
+ message.varint_i32_values_by_name = {{"varint-i32", 32}};
+ message.fixed_i64_values_by_name = {{"fixed-i64", -64}};
+ message.varint_i64_values_by_name = {{"varint-i64", 64}};
+ message.tagged_i64_values_by_name = {{"tagged-i64", 65}};
+ message.uint8_values_by_name = {{"uint8", static_cast<uint8_t>(208)}};
+ message.uint16_values_by_name = {{"uint16", 60001}};
+ message.fixed_u32_values_by_name = {{"fixed-u32", 1234567892U}};
+ message.varint_u32_values_by_name = {{"varint-u32", 1234567893U}};
+ message.fixed_u64_values_by_name = {{"fixed-u64", 9876543213ULL}};
+ message.varint_u64_values_by_name = {{"varint-u64", 9876543214ULL}};
+ message.tagged_u64_values_by_name = {{"tagged-u64", 9876543215ULL}};
+ message.float32_values_by_name = {{"float32", 3.25F}};
+ message.float64_values_by_name = {{"float64", 6.5}};
+ message.timestamp_values_by_name = {{"timestamp", ts(1717747750)}};
+ message.duration_values_by_name = {{"duration", std::chrono::seconds(10)}};
+ message.enum_values_by_name = {{"enum", example_peer::ExampleState::FAILED}};
return message;
}
diff --git a/integration_tests/idl_tests/csharp/IdlTests/RoundtripTests.cs
b/integration_tests/idl_tests/csharp/IdlTests/RoundtripTests.cs
index 4dbc99c88..92b5bb089 100644
--- a/integration_tests/idl_tests/csharp/IdlTests/RoundtripTests.cs
+++ b/integration_tests/idl_tests/csharp/IdlTests/RoundtripTests.cs
@@ -695,6 +695,36 @@ public sealed class RoundtripTests
{
["i32"] = [101, 202],
},
+ StringValuesByDate = new Dictionary<DateOnly, string>
+ {
+ [new DateOnly(2024, 5, 7)] = "date-key",
+ },
+ BoolValuesByName = new Dictionary<string, bool> { ["bool"] = true
},
+ Int8ValuesByName = new Dictionary<string, sbyte> { ["int8"] = -8 },
+ Int16ValuesByName = new Dictionary<string, short> { ["int16"] =
-16 },
+ FixedI32ValuesByName = new Dictionary<string, int> { ["fixed-i32"]
= -32 },
+ VarintI32ValuesByName = new Dictionary<string, int> {
["varint-i32"] = 32 },
+ FixedI64ValuesByName = new Dictionary<string, long> {
["fixed-i64"] = -64 },
+ VarintI64ValuesByName = new Dictionary<string, long> {
["varint-i64"] = 64 },
+ TaggedI64ValuesByName = new Dictionary<string, long> {
["tagged-i64"] = 65 },
+ Uint8ValuesByName = new Dictionary<string, byte> { ["uint8"] = 208
},
+ Uint16ValuesByName = new Dictionary<string, ushort> { ["uint16"] =
60001 },
+ FixedU32ValuesByName = new Dictionary<string, uint> {
["fixed-u32"] = 1234567892 },
+ VarintU32ValuesByName = new Dictionary<string, uint> {
["varint-u32"] = 1234567893 },
+ FixedU64ValuesByName = new Dictionary<string, ulong> {
["fixed-u64"] = 9876543213 },
+ VarintU64ValuesByName = new Dictionary<string, ulong> {
["varint-u64"] = 9876543214 },
+ TaggedU64ValuesByName = new Dictionary<string, ulong> {
["tagged-u64"] = 9876543215 },
+ Float32ValuesByName = new Dictionary<string, float> { ["float32"]
= 3.25f },
+ Float64ValuesByName = new Dictionary<string, double> { ["float64"]
= 6.5 },
+ TimestampValuesByName = new Dictionary<string, DateTimeOffset>
+ {
+ ["timestamp"] = DateTimeOffset.Parse(
+ "2024-06-07T08:09:10Z",
+ CultureInfo.InvariantCulture,
+ DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal),
+ },
+ DurationValuesByName = new Dictionary<string, TimeSpan> {
["duration"] = TimeSpan.FromSeconds(10) },
+ EnumValuesByName = new Dictionary<string, example.ExampleState> {
["enum"] = example.ExampleState.Failed },
};
}
@@ -1106,6 +1136,27 @@ public sealed class RoundtripTests
AssertArrayMap(expected.Uint8ArrayValuesByName,
actual.Uint8ArrayValuesByName);
AssertArrayMap(expected.Float32ArrayValuesByName,
actual.Float32ArrayValuesByName);
AssertArrayMap(expected.Int32ArrayValuesByName,
actual.Int32ArrayValuesByName);
+ AssertMap(expected.StringValuesByDate, actual.StringValuesByDate);
+ AssertMap(expected.BoolValuesByName, actual.BoolValuesByName);
+ AssertMap(expected.Int8ValuesByName, actual.Int8ValuesByName);
+ AssertMap(expected.Int16ValuesByName, actual.Int16ValuesByName);
+ AssertMap(expected.FixedI32ValuesByName, actual.FixedI32ValuesByName);
+ AssertMap(expected.VarintI32ValuesByName,
actual.VarintI32ValuesByName);
+ AssertMap(expected.FixedI64ValuesByName, actual.FixedI64ValuesByName);
+ AssertMap(expected.VarintI64ValuesByName,
actual.VarintI64ValuesByName);
+ AssertMap(expected.TaggedI64ValuesByName,
actual.TaggedI64ValuesByName);
+ AssertMap(expected.Uint8ValuesByName, actual.Uint8ValuesByName);
+ AssertMap(expected.Uint16ValuesByName, actual.Uint16ValuesByName);
+ AssertMap(expected.FixedU32ValuesByName, actual.FixedU32ValuesByName);
+ AssertMap(expected.VarintU32ValuesByName,
actual.VarintU32ValuesByName);
+ AssertMap(expected.FixedU64ValuesByName, actual.FixedU64ValuesByName);
+ AssertMap(expected.VarintU64ValuesByName,
actual.VarintU64ValuesByName);
+ AssertMap(expected.TaggedU64ValuesByName,
actual.TaggedU64ValuesByName);
+ AssertMap(expected.Float32ValuesByName, actual.Float32ValuesByName);
+ AssertMap(expected.Float64ValuesByName, actual.Float64ValuesByName);
+ AssertMap(expected.TimestampValuesByName,
actual.TimestampValuesByName);
+ AssertMap(expected.DurationValuesByName, actual.DurationValuesByName);
+ AssertMap(expected.EnumValuesByName, actual.EnumValuesByName);
}
private static void AssertExampleLeaf(example.ExampleLeaf? expected,
example.ExampleLeaf? actual)
@@ -1491,22 +1542,22 @@ public sealed class RoundtripTests
result = [.. strEnumerable];
return true;
case IEnumerable<object?> objEnumerable:
- {
- List<string> normalized = [];
- foreach (object? item in objEnumerable)
{
- if (item is not string text)
+ List<string> normalized = [];
+ foreach (object? item in objEnumerable)
{
- result = [];
- return false;
+ if (item is not string text)
+ {
+ result = [];
+ return false;
+ }
+
+ normalized.Add(text);
}
- normalized.Add(text);
+ result = normalized;
+ return true;
}
-
- result = normalized;
- return true;
- }
default:
result = [];
return false;
@@ -1524,22 +1575,22 @@ public sealed class RoundtripTests
result = readonlyMap.ToDictionary(kv => kv.Key, kv =>
kv.Value);
return true;
case IEnumerable<KeyValuePair<object, object?>> objectPairs:
- {
- Dictionary<string, string> normalized = [];
- foreach (KeyValuePair<object, object?> pair in objectPairs)
{
- if (pair.Key is not string key || pair.Value is not string
val)
+ Dictionary<string, string> normalized = [];
+ foreach (KeyValuePair<object, object?> pair in objectPairs)
{
- result = [];
- return false;
+ if (pair.Key is not string key || pair.Value is not
string val)
+ {
+ result = [];
+ return false;
+ }
+
+ normalized[key] = val;
}
- normalized[key] = val;
+ result = normalized;
+ return true;
}
-
- result = normalized;
- return true;
- }
default:
result = [];
return false;
diff --git a/integration_tests/idl_tests/dart/test/idl_roundtrip_test.dart
b/integration_tests/idl_tests/dart/test/idl_roundtrip_test.dart
index e4d97cea7..c58660362 100644
--- a/integration_tests/idl_tests/dart/test/idl_roundtrip_test.dart
+++ b/integration_tests/idl_tests/dart/test/idl_roundtrip_test.dart
@@ -373,8 +373,10 @@ example.ExampleMessage buildExampleMessage() {
..uint32Array = Uint32List.fromList(<int>[2000000000, 2100000000])
..uint64Array = Uint64List.fromList(<int>[9000000000, 12000000000])
..float16Array = Float16List.fromList(<Float16>[Float16(1.0),
Float16(2.0)])
- ..bfloat16Array =
- Bfloat16List.fromList(<Bfloat16>[Bfloat16(1.0), Bfloat16(2.0)])
+ ..bfloat16Array = Bfloat16List.fromList(<Bfloat16>[
+ Bfloat16(1.0),
+ Bfloat16(2.0),
+ ])
..float32Array = Float32List.fromList(<double>[1.5, 2.5])
..float64Array = Float64List.fromList(<double>[3.5, 4.5])
..int32ArrayList = <Int32List>[
@@ -399,10 +401,10 @@ example.ExampleMessage buildExampleMessage() {
..stringValuesByVarintU32 = <int, String>{1234567891: 'varint-u32'}
..stringValuesByFixedU64 = <Uint64, String>{Uint64(9876543210):
'fixed-u64'}
..stringValuesByVarintU64 = <Uint64, String>{
- Uint64(9876543211): 'varint-u64'
+ Uint64(9876543211): 'varint-u64',
}
..stringValuesByTaggedU64 = <Uint64, String>{
- Uint64(9876543212): 'tagged-u64'
+ Uint64(9876543212): 'tagged-u64',
}
..stringValuesByString = <String, String>{'name': 'value'}
..stringValuesByTimestamp = <Timestamp, String>{
@@ -441,6 +443,35 @@ example.ExampleMessage buildExampleMessage() {
}
..int32ArrayValuesByName = <String, Int32List>{
'i32': Int32List.fromList(<int>[101, 202]),
+ }
+ ..stringValuesByDate = <LocalDate, String>{
+ const LocalDate(2024, 5, 7): 'date-key',
+ }
+ ..boolValuesByName = <String, bool>{'bool': true}
+ ..int8ValuesByName = <String, int>{'int8': -8}
+ ..int16ValuesByName = <String, int>{'int16': -16}
+ ..fixedI32ValuesByName = <String, int>{'fixed-i32': -32}
+ ..varintI32ValuesByName = <String, int>{'varint-i32': 32}
+ ..fixedI64ValuesByName = <String, Int64>{'fixed-i64': Int64(-64)}
+ ..varintI64ValuesByName = <String, Int64>{'varint-i64': Int64(64)}
+ ..taggedI64ValuesByName = <String, Int64>{'tagged-i64': Int64(65)}
+ ..uint8ValuesByName = <String, int>{'uint8': 208}
+ ..uint16ValuesByName = <String, int>{'uint16': 60001}
+ ..fixedU32ValuesByName = <String, int>{'fixed-u32': 1234567892}
+ ..varintU32ValuesByName = <String, int>{'varint-u32': 1234567893}
+ ..fixedU64ValuesByName = <String, Uint64>{'fixed-u64': Uint64(9876543213)}
+ ..varintU64ValuesByName = <String, Uint64>{'varint-u64':
Uint64(9876543214)}
+ ..taggedU64ValuesByName = <String, Uint64>{'tagged-u64':
Uint64(9876543215)}
+ ..float32ValuesByName = <String, Float32>{'float32': Float32(3.25)}
+ ..float64ValuesByName = <String, double>{'float64': 6.5}
+ ..timestampValuesByName = <String, Timestamp>{
+ 'timestamp': Timestamp.fromDateTime(DateTime.utc(2024, 6, 7, 8, 9, 10)),
+ }
+ ..durationValuesByName = <String, Duration>{
+ 'duration': const Duration(seconds: 10),
+ }
+ ..enumValuesByName = <String, example.ExampleState>{
+ 'enum': example.ExampleState.failed,
};
}
@@ -1049,32 +1080,56 @@ void _expectExampleMessageEquals(
_expectMapEquals(actual.stringValuesByInt8, expected.stringValuesByInt8);
_expectMapEquals(actual.stringValuesByInt16, expected.stringValuesByInt16);
_expectMapEquals(
- actual.stringValuesByFixedI32, expected.stringValuesByFixedI32);
+ actual.stringValuesByFixedI32,
+ expected.stringValuesByFixedI32,
+ );
_expectMapEquals(
- actual.stringValuesByVarintI32, expected.stringValuesByVarintI32);
+ actual.stringValuesByVarintI32,
+ expected.stringValuesByVarintI32,
+ );
_expectMapEquals(
- actual.stringValuesByFixedI64, expected.stringValuesByFixedI64);
+ actual.stringValuesByFixedI64,
+ expected.stringValuesByFixedI64,
+ );
_expectMapEquals(
- actual.stringValuesByVarintI64, expected.stringValuesByVarintI64);
+ actual.stringValuesByVarintI64,
+ expected.stringValuesByVarintI64,
+ );
_expectMapEquals(
- actual.stringValuesByTaggedI64, expected.stringValuesByTaggedI64);
+ actual.stringValuesByTaggedI64,
+ expected.stringValuesByTaggedI64,
+ );
_expectMapEquals(actual.stringValuesByUint8, expected.stringValuesByUint8);
_expectMapEquals(actual.stringValuesByUint16, expected.stringValuesByUint16);
_expectMapEquals(
- actual.stringValuesByFixedU32, expected.stringValuesByFixedU32);
+ actual.stringValuesByFixedU32,
+ expected.stringValuesByFixedU32,
+ );
_expectMapEquals(
- actual.stringValuesByVarintU32, expected.stringValuesByVarintU32);
+ actual.stringValuesByVarintU32,
+ expected.stringValuesByVarintU32,
+ );
_expectMapEquals(
- actual.stringValuesByFixedU64, expected.stringValuesByFixedU64);
+ actual.stringValuesByFixedU64,
+ expected.stringValuesByFixedU64,
+ );
_expectMapEquals(
- actual.stringValuesByVarintU64, expected.stringValuesByVarintU64);
+ actual.stringValuesByVarintU64,
+ expected.stringValuesByVarintU64,
+ );
_expectMapEquals(
- actual.stringValuesByTaggedU64, expected.stringValuesByTaggedU64);
+ actual.stringValuesByTaggedU64,
+ expected.stringValuesByTaggedU64,
+ );
_expectMapEquals(actual.stringValuesByString, expected.stringValuesByString);
_expectMapEquals(
- actual.stringValuesByTimestamp, expected.stringValuesByTimestamp);
+ actual.stringValuesByTimestamp,
+ expected.stringValuesByTimestamp,
+ );
_expectMapEquals(
- actual.stringValuesByDuration, expected.stringValuesByDuration);
+ actual.stringValuesByDuration,
+ expected.stringValuesByDuration,
+ );
_expectMapEquals(actual.stringValuesByEnum, expected.stringValuesByEnum);
_expectMapEquals(actual.float16ValuesByName, expected.float16ValuesByName);
_expectMapEquals(
@@ -1093,7 +1148,9 @@ void _expectExampleMessageEquals(
_expectMapEquals(actual.dateValuesByName, expected.dateValuesByName);
_expectMapEquals(actual.decimalValuesByName, expected.decimalValuesByName);
expect(
- actual.messageValuesByName.length, expected.messageValuesByName.length);
+ actual.messageValuesByName.length,
+ expected.messageValuesByName.length,
+ );
for (final entry in expected.messageValuesByName.entries) {
final actualValue = actual.messageValuesByName[entry.key];
expect(actualValue, isNotNull);
@@ -1117,6 +1174,48 @@ void _expectExampleMessageEquals(
actual.int32ArrayValuesByName,
expected.int32ArrayValuesByName,
);
+ _expectMapEquals(actual.stringValuesByDate, expected.stringValuesByDate);
+ _expectMapEquals(actual.boolValuesByName, expected.boolValuesByName);
+ _expectMapEquals(actual.int8ValuesByName, expected.int8ValuesByName);
+ _expectMapEquals(actual.int16ValuesByName, expected.int16ValuesByName);
+ _expectMapEquals(actual.fixedI32ValuesByName, expected.fixedI32ValuesByName);
+ _expectMapEquals(
+ actual.varintI32ValuesByName,
+ expected.varintI32ValuesByName,
+ );
+ _expectMapEquals(actual.fixedI64ValuesByName, expected.fixedI64ValuesByName);
+ _expectMapEquals(
+ actual.varintI64ValuesByName,
+ expected.varintI64ValuesByName,
+ );
+ _expectMapEquals(
+ actual.taggedI64ValuesByName,
+ expected.taggedI64ValuesByName,
+ );
+ _expectMapEquals(actual.uint8ValuesByName, expected.uint8ValuesByName);
+ _expectMapEquals(actual.uint16ValuesByName, expected.uint16ValuesByName);
+ _expectMapEquals(actual.fixedU32ValuesByName, expected.fixedU32ValuesByName);
+ _expectMapEquals(
+ actual.varintU32ValuesByName,
+ expected.varintU32ValuesByName,
+ );
+ _expectMapEquals(actual.fixedU64ValuesByName, expected.fixedU64ValuesByName);
+ _expectMapEquals(
+ actual.varintU64ValuesByName,
+ expected.varintU64ValuesByName,
+ );
+ _expectMapEquals(
+ actual.taggedU64ValuesByName,
+ expected.taggedU64ValuesByName,
+ );
+ _expectMapEquals(actual.float32ValuesByName, expected.float32ValuesByName);
+ _expectMapEquals(actual.float64ValuesByName, expected.float64ValuesByName);
+ _expectMapEquals(
+ actual.timestampValuesByName,
+ expected.timestampValuesByName,
+ );
+ _expectMapEquals(actual.durationValuesByName, expected.durationValuesByName);
+ _expectMapEquals(actual.enumValuesByName, expected.enumValuesByName);
}
void _expectExampleMessageUnionEquals(
diff --git a/integration_tests/idl_tests/go/idl_roundtrip_test.go
b/integration_tests/idl_tests/go/idl_roundtrip_test.go
index 02de5689f..ec41e120c 100644
--- a/integration_tests/idl_tests/go/idl_roundtrip_test.go
+++ b/integration_tests/idl_tests/go/idl_roundtrip_test.go
@@ -513,6 +513,27 @@ func buildExampleMessage() example.ExampleMessage {
Uint8ArrayValuesByName: map[string][]uint8{"u8": {201, 202}},
Float32ArrayValuesByName: map[string][]float32{"f32": {1.25,
2.5}},
Int32ArrayValuesByName: map[string][]int32{"i32": {101, 202}},
+ StringValuesByDate: map[fory.Date]string{{Year: 2024,
Month: time.May, Day: 7}: "date-key"},
+ BoolValuesByName: map[string]bool{"bool": true},
+ Int8ValuesByName: map[string]int8{"int8": -8},
+ Int16ValuesByName: map[string]int16{"int16": -16},
+ FixedI32ValuesByName: map[string]int32{"fixed-i32": -32},
+ VarintI32ValuesByName: map[string]int32{"varint-i32": 32},
+ FixedI64ValuesByName: map[string]int64{"fixed-i64": -64},
+ VarintI64ValuesByName: map[string]int64{"varint-i64": 64},
+ TaggedI64ValuesByName: map[string]int64{"tagged-i64": 65},
+ Uint8ValuesByName: map[string]uint8{"uint8": 208},
+ Uint16ValuesByName: map[string]uint16{"uint16": 60001},
+ FixedU32ValuesByName: map[string]uint32{"fixed-u32":
1234567892},
+ VarintU32ValuesByName: map[string]uint32{"varint-u32":
1234567893},
+ FixedU64ValuesByName: map[string]uint64{"fixed-u64":
9876543213},
+ VarintU64ValuesByName: map[string]uint64{"varint-u64":
9876543214},
+ TaggedU64ValuesByName: map[string]uint64{"tagged-u64":
9876543215},
+ Float32ValuesByName: map[string]float32{"float32": 3.25},
+ Float64ValuesByName: map[string]float64{"float64": 6.5},
+ TimestampValuesByName: map[string]time.Time{"timestamp":
time.Date(2024, 6, 7, 8, 9, 10, 0, time.UTC)},
+ DurationValuesByName: map[string]time.Duration{"duration":
10 * time.Second},
+ EnumValuesByName:
map[string]example.ExampleState{"enum": example.ExampleStateFailed},
}
setOptionalExampleMessageFields(&message)
return message
@@ -628,6 +649,13 @@ func normalizeExampleMessageForCompare(message
example.ExampleMessage) example.E
}
message.StringValuesByTimestamp = normalized
}
+ if message.TimestampValuesByName != nil {
+ normalized := make(map[string]time.Time,
len(message.TimestampValuesByName))
+ for key, value := range message.TimestampValuesByName {
+ normalized[key] = value.UTC()
+ }
+ message.TimestampValuesByName = normalized
+ }
value := reflect.ValueOf(&message).Elem()
for i := 0; i < value.NumField(); i++ {
field := value.Field(i)
diff --git a/integration_tests/idl_tests/idl/example.fdl
b/integration_tests/idl_tests/idl/example.fdl
index 7e2960991..4ade5cd85 100644
--- a/integration_tests/idl_tests/idl/example.fdl
+++ b/integration_tests/idl_tests/idl/example.fdl
@@ -145,6 +145,27 @@ message ExampleMessage [id=1500, evolving=true] {
map<string, array<uint8>> uint8_array_values_by_name = 231;
map<string, array<float32>> float32_array_values_by_name = 232;
map<string, array<int32>> int32_array_values_by_name = 233;
+ map<date, string> string_values_by_date = 234;
+ map<string, bool> bool_values_by_name = 236;
+ map<string, int8> int8_values_by_name = 237;
+ map<string, int16> int16_values_by_name = 238;
+ map<string, fixed int32> fixed_i32_values_by_name = 239;
+ map<string, int32> varint_i32_values_by_name = 240;
+ map<string, fixed int64> fixed_i64_values_by_name = 241;
+ map<string, int64> varint_i64_values_by_name = 242;
+ map<string, tagged int64> tagged_i64_values_by_name = 243;
+ map<string, uint8> uint8_values_by_name = 244;
+ map<string, uint16> uint16_values_by_name = 245;
+ map<string, fixed uint32> fixed_u32_values_by_name = 246;
+ map<string, uint32> varint_u32_values_by_name = 247;
+ map<string, fixed uint64> fixed_u64_values_by_name = 248;
+ map<string, uint64> varint_u64_values_by_name = 249;
+ map<string, tagged uint64> tagged_u64_values_by_name = 250;
+ map<string, float32> float32_values_by_name = 251;
+ map<string, float64> float64_values_by_name = 252;
+ map<string, timestamp> timestamp_values_by_name = 253;
+ map<string, duration> duration_values_by_name = 254;
+ map<string, ExampleState> enum_values_by_name = 255;
}
union ExampleMessageUnion [id=1501] {
@@ -254,4 +275,25 @@ union ExampleMessageUnion [id=1501] {
map<string, array<uint8>> uint8_array_values_by_name = 231;
map<string, array<float32>> float32_array_values_by_name = 232;
map<string, array<int32>> int32_array_values_by_name = 233;
+ map<date, string> string_values_by_date = 234;
+ map<string, bool> bool_values_by_name = 236;
+ map<string, int8> int8_values_by_name = 237;
+ map<string, int16> int16_values_by_name = 238;
+ map<string, fixed int32> fixed_i32_values_by_name = 239;
+ map<string, int32> varint_i32_values_by_name = 240;
+ map<string, fixed int64> fixed_i64_values_by_name = 241;
+ map<string, int64> varint_i64_values_by_name = 242;
+ map<string, tagged int64> tagged_i64_values_by_name = 243;
+ map<string, uint8> uint8_values_by_name = 244;
+ map<string, uint16> uint16_values_by_name = 245;
+ map<string, fixed uint32> fixed_u32_values_by_name = 246;
+ map<string, uint32> varint_u32_values_by_name = 247;
+ map<string, fixed uint64> fixed_u64_values_by_name = 248;
+ map<string, uint64> varint_u64_values_by_name = 249;
+ map<string, tagged uint64> tagged_u64_values_by_name = 250;
+ map<string, float32> float32_values_by_name = 251;
+ map<string, float64> float64_values_by_name = 252;
+ map<string, timestamp> timestamp_values_by_name = 253;
+ map<string, duration> duration_values_by_name = 254;
+ map<string, ExampleState> enum_values_by_name = 255;
}
diff --git
a/integration_tests/idl_tests/java/src/test/java/org/apache/fory/idl_tests/IdlRoundTripTest.java
b/integration_tests/idl_tests/java/src/test/java/org/apache/fory/idl_tests/IdlRoundTripTest.java
index ae702146a..cd1f2ea0f 100644
---
a/integration_tests/idl_tests/java/src/test/java/org/apache/fory/idl_tests/IdlRoundTripTest.java
+++
b/integration_tests/idl_tests/java/src/test/java/org/apache/fory/idl_tests/IdlRoundTripTest.java
@@ -27,6 +27,10 @@ import addressbook.Dog;
import addressbook.Person;
import addressbook.Person.PhoneNumber;
import addressbook.Person.PhoneType;
+import any_example.AnyExampleForyRegistration;
+import any_example.AnyHolder;
+import any_example.AnyInner;
+import any_example.AnyUnion;
import auto_id.AutoIdForyRegistration;
import auto_id.Envelope;
import auto_id.Wrapper;
@@ -35,12 +39,6 @@ import collection.NumericCollectionArrayUnion;
import collection.NumericCollectionUnion;
import collection.NumericCollections;
import collection.NumericCollectionsArray;
-import complex_pb.ComplexPbForyRegistration;
-import complex_pb.PrimitiveTypes;
-import any_example.AnyExampleForyRegistration;
-import any_example.AnyHolder;
-import any_example.AnyInner;
-import any_example.AnyUnion;
import complex_fbs.ComplexFbsForyRegistration;
import complex_fbs.Container;
import complex_fbs.Metric;
@@ -48,6 +46,8 @@ import complex_fbs.Note;
import complex_fbs.Payload;
import complex_fbs.ScalarPack;
import complex_fbs.Status;
+import complex_pb.ComplexPbForyRegistration;
+import complex_pb.PrimitiveTypes;
import evolving1.Evolving1ForyRegistration;
import evolving1.EvolvingMessage;
import evolving1.EvolvingSizeMessage;
@@ -64,17 +64,6 @@ import graph.Edge;
import graph.Graph;
import graph.GraphForyRegistration;
import graph.Node;
-import root.MultiHolder;
-import optional_types.AllOptionalTypes;
-import optional_types.OptionalHolder;
-import optional_types.OptionalTypesForyRegistration;
-import optional_types.OptionalUnion;
-import tree.TreeForyRegistration;
-import tree.TreeNode;
-import monster.Color;
-import monster.Monster;
-import monster.MonsterForyRegistration;
-import monster.Vec3;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -94,6 +83,14 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
+import monster.Color;
+import monster.Monster;
+import monster.MonsterForyRegistration;
+import monster.Vec3;
+import optional_types.AllOptionalTypes;
+import optional_types.OptionalHolder;
+import optional_types.OptionalTypesForyRegistration;
+import optional_types.OptionalUnion;
import org.apache.fory.Fory;
import org.apache.fory.collection.BFloat16List;
import org.apache.fory.collection.BoolList;
@@ -114,6 +111,9 @@ import org.apache.fory.type.Float16;
import org.apache.fory.type.Float16Array;
import org.testng.Assert;
import org.testng.annotations.Test;
+import root.MultiHolder;
+import tree.TreeForyRegistration;
+import tree.TreeNode;
public class IdlRoundTripTest {
@@ -266,8 +266,7 @@ public class IdlRoundTripTest {
Object fixedSizeDecoded = foryV2.deserialize(fixedSizeBytes);
Assert.assertTrue(fixedSizeDecoded instanceof evolving2.FixedSizeMessage);
Assert.assertEquals(
- ((evolving2.FixedSizeMessage) fixedSizeDecoded).getPayload(),
- fixedSizeV1.getPayload());
+ ((evolving2.FixedSizeMessage) fixedSizeDecoded).getPayload(),
fixedSizeV1.getPayload());
Object fixedSizeRoundTrip =
foryV1.deserialize(foryV2.serialize(fixedSizeDecoded));
Assert.assertTrue(fixedSizeRoundTrip instanceof FixedSizeMessage);
Assert.assertEquals(fixedSizeRoundTrip, fixedSizeV1);
@@ -399,18 +398,15 @@ public class IdlRoundTripTest {
assertNumericCollectionArrayUnion(arrayUnionDecoded, collectionArrayUnion);
for (String peer : resolvePeers()) {
- Path collectionsFile =
- Files.createTempFile("idl-collections-" + peer + "-", ".bin");
+ Path collectionsFile = Files.createTempFile("idl-collections-" + peer +
"-", ".bin");
collectionsFile.toFile().deleteOnExit();
Files.write(collectionsFile, collectionsBytes);
- Path unionFile =
- Files.createTempFile("idl-collection-union-" + peer + "-", ".bin");
+ Path unionFile = Files.createTempFile("idl-collection-union-" + peer +
"-", ".bin");
unionFile.toFile().deleteOnExit();
Files.write(unionFile, unionBytes);
- Path arrayFile =
- Files.createTempFile("idl-collections-array-" + peer + "-", ".bin");
+ Path arrayFile = Files.createTempFile("idl-collections-array-" + peer +
"-", ".bin");
arrayFile.toFile().deleteOnExit();
Files.write(arrayFile, arrayBytes);
@@ -423,8 +419,7 @@ public class IdlRoundTripTest {
env.put("DATA_FILE_COLLECTION",
collectionsFile.toAbsolutePath().toString());
env.put("DATA_FILE_COLLECTION_UNION",
unionFile.toAbsolutePath().toString());
env.put("DATA_FILE_COLLECTION_ARRAY",
arrayFile.toAbsolutePath().toString());
- env.put(
- "DATA_FILE_COLLECTION_ARRAY_UNION",
arrayUnionFile.toAbsolutePath().toString());
+ env.put("DATA_FILE_COLLECTION_ARRAY_UNION",
arrayUnionFile.toAbsolutePath().toString());
PeerCommand command = buildPeerCommand(peer, env, compatible);
runPeer(command, peer);
@@ -667,13 +662,11 @@ public class IdlRoundTripTest {
Assert.assertEquals(containerDecoded, container);
for (String peer : resolvePeers()) {
- Path monsterFile =
- Files.createTempFile("idl-flatbuffers-monster-" + peer + "-",
".bin");
+ Path monsterFile = Files.createTempFile("idl-flatbuffers-monster-" +
peer + "-", ".bin");
monsterFile.toFile().deleteOnExit();
Files.write(monsterFile, monsterBytes);
- Path containerFile =
- Files.createTempFile("idl-flatbuffers-test2-" + peer + "-", ".bin");
+ Path containerFile = Files.createTempFile("idl-flatbuffers-test2-" +
peer + "-", ".bin");
containerFile.toFile().deleteOnExit();
Files.write(containerFile, containerBytes);
@@ -696,18 +689,11 @@ public class IdlRoundTripTest {
}
private Fory buildFory(boolean compatible) {
- return Fory.builder()
- .withXlang(true)
- .withCompatible(compatible)
- .build();
+ return Fory.builder().withXlang(true).withCompatible(compatible).build();
}
private Fory buildRefFory(boolean compatible) {
- return Fory.builder()
- .withXlang(true)
- .withCompatible(compatible)
- .withRefTracking(true)
- .build();
+ return
Fory.builder().withXlang(true).withCompatible(compatible).withRefTracking(true).build();
}
private List<String> resolvePeers() {
@@ -802,10 +788,7 @@ public class IdlRoundTripTest {
workDir = idlRoot.resolve("dart");
command =
Arrays.asList(
- "dart",
- "test",
- "--name",
- "interop file roundtrip hooks when env vars are set");
+ "dart", "test", "--name", "interop file roundtrip hooks when
env vars are set");
peerCommand.environment.put("ENABLE_FORY_DEBUG_OUTPUT", "1");
break;
default:
@@ -834,9 +817,7 @@ public class IdlRoundTripTest {
process.waitFor(10, TimeUnit.SECONDS);
String output = outputCollector.awaitOutput();
Assert.fail(
- "Peer process timed out for "
- + peer
- + (output.isEmpty() ? "" : "\noutput:\n" + output));
+ "Peer process timed out for " + peer + (output.isEmpty() ? "" :
"\noutput:\n" + output));
}
int exitCode = process.exitValue();
@@ -1085,8 +1066,7 @@ public class IdlRoundTripTest {
message.setDateList(Arrays.asList(LocalDate.of(2024, 1, 1),
LocalDate.of(2024, 1, 2)));
message.setTimestampList(
Arrays.asList(
- Instant.parse("2024-01-01T00:00:00Z"),
- Instant.parse("2024-01-02T00:00:00Z")));
+ Instant.parse("2024-01-01T00:00:00Z"),
Instant.parse("2024-01-02T00:00:00Z")));
message.setDurationList(Arrays.asList(Duration.ofMillis(1),
Duration.ofSeconds(2)));
message.setDecimalList(Arrays.asList(new BigDecimal("1.25"), new
BigDecimal("2.50")));
message.setEnumList(Arrays.asList(ExampleState.UNKNOWN,
ExampleState.FAILED));
@@ -1144,6 +1124,27 @@ public class IdlRoundTripTest {
message.setUint8ArrayValuesByName(Map.of("u8", new byte[] {(byte) 201,
(byte) 202}));
message.setFloat32ArrayValuesByName(Map.of("f32", new float[] {1.25f,
2.5f}));
message.setInt32ArrayValuesByName(Map.of("i32", new int[] {101, 202}));
+ message.setStringValuesByDate(Map.of(LocalDate.of(2024, 5, 7),
"date-key"));
+ message.setBoolValuesByName(Map.of("bool", true));
+ message.setInt8ValuesByName(Map.of("int8", (byte) -8));
+ message.setInt16ValuesByName(Map.of("int16", (short) -16));
+ message.setFixedI32ValuesByName(Map.of("fixed-i32", -32));
+ message.setVarintI32ValuesByName(Map.of("varint-i32", 32));
+ message.setFixedI64ValuesByName(Map.of("fixed-i64", -64L));
+ message.setVarintI64ValuesByName(Map.of("varint-i64", 64L));
+ message.setTaggedI64ValuesByName(Map.of("tagged-i64", 65L));
+ message.setUint8ValuesByName(Map.of("uint8", 208));
+ message.setUint16ValuesByName(Map.of("uint16", 60001));
+ message.setFixedU32ValuesByName(Map.of("fixed-u32", 1234567892L));
+ message.setVarintU32ValuesByName(Map.of("varint-u32", 1234567893L));
+ message.setFixedU64ValuesByName(Map.of("fixed-u64", 9876543213L));
+ message.setVarintU64ValuesByName(Map.of("varint-u64", 9876543214L));
+ message.setTaggedU64ValuesByName(Map.of("tagged-u64", 9876543215L));
+ message.setFloat32ValuesByName(Map.of("float32", 3.25f));
+ message.setFloat64ValuesByName(Map.of("float64", 6.5d));
+ message.setTimestampValuesByName(Map.of("timestamp",
Instant.parse("2024-06-07T08:09:10Z")));
+ message.setDurationValuesByName(Map.of("duration",
Duration.ofSeconds(10)));
+ message.setEnumValuesByName(Map.of("enum", ExampleState.FAILED));
return message;
}
@@ -1159,11 +1160,11 @@ public class IdlRoundTripTest {
Arrays.asList(new int[] {11, 12}, new int[] {13, 14}));
}
- private void assertNumericCollectionUnion(
- Object decoded, NumericCollectionUnion expected) {
+ private void assertNumericCollectionUnion(Object decoded,
NumericCollectionUnion expected) {
Assert.assertTrue(decoded instanceof NumericCollectionUnion);
NumericCollectionUnion union = (NumericCollectionUnion) decoded;
- Assert.assertEquals(union.getNumericCollectionUnionCase(),
expected.getNumericCollectionUnionCase());
+ Assert.assertEquals(
+ union.getNumericCollectionUnionCase(),
expected.getNumericCollectionUnionCase());
switch (union.getNumericCollectionUnionCase()) {
case INT32_VALUES:
Assert.assertEquals(union.getInt32Values(), expected.getInt32Values());
@@ -1178,16 +1179,13 @@ public class IdlRoundTripTest {
Assert.assertTrue(decoded instanceof NumericCollectionArrayUnion);
NumericCollectionArrayUnion union = (NumericCollectionArrayUnion) decoded;
Assert.assertEquals(
- union.getNumericCollectionArrayUnionCase(),
- expected.getNumericCollectionArrayUnionCase());
+ union.getNumericCollectionArrayUnionCase(),
expected.getNumericCollectionArrayUnionCase());
switch (union.getNumericCollectionArrayUnionCase()) {
case UINT16_VALUES:
- Assert.assertTrue(
- Arrays.equals(union.getUint16Values(),
expected.getUint16Values()));
+ Assert.assertTrue(Arrays.equals(union.getUint16Values(),
expected.getUint16Values()));
break;
default:
- Assert.fail(
- "Unexpected array union case: " +
union.getNumericCollectionArrayUnionCase());
+ Assert.fail("Unexpected array union case: " +
union.getNumericCollectionArrayUnionCase());
}
}
diff --git a/integration_tests/idl_tests/javascript/roundtrip.ts
b/integration_tests/idl_tests/javascript/roundtrip.ts
index 020747427..23af999e0 100644
--- a/integration_tests/idl_tests/javascript/roundtrip.ts
+++ b/integration_tests/idl_tests/javascript/roundtrip.ts
@@ -147,11 +147,10 @@ function resolveRootSerializer(fory: Fory, bytes:
Uint8Array): Serializer {
// serializer detection from the payload, then map back to the local
// registered serializer when available.
const detectedSerializer = AnyHelper.detectSerializer(fory.readContext);
- const resolvedSerializer = (
+ const resolvedSerializer =
fory.typeResolver.getSerializerByTypeInfo(
detectedSerializer.getTypeInfo(),
- ) ?? detectedSerializer
- );
+ ) ?? detectedSerializer;
return resolvedSerializer;
}
@@ -514,7 +513,9 @@ function buildExampleMessage(): ExampleMessage {
stringValuesByVarintU64: new Map([[9876543211n, "varint-u64"]]),
stringValuesByTaggedU64: new Map([[9876543212n, "tagged-u64"]]),
stringValuesByString: new Map([["name", "value"]]),
- stringValuesByTimestamp: new Map([[new Date("2024-03-04T05:06:07Z"),
"time"]]),
+ stringValuesByTimestamp: new Map([
+ [new Date("2024-03-04T05:06:07Z"), "time"],
+ ]),
stringValuesByDuration: new Map([[9000, "duration"]]),
stringValuesByEnum: new Map([[ExampleState.READY, "ready"]]),
float16ValuesByName: new Map([["f16", 1.25]]),
@@ -529,10 +530,31 @@ function buildExampleMessage(): ExampleMessage {
["union", { case: ExampleLeafUnionCase.CODE, value: 42 }],
]),
uint8ArrayValuesByName: new Map([["u8", new Uint8Array([201, 202])]]),
- float32ArrayValuesByName: new Map([
- ["f32", new Float32Array([1.25, 2.5])],
- ]),
+ float32ArrayValuesByName: new Map([["f32", new Float32Array([1.25,
2.5])]]),
int32ArrayValuesByName: new Map([["i32", new Int32Array([101, 202])]]),
+ stringValuesByDate: new Map([[buildLocalDate(2024, 5, 7), "date-key"]]),
+ boolValuesByName: new Map([["bool", true]]),
+ int8ValuesByName: new Map([["int8", -8]]),
+ int16ValuesByName: new Map([["int16", -16]]),
+ fixedI32ValuesByName: new Map([["fixed-i32", -32]]),
+ varintI32ValuesByName: new Map([["varint-i32", 32]]),
+ fixedI64ValuesByName: new Map([["fixed-i64", -64n]]),
+ varintI64ValuesByName: new Map([["varint-i64", 64n]]),
+ taggedI64ValuesByName: new Map([["tagged-i64", 65n]]),
+ uint8ValuesByName: new Map([["uint8", 208]]),
+ uint16ValuesByName: new Map([["uint16", 60001]]),
+ fixedU32ValuesByName: new Map([["fixed-u32", 1234567892]]),
+ varintU32ValuesByName: new Map([["varint-u32", 1234567893]]),
+ fixedU64ValuesByName: new Map([["fixed-u64", 9876543213n]]),
+ varintU64ValuesByName: new Map([["varint-u64", 9876543214n]]),
+ taggedU64ValuesByName: new Map([["tagged-u64", 9876543215n]]),
+ float32ValuesByName: new Map([["float32", 3.25]]),
+ float64ValuesByName: new Map([["float64", 6.5]]),
+ timestampValuesByName: new Map([
+ ["timestamp", new Date("2024-06-07T08:09:10Z")],
+ ]),
+ durationValuesByName: new Map([["duration", 10000]]),
+ enumValuesByName: new Map([["enum", ExampleState.FAILED]]),
};
}
diff --git a/integration_tests/idl_tests/javascript/test/roundtrip.test.ts
b/integration_tests/idl_tests/javascript/test/roundtrip.test.ts
index 953b79af6..2d3a3b276 100644
--- a/integration_tests/idl_tests/javascript/test/roundtrip.test.ts
+++ b/integration_tests/idl_tests/javascript/test/roundtrip.test.ts
@@ -460,7 +460,9 @@ function buildExampleMessage(): ExampleMessage {
stringValuesByVarintU64: new Map([[9876543211n, "varint-u64"]]),
stringValuesByTaggedU64: new Map([[9876543212n, "tagged-u64"]]),
stringValuesByString: new Map([["name", "value"]]),
- stringValuesByTimestamp: new Map([[new Date("2024-03-04T05:06:07Z"),
"time"]]),
+ stringValuesByTimestamp: new Map([
+ [new Date("2024-03-04T05:06:07Z"), "time"],
+ ]),
stringValuesByDuration: new Map([[9000, "duration"]]),
stringValuesByEnum: new Map([[ExampleState.READY, "ready"]]),
float16ValuesByName: new Map([["f16", 1.25]]),
@@ -475,10 +477,31 @@ function buildExampleMessage(): ExampleMessage {
["union", { case: ExampleLeafUnionCase.CODE, value: 42 }],
]),
uint8ArrayValuesByName: new Map([["u8", new Uint8Array([201, 202])]]),
- float32ArrayValuesByName: new Map([
- ["f32", new Float32Array([1.25, 2.5])],
- ]),
+ float32ArrayValuesByName: new Map([["f32", new Float32Array([1.25,
2.5])]]),
int32ArrayValuesByName: new Map([["i32", new Int32Array([101, 202])]]),
+ stringValuesByDate: new Map([[buildLocalDate(2024, 5, 7), "date-key"]]),
+ boolValuesByName: new Map([["bool", true]]),
+ int8ValuesByName: new Map([["int8", -8]]),
+ int16ValuesByName: new Map([["int16", -16]]),
+ fixedI32ValuesByName: new Map([["fixed-i32", -32]]),
+ varintI32ValuesByName: new Map([["varint-i32", 32]]),
+ fixedI64ValuesByName: new Map([["fixed-i64", -64n]]),
+ varintI64ValuesByName: new Map([["varint-i64", 64n]]),
+ taggedI64ValuesByName: new Map([["tagged-i64", 65n]]),
+ uint8ValuesByName: new Map([["uint8", 208]]),
+ uint16ValuesByName: new Map([["uint16", 60001]]),
+ fixedU32ValuesByName: new Map([["fixed-u32", 1234567892]]),
+ varintU32ValuesByName: new Map([["varint-u32", 1234567893]]),
+ fixedU64ValuesByName: new Map([["fixed-u64", 9876543213n]]),
+ varintU64ValuesByName: new Map([["varint-u64", 9876543214n]]),
+ taggedU64ValuesByName: new Map([["tagged-u64", 9876543215n]]),
+ float32ValuesByName: new Map([["float32", 3.25]]),
+ float64ValuesByName: new Map([["float64", 6.5]]),
+ timestampValuesByName: new Map([
+ ["timestamp", new Date("2024-06-07T08:09:10Z")],
+ ]),
+ durationValuesByName: new Map([["duration", 10000]]),
+ enumValuesByName: new Map([["enum", ExampleState.FAILED]]),
};
}
diff --git a/integration_tests/idl_tests/python/idl_tests/roundtrip.py
b/integration_tests/idl_tests/python/idl_tests/roundtrip.py
index 76bdb3731..942386c05 100644
--- a/integration_tests/idl_tests/python/idl_tests/roundtrip.py
+++ b/integration_tests/idl_tests/python/idl_tests/roundtrip.py
@@ -540,6 +540,31 @@ def build_example_message() -> "example.ExampleMessage":
union_values_by_name={"union": example.ExampleLeafUnion.code(42)},
uint8_array_values_by_name={"u8": np.array([201, 202],
dtype=np.uint8)},
float32_array_values_by_name={"f32": np.array([1.25, 2.5],
dtype=np.float32)},
+ string_values_by_date={datetime.date(2024, 5, 7): "date-key"},
+ bool_values_by_name={"bool": True},
+ int8_values_by_name={"int8": -8},
+ int16_values_by_name={"int16": -16},
+ fixed_i32_values_by_name={"fixed-i32": -32},
+ varint_i32_values_by_name={"varint-i32": 32},
+ fixed_i64_values_by_name={"fixed-i64": -64},
+ varint_i64_values_by_name={"varint-i64": 64},
+ tagged_i64_values_by_name={"tagged-i64": 65},
+ uint8_values_by_name={"uint8": 208},
+ uint16_values_by_name={"uint16": 60001},
+ fixed_u32_values_by_name={"fixed-u32": 1234567892},
+ varint_u32_values_by_name={"varint-u32": 1234567893},
+ fixed_u64_values_by_name={"fixed-u64": 9876543213},
+ varint_u64_values_by_name={"varint-u64": 9876543214},
+ tagged_u64_values_by_name={"tagged-u64": 9876543215},
+ float32_values_by_name={"float32": 3.25},
+ float64_values_by_name={"float64": 6.5},
+ timestamp_values_by_name={
+ "timestamp": datetime.datetime(
+ 2024, 6, 7, 8, 9, 10, tzinfo=datetime.timezone.utc
+ )
+ },
+ duration_values_by_name={"duration": datetime.timedelta(seconds=10)},
+ enum_values_by_name={"enum": example.ExampleState.FAILED},
)
fields = example.ExampleMessage.__dataclass_fields__
if "uint8_array_list" in fields:
diff --git a/integration_tests/idl_tests/rust/tests/idl_roundtrip.rs
b/integration_tests/idl_tests/rust/tests/idl_roundtrip.rs
index 201c5359f..1e1b7b1c2 100644
--- a/integration_tests/idl_tests/rust/tests/idl_roundtrip.rs
+++ b/integration_tests/idl_tests/rust/tests/idl_roundtrip.rs
@@ -32,7 +32,7 @@ use idl_tests::generated::collection::{
self, NumericCollectionArrayUnion, NumericCollectionUnion,
NumericCollections,
NumericCollectionsArray,
};
-use idl_tests::generated::complex_fbs::{self, Container, Note, Payload,
ScalarPack, Status};
+use idl_tests::generated::complex_fbs::{self, Container, Payload, ScalarPack,
Status};
use idl_tests::generated::complex_pb::{self, PrimitiveTypes};
use idl_tests::generated::evolving1;
use idl_tests::generated::evolving2;
@@ -54,11 +54,7 @@ fn build_address_book() -> AddressBook {
phone_type: PhoneType::Work,
};
- let mut pet = Animal::Dog(Dog {
- name: "Rex".to_string(),
- bark_volume: 5,
- });
- pet = Animal::Cat(Cat {
+ let pet = Animal::Cat(Cat {
name: "Mimi".to_string(),
lives: 9,
});
@@ -152,8 +148,7 @@ fn test_to_bytes_from_bytes() {
}
fn build_primitive_types() -> PrimitiveTypes {
- let mut contact =
complex_pb::primitive_types::Contact::Email("[email protected]".to_string());
- contact = complex_pb::primitive_types::Contact::Phone(12345);
+ let contact = complex_pb::primitive_types::Contact::Phone(12345);
PrimitiveTypes {
bool_value: true,
@@ -246,10 +241,7 @@ fn build_container() -> Container {
d: 2.5,
ok: true,
};
- let mut payload = Payload::Note(Note {
- text: "alpha".to_string(),
- });
- payload = Payload::Metric(complex_fbs::Metric { value: 42.0 });
+ let payload = Payload::Metric(complex_fbs::Metric { value: 42.0 });
Container {
id: 9876543210,
@@ -519,6 +511,39 @@ fn build_example_message() -> ExampleMessage {
uint8_array_values_by_name: HashMap::from([("u8".to_string(),
vec![201, 202])]),
float32_array_values_by_name: HashMap::from([("f32".to_string(),
vec![1.25, 2.5])]),
int32_array_values_by_name: HashMap::from([("i32".to_string(),
vec![101, 202])]),
+ string_values_by_date: HashMap::from([(
+ NaiveDate::from_ymd_opt(2024, 5, 7).unwrap(),
+ "date-key".to_string(),
+ )]),
+ bool_values_by_name: HashMap::from([("bool".to_string(), true)]),
+ int8_values_by_name: HashMap::from([("int8".to_string(), -8)]),
+ int16_values_by_name: HashMap::from([("int16".to_string(), -16)]),
+ fixed_i32_values_by_name: HashMap::from([("fixed-i32".to_string(),
-32)]),
+ varint_i32_values_by_name: HashMap::from([("varint-i32".to_string(),
32)]),
+ fixed_i64_values_by_name: HashMap::from([("fixed-i64".to_string(),
-64)]),
+ varint_i64_values_by_name: HashMap::from([("varint-i64".to_string(),
64)]),
+ tagged_i64_values_by_name: HashMap::from([("tagged-i64".to_string(),
65)]),
+ uint8_values_by_name: HashMap::from([("uint8".to_string(), 208)]),
+ uint16_values_by_name: HashMap::from([("uint16".to_string(), 60001)]),
+ fixed_u32_values_by_name: HashMap::from([("fixed-u32".to_string(),
1234567892)]),
+ varint_u32_values_by_name: HashMap::from([("varint-u32".to_string(),
1234567893)]),
+ fixed_u64_values_by_name: HashMap::from([("fixed-u64".to_string(),
9876543213)]),
+ varint_u64_values_by_name: HashMap::from([("varint-u64".to_string(),
9876543214)]),
+ tagged_u64_values_by_name: HashMap::from([("tagged-u64".to_string(),
9876543215)]),
+ float32_values_by_name: HashMap::from([("float32".to_string(), 3.25)]),
+ float64_values_by_name: HashMap::from([("float64".to_string(), 6.5)]),
+ timestamp_values_by_name: HashMap::from([(
+ "timestamp".to_string(),
+ NaiveDate::from_ymd_opt(2024, 6, 7)
+ .unwrap()
+ .and_hms_opt(8, 9, 10)
+ .unwrap(),
+ )]),
+ duration_values_by_name: HashMap::from([(
+ "duration".to_string(),
+ chrono::Duration::seconds(10),
+ )]),
+ enum_values_by_name: HashMap::from([("enum".to_string(),
ExampleState::Failed)]),
}
}
diff --git
a/integration_tests/idl_tests/swift/idl_package/Tests/IdlRoundTripTests/IdlRoundTripTests.swift
b/integration_tests/idl_tests/swift/idl_package/Tests/IdlRoundTripTests/IdlRoundTripTests.swift
index 4c1a73840..7e80b7aad 100644
---
a/integration_tests/idl_tests/swift/idl_package/Tests/IdlRoundTripTests/IdlRoundTripTests.swift
+++
b/integration_tests/idl_tests/swift/idl_package/Tests/IdlRoundTripTests/IdlRoundTripTests.swift
@@ -562,7 +562,28 @@ final class IdlRoundTripTests: XCTestCase {
unionValuesByName: ["union": .code(42)],
uint8ArrayValuesByName: ["u8": [201, 202]],
float32ArrayValuesByName: ["f32": [1.25, 2.5]],
- int32ArrayValuesByName: ["i32": [101, 202]]
+ int32ArrayValuesByName: ["i32": [101, 202]],
+ stringValuesByDate: [try! LocalDate(year: 2024, month: 5, day: 7):
"date-key"],
+ boolValuesByName: ["bool": true],
+ int8ValuesByName: ["int8": -8],
+ int16ValuesByName: ["int16": -16],
+ fixedI32ValuesByName: ["fixed-i32": -32],
+ varintI32ValuesByName: ["varint-i32": 32],
+ fixedI64ValuesByName: ["fixed-i64": -64],
+ varintI64ValuesByName: ["varint-i64": 64],
+ taggedI64ValuesByName: ["tagged-i64": 65],
+ uint8ValuesByName: ["uint8": 208],
+ uint16ValuesByName: ["uint16": 60001],
+ fixedU32ValuesByName: ["fixed-u32": 1234567892],
+ varintU32ValuesByName: ["varint-u32": 1234567893],
+ fixedU64ValuesByName: ["fixed-u64": 9876543213],
+ varintU64ValuesByName: ["varint-u64": 9876543214],
+ taggedU64ValuesByName: ["tagged-u64": 9876543215],
+ float32ValuesByName: ["float32": 3.25],
+ float64ValuesByName: ["float64": 6.5],
+ timestampValuesByName: ["timestamp": Date(timeIntervalSince1970:
1717747750)],
+ durationValuesByName: ["duration": .seconds(10)],
+ enumValuesByName: ["enum": .failed]
)
}
@@ -618,6 +639,27 @@ final class IdlRoundTripTests: XCTestCase {
XCTAssertEqual(actual.uint8ArrayValuesByName,
expected.uint8ArrayValuesByName)
XCTAssertEqual(actual.float32ArrayValuesByName,
expected.float32ArrayValuesByName)
XCTAssertEqual(actual.int32ArrayValuesByName,
expected.int32ArrayValuesByName)
+ XCTAssertEqual(actual.stringValuesByDate, expected.stringValuesByDate)
+ XCTAssertEqual(actual.boolValuesByName, expected.boolValuesByName)
+ XCTAssertEqual(actual.int8ValuesByName, expected.int8ValuesByName)
+ XCTAssertEqual(actual.int16ValuesByName, expected.int16ValuesByName)
+ XCTAssertEqual(actual.fixedI32ValuesByName,
expected.fixedI32ValuesByName)
+ XCTAssertEqual(actual.varintI32ValuesByName,
expected.varintI32ValuesByName)
+ XCTAssertEqual(actual.fixedI64ValuesByName,
expected.fixedI64ValuesByName)
+ XCTAssertEqual(actual.varintI64ValuesByName,
expected.varintI64ValuesByName)
+ XCTAssertEqual(actual.taggedI64ValuesByName,
expected.taggedI64ValuesByName)
+ XCTAssertEqual(actual.uint8ValuesByName, expected.uint8ValuesByName)
+ XCTAssertEqual(actual.uint16ValuesByName, expected.uint16ValuesByName)
+ XCTAssertEqual(actual.fixedU32ValuesByName,
expected.fixedU32ValuesByName)
+ XCTAssertEqual(actual.varintU32ValuesByName,
expected.varintU32ValuesByName)
+ XCTAssertEqual(actual.fixedU64ValuesByName,
expected.fixedU64ValuesByName)
+ XCTAssertEqual(actual.varintU64ValuesByName,
expected.varintU64ValuesByName)
+ XCTAssertEqual(actual.taggedU64ValuesByName,
expected.taggedU64ValuesByName)
+ XCTAssertEqual(actual.float32ValuesByName,
expected.float32ValuesByName)
+ XCTAssertEqual(actual.float64ValuesByName,
expected.float64ValuesByName)
+ XCTAssertEqual(actual.timestampValuesByName,
expected.timestampValuesByName)
+ XCTAssertEqual(actual.durationValuesByName,
expected.durationValuesByName)
+ XCTAssertEqual(actual.enumValuesByName, expected.enumValuesByName)
}
private func buildOptionalHolder() -> OptionalTypes.OptionalHolder {
diff --git
a/kotlin/src/test/kotlin/org/apache/fory/serializer/kotlin/TypeUseAnnotationTest.kt
b/kotlin/src/test/kotlin/org/apache/fory/serializer/kotlin/TypeUseAnnotationTest.kt
new file mode 100644
index 000000000..f6c68565b
--- /dev/null
+++
b/kotlin/src/test/kotlin/org/apache/fory/serializer/kotlin/TypeUseAnnotationTest.kt
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package org.apache.fory.serializer.kotlin
+
+import org.apache.fory.annotation.Int32Type
+import org.apache.fory.annotation.UInt32Type
+import org.apache.fory.annotation.UInt64Type
+import org.apache.fory.config.Int32Encoding
+import org.testng.Assert
+import org.testng.annotations.Test
+
+class TypeUseAnnotationTest {
+ private class TypeUseCarrier(
+ val fixedId: @Int32Type(encoding = Int32Encoding.FIXED) Int = 1,
+ val unsignedId: @UInt32Type Int = 2,
+ val unsignedValues: List<@UInt64Type Long> = listOf(3L),
+ val unsignedArrayValues: Array<@UInt32Type Int> = arrayOf(4),
+ )
+
+ @Test
+ fun testJavaScalarAnnotationsCompileAtKotlinTypeUseSites() {
+ val carrier = TypeUseCarrier()
+ Assert.assertEquals(carrier.fixedId, 1)
+ Assert.assertEquals(carrier.unsignedId, 2)
+ Assert.assertEquals(carrier.unsignedValues, listOf(3L))
+ Assert.assertEquals(carrier.unsignedArrayValues.toList(), listOf(4))
+ }
+}
diff --git a/rust/fory/src/lib.rs b/rust/fory/src/lib.rs
index ed66e6f86..c96e46baf 100644
--- a/rust/fory/src/lib.rs
+++ b/rust/fory/src/lib.rs
@@ -806,7 +806,7 @@
//!
//! - External types from other crates that you can't modify
//! - Types with special serialization requirements
-//! - Legacy data format compatibility
+//! - Existing external binary format interoperability
//! - Performance-critical custom encoding
//! - Complex types that require special handling
//!
diff --git
a/scala/src/test/scala/org/apache/fory/serializer/scala/TypeUseAnnotationTest.scala
b/scala/src/test/scala/org/apache/fory/serializer/scala/TypeUseAnnotationTest.scala
new file mode 100644
index 000000000..4032eaee1
--- /dev/null
+++
b/scala/src/test/scala/org/apache/fory/serializer/scala/TypeUseAnnotationTest.scala
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+package org.apache.fory.serializer.scala
+
+import java.util.Arrays
+import org.apache.fory.annotation.{Int32Type, UInt32Type, UInt64Type}
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.wordspec.AnyWordSpec
+
+final class ScalaTypeUseCarrier {
+ val fixedId: Int @Int32Type = 1
+ val unsignedId: Int @UInt32Type = 2
+ val unsignedValues: java.util.List[Long @UInt64Type] = Arrays.asList(3L)
+}
+
+class TypeUseAnnotationTest extends AnyWordSpec with Matchers {
+ "Java scalar annotations" should {
+ "compile at Scala type positions" in {
+ val carrier = new ScalaTypeUseCarrier
+ carrier.fixedId shouldBe 1
+ carrier.unsignedId shouldBe 2
+ carrier.unsignedValues shouldEqual Arrays.asList(3L)
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]