| // 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. |
| |
| using System.Buffers; |
| using System.Text; |
| using Apache.Fory; |
| using ForyRuntime = Apache.Fory.Fory; |
| |
| namespace Apache.Fory.XlangPeer; |
| |
| internal static class Program |
| { |
| private const string DataFileEnv = "DATA_FILE"; |
| |
| private static readonly string[] StringSamples = |
| [ |
| "ab", |
| "Rust123", |
| "Çüéâäàåçêëèïî", |
| "こんにちは", |
| "Привет", |
| "𝄞🎵🎶", |
| "Hello, 世界", |
| ]; |
| |
| private static readonly int[] VarInt32Values = |
| [ |
| int.MinValue, |
| int.MinValue + 1, |
| -1_000_000, |
| -1000, |
| -128, |
| -1, |
| 0, |
| 1, |
| 127, |
| 128, |
| 16_383, |
| 16_384, |
| 2_097_151, |
| 2_097_152, |
| 268_435_455, |
| 268_435_456, |
| int.MaxValue - 1, |
| int.MaxValue, |
| ]; |
| |
| private static readonly uint[] VarUInt32Values = |
| [ |
| 0, |
| 1, |
| 127, |
| 128, |
| 16_383, |
| 16_384, |
| 2_097_151, |
| 2_097_152, |
| 268_435_455, |
| 268_435_456, |
| 2_147_483_646, |
| 2_147_483_647, |
| ]; |
| |
| private static readonly ulong[] VarUInt64Values = |
| [ |
| 0UL, |
| 1UL, |
| 127UL, |
| 128UL, |
| 16_383UL, |
| 16_384UL, |
| 2_097_151UL, |
| 2_097_152UL, |
| 268_435_455UL, |
| 268_435_456UL, |
| 34_359_738_367UL, |
| 34_359_738_368UL, |
| 4_398_046_511_103UL, |
| 4_398_046_511_104UL, |
| 562_949_953_421_311UL, |
| 562_949_953_421_312UL, |
| 72_057_594_037_927_935UL, |
| 72_057_594_037_927_936UL, |
| long.MaxValue, |
| ]; |
| |
| private static readonly long[] VarInt64Values = |
| [ |
| long.MinValue, |
| long.MinValue + 1, |
| -1_000_000_000_000L, |
| -1_000_000L, |
| -1000L, |
| -128L, |
| -1L, |
| 0L, |
| 1L, |
| 127L, |
| 1000L, |
| 1_000_000L, |
| 1_000_000_000_000L, |
| long.MaxValue - 1, |
| long.MaxValue, |
| ]; |
| |
| private static int Main(string[] args) |
| { |
| try |
| { |
| string caseName = ParseCaseName(args); |
| string dataFile = RequireDataFile(); |
| byte[] input = File.ReadAllBytes(dataFile); |
| byte[] output = ExecuteCase(caseName, input); |
| File.WriteAllBytes(dataFile, output); |
| Console.WriteLine($"case {caseName} passed"); |
| return 0; |
| } |
| catch (Exception ex) |
| { |
| Console.Error.WriteLine($"xlang peer failed: {ex}"); |
| return 1; |
| } |
| } |
| |
| private static string ParseCaseName(string[] args) |
| { |
| for (int i = 0; i < args.Length; i++) |
| { |
| if (args[i] == "--case" && i + 1 < args.Length) |
| { |
| return args[i + 1]; |
| } |
| } |
| |
| if (args.Length == 1) |
| { |
| return args[0]; |
| } |
| |
| throw new InvalidOperationException("Usage: Fory.XlangPeer --case <case_name>"); |
| } |
| |
| private static string RequireDataFile() |
| { |
| string? dataFile = Environment.GetEnvironmentVariable(DataFileEnv); |
| if (string.IsNullOrWhiteSpace(dataFile)) |
| { |
| throw new InvalidOperationException($"{DataFileEnv} environment variable is required"); |
| } |
| |
| return dataFile; |
| } |
| |
| private static byte[] ExecuteCase(string caseName, byte[] input) |
| { |
| return caseName switch |
| { |
| "test_buffer" => CaseBuffer(input), |
| "test_buffer_var" => CaseBufferVar(input), |
| "test_murmurhash3" => CaseMurmurHash3(input), |
| "test_string_serializer" => CaseStringSerializer(input), |
| "test_cross_language_serializer" => CaseCrossLanguageSerializer(input), |
| "test_simple_struct" => CaseSimpleStruct(input), |
| "test_named_simple_struct" => CaseNamedSimpleStruct(input), |
| "test_struct_evolving_override" => CaseStructEvolvingOverride(input), |
| "test_list" => CaseList(input), |
| "test_map" => CaseMap(input), |
| "test_integer" => CaseInteger(input), |
| "test_item" => CaseItem(input), |
| "test_color" => CaseColor(input), |
| "test_union_xlang" => CaseUnionXlang(input), |
| "test_struct_with_list" => CaseStructWithList(input), |
| "test_struct_with_map" => CaseStructWithMap(input), |
| "test_skip_id_custom" => CaseSkipIdCustom(input), |
| "test_skip_name_custom" => CaseSkipNameCustom(input), |
| "test_consistent_named" => CaseConsistentNamed(input), |
| "test_struct_version_check" => CaseStructVersionCheck(input), |
| "test_polymorphic_list" => CasePolymorphicList(input), |
| "test_polymorphic_map" => CasePolymorphicMap(input), |
| "test_one_field_struct_compatible" => CaseOneFieldStructCompatible(input), |
| "test_one_field_struct_schema" => CaseOneFieldStructSchema(input), |
| "test_one_string_field_schema" => CaseOneStringFieldSchema(input), |
| "test_one_string_field_compatible" => CaseOneStringFieldCompatible(input), |
| "test_two_string_field_compatible" => CaseTwoStringFieldCompatible(input), |
| "test_schema_evolution_compatible" => CaseSchemaEvolutionCompatible(input), |
| "test_schema_evolution_compatible_reverse" => CaseSchemaEvolutionCompatibleReverse(input), |
| "test_one_enum_field_schema" => CaseOneEnumFieldSchema(input), |
| "test_one_enum_field_compatible" => CaseOneEnumFieldCompatible(input), |
| "test_two_enum_field_compatible" => CaseTwoEnumFieldCompatible(input), |
| "test_enum_schema_evolution_compatible" => CaseEnumSchemaEvolutionCompatible(input), |
| "test_enum_schema_evolution_compatible_reverse" => CaseEnumSchemaEvolutionCompatibleReverse(input), |
| "test_nullable_field_schema_consistent_not_null" => CaseNullableFieldSchemaConsistentNotNull(input), |
| "test_nullable_field_schema_consistent_null" => CaseNullableFieldSchemaConsistentNull(input), |
| "test_nullable_field_compatible_not_null" => CaseNullableFieldCompatibleNotNull(input), |
| "test_nullable_field_compatible_null" => CaseNullableFieldCompatibleNull(input), |
| "test_ref_schema_consistent" => CaseRefSchemaConsistent(input), |
| "test_ref_compatible" => CaseRefCompatible(input), |
| "test_collection_element_ref_override" => CaseCollectionElementRefOverride(input), |
| "test_circular_ref_schema_consistent" => CaseCircularRefSchemaConsistent(input), |
| "test_circular_ref_compatible" => CaseCircularRefCompatible(input), |
| "test_unsigned_schema_consistent_simple" => CaseUnsignedSchemaConsistentSimple(input), |
| "test_unsigned_schema_consistent" => CaseUnsignedSchemaConsistent(input), |
| "test_unsigned_schema_compatible" => CaseUnsignedSchemaCompatible(input), |
| _ => throw new InvalidOperationException($"unknown test case {caseName}"), |
| }; |
| } |
| |
| private static byte[] CaseBuffer(byte[] input) |
| { |
| ByteReader reader = new(input); |
| Ensure(reader.ReadUInt8() == 1, "bool mismatch"); |
| Ensure(reader.ReadInt8() == sbyte.MaxValue, "byte mismatch"); |
| Ensure(reader.ReadInt16() == short.MaxValue, "int16 mismatch"); |
| Ensure(reader.ReadInt32() == int.MaxValue, "int32 mismatch"); |
| Ensure(reader.ReadInt64() == long.MaxValue, "int64 mismatch"); |
| Ensure(Math.Abs(reader.ReadFloat32() - (-1.1f)) < 0.0001f, "float32 mismatch"); |
| Ensure(Math.Abs(reader.ReadFloat64() - (-1.1d)) < 0.000001d, "float64 mismatch"); |
| Ensure(reader.ReadVarUInt32() == 100, "varuint32 mismatch"); |
| int size = reader.ReadInt32(); |
| byte[] payload = reader.ReadBytes(size); |
| Ensure(payload.SequenceEqual("ab"u8.ToArray()), "binary mismatch"); |
| Ensure(reader.Remaining == 0, "buffer should be fully consumed"); |
| |
| ByteWriter writer = new(); |
| writer.WriteUInt8(1); |
| writer.WriteInt8(sbyte.MaxValue); |
| writer.WriteInt16(short.MaxValue); |
| writer.WriteInt32(int.MaxValue); |
| writer.WriteInt64(long.MaxValue); |
| writer.WriteFloat32(-1.1f); |
| writer.WriteFloat64(-1.1d); |
| writer.WriteVarUInt32(100); |
| writer.WriteInt32(2); |
| writer.WriteBytes("ab"u8); |
| return writer.ToArray(); |
| } |
| |
| private static byte[] CaseBufferVar(byte[] input) |
| { |
| ByteReader reader = new(input); |
| foreach (int expected in VarInt32Values) |
| { |
| Ensure(reader.ReadVarInt32() == expected, $"varint32 mismatch {expected}"); |
| } |
| |
| foreach (uint expected in VarUInt32Values) |
| { |
| Ensure(reader.ReadVarUInt32() == expected, $"varuint32 mismatch {expected}"); |
| } |
| |
| foreach (ulong expected in VarUInt64Values) |
| { |
| Ensure(reader.ReadVarUInt64() == expected, $"varuint64 mismatch {expected}"); |
| } |
| |
| foreach (long expected in VarInt64Values) |
| { |
| Ensure(reader.ReadVarInt64() == expected, $"varint64 mismatch {expected}"); |
| } |
| |
| Ensure(reader.Remaining == 0, "buffer var should be fully consumed"); |
| |
| ByteWriter writer = new(); |
| foreach (int value in VarInt32Values) |
| { |
| writer.WriteVarInt32(value); |
| } |
| |
| foreach (uint value in VarUInt32Values) |
| { |
| writer.WriteVarUInt32(value); |
| } |
| |
| foreach (ulong value in VarUInt64Values) |
| { |
| writer.WriteVarUInt64(value); |
| } |
| |
| foreach (long value in VarInt64Values) |
| { |
| writer.WriteVarInt64(value); |
| } |
| |
| return writer.ToArray(); |
| } |
| |
| private static byte[] CaseMurmurHash3(byte[] input) |
| { |
| if (input.Length == 32) |
| { |
| (ulong h1a, ulong h1b) = MurmurHash3.X64_128([1, 2, 8], 47); |
| (ulong h2a, ulong h2b) = MurmurHash3.X64_128(Encoding.UTF8.GetBytes("01234567890123456789"), 47); |
| ByteWriter writer = new(); |
| writer.WriteInt64(unchecked((long)h1a)); |
| writer.WriteInt64(unchecked((long)h1b)); |
| writer.WriteInt64(unchecked((long)h2a)); |
| writer.WriteInt64(unchecked((long)h2b)); |
| return writer.ToArray(); |
| } |
| |
| if (input.Length == 16) |
| { |
| ByteReader reader = new(input); |
| long h1 = reader.ReadInt64(); |
| long h2 = reader.ReadInt64(); |
| (ulong expected1, ulong expected2) = MurmurHash3.X64_128([1, 2, 8], 47); |
| Ensure(h1 == unchecked((long)expected1), "murmur hash h1 mismatch"); |
| Ensure(h2 == unchecked((long)expected2), "murmur hash h2 mismatch"); |
| return []; |
| } |
| |
| throw new InvalidOperationException($"unexpected murmur hash input length {input.Length}"); |
| } |
| |
| private static byte[] CaseStringSerializer(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| ReadOnlySequence<byte> sequence = new(input); |
| foreach (string expected in StringSamples) |
| { |
| string value = fory.Deserialize<string>(ref sequence); |
| Ensure(value == expected, "string value mismatch"); |
| } |
| |
| EnsureConsumed(sequence, nameof(CaseStringSerializer)); |
| List<byte> output = []; |
| foreach (string sample in StringSamples) |
| { |
| Append(output, fory.Serialize<object?>(sample)); |
| } |
| |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseCrossLanguageSerializer(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Color>(101); |
| ReadOnlySequence<byte> sequence = new(input); |
| |
| bool b1 = fory.Deserialize<bool>(ref sequence); |
| bool b2 = fory.Deserialize<bool>(ref sequence); |
| int i32 = fory.Deserialize<int>(ref sequence); |
| sbyte i8a = fory.Deserialize<sbyte>(ref sequence); |
| sbyte i8b = fory.Deserialize<sbyte>(ref sequence); |
| short i16a = fory.Deserialize<short>(ref sequence); |
| short i16b = fory.Deserialize<short>(ref sequence); |
| int i32a = fory.Deserialize<int>(ref sequence); |
| int i32b = fory.Deserialize<int>(ref sequence); |
| long i64a = fory.Deserialize<long>(ref sequence); |
| long i64b = fory.Deserialize<long>(ref sequence); |
| float f32 = fory.Deserialize<float>(ref sequence); |
| double f64 = fory.Deserialize<double>(ref sequence); |
| string str = fory.Deserialize<string>(ref sequence); |
| DateOnly day = fory.Deserialize<DateOnly>(ref sequence); |
| DateTimeOffset timestamp = fory.Deserialize<DateTimeOffset>(ref sequence); |
| bool[] bools = fory.Deserialize<bool[]>(ref sequence); |
| byte[] bytes = fory.Deserialize<byte[]>(ref sequence); |
| short[] int16s = fory.Deserialize<short[]>(ref sequence); |
| int[] int32s = fory.Deserialize<int[]>(ref sequence); |
| long[] int64s = fory.Deserialize<long[]>(ref sequence); |
| float[] floats = fory.Deserialize<float[]>(ref sequence); |
| double[] doubles = fory.Deserialize<double[]>(ref sequence); |
| List<string> list = fory.Deserialize<List<string>>(ref sequence); |
| HashSet<string> set = fory.Deserialize<HashSet<string>>(ref sequence); |
| Dictionary<string, string> map = fory.Deserialize<Dictionary<string, string>>(ref sequence); |
| Color color = fory.Deserialize<Color>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseCrossLanguageSerializer)); |
| |
| Ensure(b1, "bool1 mismatch"); |
| Ensure(!b2, "bool2 mismatch"); |
| Ensure(i32 == -1, "int mismatch"); |
| Ensure(str == "str", "string mismatch"); |
| Ensure(day == new DateOnly(2021, 11, 23), "date mismatch"); |
| Ensure(timestamp.ToUnixTimeSeconds() == 100, "timestamp mismatch"); |
| Ensure(color == Color.White, "color mismatch"); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(b1)); |
| Append(output, fory.Serialize<object?>(b2)); |
| Append(output, fory.Serialize<object?>(i32)); |
| Append(output, fory.Serialize<object?>(i8a)); |
| Append(output, fory.Serialize<object?>(i8b)); |
| Append(output, fory.Serialize<object?>(i16a)); |
| Append(output, fory.Serialize<object?>(i16b)); |
| Append(output, fory.Serialize<object?>(i32a)); |
| Append(output, fory.Serialize<object?>(i32b)); |
| Append(output, fory.Serialize<object?>(i64a)); |
| Append(output, fory.Serialize<object?>(i64b)); |
| Append(output, fory.Serialize<object?>(f32)); |
| Append(output, fory.Serialize<object?>(f64)); |
| Append(output, fory.Serialize<object?>(str)); |
| Append(output, fory.Serialize<object?>(day)); |
| Append(output, fory.Serialize<object?>(timestamp)); |
| Append(output, fory.Serialize<object?>(bools)); |
| Append(output, fory.Serialize<object?>(bytes)); |
| Append(output, fory.Serialize<object?>(int16s)); |
| Append(output, fory.Serialize<object?>(int32s)); |
| Append(output, fory.Serialize<object?>(int64s)); |
| Append(output, fory.Serialize<object?>(floats)); |
| Append(output, fory.Serialize<object?>(doubles)); |
| Append(output, fory.Serialize<object?>(list)); |
| Append(output, fory.Serialize<object?>(set)); |
| Append(output, fory.Serialize<object?>(map)); |
| Append(output, fory.Serialize<object?>(color)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseSimpleStruct(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| RegisterSimpleById(fory); |
| return RoundTripSingle<SimpleStruct>(input, fory); |
| } |
| |
| private static byte[] CaseNamedSimpleStruct(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| RegisterSimpleByName(fory); |
| return RoundTripSingle<SimpleStruct>(input, fory); |
| } |
| |
| private static byte[] CaseStructEvolvingOverride(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<EvolvingOverrideStruct>("test", "evolving_yes"); |
| fory.Register<FixedOverrideStruct>("test", "evolving_off"); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| EvolvingOverrideStruct evolving = fory.Deserialize<EvolvingOverrideStruct>(ref sequence); |
| FixedOverrideStruct fixedValue = fory.Deserialize<FixedOverrideStruct>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseStructEvolvingOverride)); |
| Ensure(evolving.F1 == "payload", "evolving override struct mismatch"); |
| Ensure(fixedValue.F1 == "payload", "fixed override struct mismatch"); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(evolving)); |
| Append(output, fory.Serialize<object?>(fixedValue)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseList(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Item>(102); |
| ReadOnlySequence<byte> sequence = new(input); |
| List<string?> strList = fory.Deserialize<List<string?>>(ref sequence); |
| List<string?> strList2 = fory.Deserialize<List<string?>>(ref sequence); |
| List<Item?> itemList = fory.Deserialize<List<Item?>>(ref sequence); |
| List<Item?> itemList2 = fory.Deserialize<List<Item?>>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseList)); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(strList)); |
| Append(output, fory.Serialize<object?>(strList2)); |
| Append(output, fory.Serialize<object?>(itemList)); |
| Append(output, fory.Serialize<object?>(itemList2)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseMap(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Item>(102); |
| ReadOnlySequence<byte> sequence = new(input); |
| NullableKeyDictionary<string, string?> strMap = fory.Deserialize<NullableKeyDictionary<string, string?>>(ref sequence); |
| NullableKeyDictionary<string, Item?> itemMap = fory.Deserialize<NullableKeyDictionary<string, Item?>>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseMap)); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(strMap)); |
| Append(output, fory.Serialize<object?>(itemMap)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseInteger(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Item1>(101); |
| ReadOnlySequence<byte> sequence = new(input); |
| Item1 obj = fory.Deserialize<Item1>(ref sequence); |
| int f1 = fory.Deserialize<int>(ref sequence); |
| int f2 = fory.Deserialize<int>(ref sequence); |
| int f3 = fory.Deserialize<int>(ref sequence); |
| int f4 = fory.Deserialize<int>(ref sequence); |
| int f5 = fory.Deserialize<int>(ref sequence); |
| int f6 = fory.Deserialize<int>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseInteger)); |
| |
| Ensure(obj.F1 == 1 && obj.F2 == 2, "item1 primitive fields mismatch"); |
| Ensure(obj.F3 == 3 && obj.F4 == 4 && obj.F5 == 0 && obj.F6 == 0, "item1 boxed fields mismatch"); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(obj)); |
| Append(output, fory.Serialize<object?>(f1)); |
| Append(output, fory.Serialize<object?>(f2)); |
| Append(output, fory.Serialize<object?>(f3)); |
| Append(output, fory.Serialize<object?>(f4)); |
| Append(output, fory.Serialize<object?>(f5)); |
| Append(output, fory.Serialize<object?>(f6)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseItem(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Item>(102); |
| ReadOnlySequence<byte> sequence = new(input); |
| Item i1 = fory.Deserialize<Item>(ref sequence); |
| Item i2 = fory.Deserialize<Item>(ref sequence); |
| Item i3 = fory.Deserialize<Item>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseItem)); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(i1)); |
| Append(output, fory.Serialize<object?>(i2)); |
| Append(output, fory.Serialize<object?>(i3)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseColor(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Color>(101); |
| ReadOnlySequence<byte> sequence = new(input); |
| Color c1 = fory.Deserialize<Color>(ref sequence); |
| Color c2 = fory.Deserialize<Color>(ref sequence); |
| Color c3 = fory.Deserialize<Color>(ref sequence); |
| Color c4 = fory.Deserialize<Color>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseColor)); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(c1)); |
| Append(output, fory.Serialize<object?>(c2)); |
| Append(output, fory.Serialize<object?>(c3)); |
| Append(output, fory.Serialize<object?>(c4)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseStructWithList(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<StructWithList>(201); |
| ReadOnlySequence<byte> sequence = new(input); |
| StructWithList s1 = fory.Deserialize<StructWithList>(ref sequence); |
| StructWithList s2 = fory.Deserialize<StructWithList>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseStructWithList)); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(s1)); |
| Append(output, fory.Serialize<object?>(s2)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseStructWithMap(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<StructWithMap>(202); |
| ReadOnlySequence<byte> sequence = new(input); |
| StructWithMap s1 = fory.Deserialize<StructWithMap>(ref sequence); |
| StructWithMap s2 = fory.Deserialize<StructWithMap>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseStructWithMap)); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(s1)); |
| Append(output, fory.Serialize<object?>(s2)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseUnionXlang(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<StructWithUnion2>(301); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| StructWithUnion2 first = fory.Deserialize<StructWithUnion2>(ref sequence); |
| StructWithUnion2 second = fory.Deserialize<StructWithUnion2>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseUnionXlang)); |
| |
| Ensure(first.Union.Index == 0, "union case index mismatch for first value"); |
| Ensure(first.Union.Value is string firstValue && firstValue == "hello", "union case value mismatch for first value"); |
| Ensure(second.Union.Index == 1, "union case index mismatch for second value"); |
| Ensure(second.Union.Value is long secondValue && secondValue == 42L, "union case value mismatch for second value"); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(first)); |
| Append(output, fory.Serialize<object?>(second)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseSkipIdCustom(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Color>(101); |
| fory.Register<MyStruct>(102); |
| fory.Register<MyExt, MyExtSerializer>(103); |
| fory.Register<MyWrapper>(104); |
| return RoundTripSingle<MyWrapper>(input, fory); |
| } |
| |
| private static byte[] CaseSkipNameCustom(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Color>("color"); |
| fory.Register<MyStruct>("my_struct"); |
| fory.Register<MyExt, MyExtSerializer>(string.Empty, "my_ext"); |
| fory.Register<MyWrapper>("my_wrapper"); |
| return RoundTripSingle<MyWrapper>(input, fory); |
| } |
| |
| private static byte[] CaseConsistentNamed(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false, checkStructVersion: true); |
| fory.Register<Color>("color"); |
| fory.Register<MyStruct>("my_struct"); |
| fory.Register<MyExt, MyExtSerializer>(string.Empty, "my_ext"); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| List<byte> output = []; |
| for (int i = 0; i < 3; i++) |
| { |
| Color color = fory.Deserialize<Color>(ref sequence); |
| Append(output, fory.Serialize<object?>(color)); |
| } |
| |
| for (int i = 0; i < 3; i++) |
| { |
| MyStruct myStruct = fory.Deserialize<MyStruct>(ref sequence); |
| Append(output, fory.Serialize<object?>(myStruct)); |
| } |
| |
| for (int i = 0; i < 3; i++) |
| { |
| MyExt myExt = fory.Deserialize<MyExt>(ref sequence); |
| Append(output, fory.Serialize<object?>(myExt)); |
| } |
| |
| EnsureConsumed(sequence, nameof(CaseConsistentNamed)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseStructVersionCheck(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false, checkStructVersion: true); |
| fory.Register<VersionCheckStruct>(201); |
| return RoundTripSingle<VersionCheckStruct>(input, fory); |
| } |
| |
| private static byte[] CasePolymorphicList(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Dog>(302); |
| fory.Register<Cat>(303); |
| fory.Register<AnimalListHolder>(304); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| List<object?> animals = fory.Deserialize<List<object?>>(ref sequence); |
| AnimalListHolder holder = fory.Deserialize<AnimalListHolder>(ref sequence); |
| EnsureConsumed(sequence, nameof(CasePolymorphicList)); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(animals)); |
| Append(output, fory.Serialize<object?>(holder)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CasePolymorphicMap(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<Dog>(302); |
| fory.Register<Cat>(303); |
| fory.Register<AnimalMapHolder>(305); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| Dictionary<string, object?> map = fory.Deserialize<Dictionary<string, object?>>(ref sequence); |
| AnimalMapHolder holder = fory.Deserialize<AnimalMapHolder>(ref sequence); |
| EnsureConsumed(sequence, nameof(CasePolymorphicMap)); |
| |
| List<byte> output = []; |
| Append(output, fory.Serialize<object?>(map)); |
| Append(output, fory.Serialize<object?>(holder)); |
| return output.ToArray(); |
| } |
| |
| private static byte[] CaseOneFieldStructCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<OneFieldStruct>(200); |
| return RoundTripSingle<OneFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseOneFieldStructSchema(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false); |
| fory.Register<OneFieldStruct>(200); |
| return RoundTripSingle<OneFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseOneStringFieldSchema(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false); |
| fory.Register<OneStringFieldStruct>(200); |
| return RoundTripSingle<OneStringFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseOneStringFieldCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<OneStringFieldStruct>(200); |
| return RoundTripSingle<OneStringFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseTwoStringFieldCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<TwoStringFieldStruct>(201); |
| return RoundTripSingle<TwoStringFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseSchemaEvolutionCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<TwoStringFieldStruct>(200); |
| return RoundTripSingle<TwoStringFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseSchemaEvolutionCompatibleReverse(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<OneStringFieldStruct>(200); |
| return RoundTripSingle<OneStringFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseOneEnumFieldSchema(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false); |
| fory.Register<TestEnum>(210); |
| fory.Register<OneEnumFieldStruct>(211); |
| return RoundTripSingle<OneEnumFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseOneEnumFieldCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<TestEnum>(210); |
| fory.Register<OneEnumFieldStruct>(211); |
| return RoundTripSingle<OneEnumFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseTwoEnumFieldCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<TestEnum>(210); |
| fory.Register<TwoEnumFieldStruct>(212); |
| return RoundTripSingle<TwoEnumFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseEnumSchemaEvolutionCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<TestEnum>(210); |
| fory.Register<TwoEnumFieldStruct>(211); |
| return RoundTripSingle<TwoEnumFieldStruct>(input, fory); |
| } |
| |
| private static byte[] CaseEnumSchemaEvolutionCompatibleReverse(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<TestEnum>(210); |
| fory.Register<TwoEnumFieldStruct>(211); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| TwoEnumFieldStruct value = fory.Deserialize<TwoEnumFieldStruct>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseEnumSchemaEvolutionCompatibleReverse)); |
| Ensure(value.F1 == TestEnum.ValueC, "enum schema evolution reverse F1 mismatch"); |
| Ensure(value.F2 == TestEnum.ValueA, "enum schema evolution reverse F2 default mismatch"); |
| return fory.Serialize<object?>(value); |
| } |
| |
| private static byte[] CaseNullableFieldSchemaConsistentNotNull(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false); |
| fory.Register<NullableComprehensiveSchemaConsistent>(401); |
| return RoundTripSingle<NullableComprehensiveSchemaConsistent>(input, fory); |
| } |
| |
| private static byte[] CaseNullableFieldSchemaConsistentNull(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false); |
| fory.Register<NullableComprehensiveSchemaConsistent>(401); |
| return RoundTripSingle<NullableComprehensiveSchemaConsistent>(input, fory); |
| } |
| |
| private static byte[] CaseNullableFieldCompatibleNotNull(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<NullableComprehensiveCompatible>(402); |
| return RoundTripSingle<NullableComprehensiveCompatible>(input, fory); |
| } |
| |
| private static byte[] CaseNullableFieldCompatibleNull(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<NullableComprehensiveCompatible>(402); |
| return RoundTripSingle<NullableComprehensiveCompatible>(input, fory); |
| } |
| |
| private static byte[] CaseRefSchemaConsistent(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false, trackRef: true); |
| fory.Register<RefInnerSchemaConsistent>(501); |
| fory.Register<RefOuterSchemaConsistent>(502); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| RefOuterSchemaConsistent outer = fory.Deserialize<RefOuterSchemaConsistent>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseRefSchemaConsistent)); |
| Ensure(ReferenceEquals(outer.Inner1, outer.Inner2), "reference tracking mismatch"); |
| return fory.Serialize<object?>(outer); |
| } |
| |
| private static byte[] CaseRefCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true, trackRef: true); |
| fory.Register<RefInnerCompatible>(503); |
| fory.Register<RefOuterCompatible>(504); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| RefOuterCompatible outer = fory.Deserialize<RefOuterCompatible>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseRefCompatible)); |
| Ensure(ReferenceEquals(outer.Inner1, outer.Inner2), "reference tracking mismatch"); |
| return fory.Serialize<object?>(outer); |
| } |
| |
| private static byte[] CaseCollectionElementRefOverride(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false, trackRef: true); |
| fory.Register<RefOverrideElement>(701); |
| fory.Register<RefOverrideContainer>(702); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| RefOverrideContainer container = fory.Deserialize<RefOverrideContainer>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseCollectionElementRefOverride)); |
| |
| if (container.ListField.Count > 0) |
| { |
| RefOverrideElement? shared = container.ListField[0]; |
| if (shared is not null) |
| { |
| if (container.ListField.Count > 1) |
| { |
| container.ListField[1] = shared; |
| } |
| |
| if (container.MapField.ContainsKey("k1")) |
| { |
| container.MapField["k1"] = shared; |
| } |
| |
| if (container.MapField.ContainsKey("k2")) |
| { |
| container.MapField["k2"] = shared; |
| } |
| } |
| } |
| |
| return fory.Serialize<object?>(container); |
| } |
| |
| private static byte[] CaseCircularRefSchemaConsistent(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false, trackRef: true); |
| fory.Register<CircularRefStruct>(601); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| CircularRefStruct value = fory.Deserialize<CircularRefStruct>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseCircularRefSchemaConsistent)); |
| Ensure(ReferenceEquals(value, value.SelfRef), "circular ref mismatch"); |
| return fory.Serialize<object?>(value); |
| } |
| |
| private static byte[] CaseCircularRefCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true, trackRef: true); |
| fory.Register<CircularRefStruct>(602); |
| |
| ReadOnlySequence<byte> sequence = new(input); |
| CircularRefStruct value = fory.Deserialize<CircularRefStruct>(ref sequence); |
| EnsureConsumed(sequence, nameof(CaseCircularRefCompatible)); |
| Ensure(ReferenceEquals(value, value.SelfRef), "circular ref mismatch"); |
| return fory.Serialize<object?>(value); |
| } |
| |
| private static byte[] CaseUnsignedSchemaConsistentSimple(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false); |
| fory.Register<UnsignedSchemaConsistentSimple>(1); |
| return RoundTripSingle<UnsignedSchemaConsistentSimple>(input, fory); |
| } |
| |
| private static byte[] CaseUnsignedSchemaConsistent(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: false); |
| fory.Register<UnsignedSchemaConsistent>(501); |
| return RoundTripSingle<UnsignedSchemaConsistent>(input, fory); |
| } |
| |
| private static byte[] CaseUnsignedSchemaCompatible(byte[] input) |
| { |
| ForyRuntime fory = BuildFory(compatible: true); |
| fory.Register<UnsignedSchemaCompatible>(502); |
| return RoundTripSingle<UnsignedSchemaCompatible>(input, fory); |
| } |
| |
| private static byte[] RoundTripSingle<T>(byte[] input, ForyRuntime fory) |
| { |
| ReadOnlySequence<byte> sequence = new(input); |
| T value = fory.Deserialize<T>(ref sequence); |
| EnsureConsumed(sequence, typeof(T).Name); |
| return fory.Serialize<object?>(value); |
| } |
| |
| private static void RegisterSimpleById(ForyRuntime fory) |
| { |
| fory.Register<Color>(101); |
| fory.Register<Item>(102); |
| fory.Register<SimpleStruct>(103); |
| } |
| |
| private static void RegisterSimpleByName(ForyRuntime fory) |
| { |
| fory.Register<Color>("demo", "color"); |
| fory.Register<Item>("demo", "item"); |
| fory.Register<SimpleStruct>("demo", "simple_struct"); |
| } |
| |
| private static ForyRuntime BuildFory(bool compatible, bool trackRef = false, bool checkStructVersion = false) |
| { |
| return ForyRuntime.Builder() |
| .Compatible(compatible) |
| .TrackRef(trackRef) |
| .CheckStructVersion(checkStructVersion) |
| .Build(); |
| } |
| |
| private static void Append(List<byte> target, byte[] payload) |
| { |
| target.AddRange(payload); |
| } |
| |
| private static void EnsureConsumed(ReadOnlySequence<byte> sequence, string caseName) |
| { |
| Ensure(sequence.Length == 0, $"case {caseName} did not consume full payload"); |
| } |
| |
| private static void Ensure(bool condition, string message) |
| { |
| if (!condition) |
| { |
| throw new InvalidOperationException(message); |
| } |
| } |
| } |
| |
| [ForyObject] |
| public enum Color |
| { |
| Green, |
| Red, |
| Blue, |
| White, |
| } |
| |
| [ForyObject] |
| public sealed class Item |
| { |
| public string Name { get; set; } = string.Empty; |
| } |
| |
| [ForyObject] |
| public sealed class SimpleStruct |
| { |
| public Dictionary<int, double> F1 { get; set; } = []; |
| public int F2 { get; set; } |
| public Item F3 { get; set; } = new(); |
| public string F4 { get; set; } = string.Empty; |
| public Color F5 { get; set; } |
| public List<string> F6 { get; set; } = []; |
| public int F7 { get; set; } |
| public int F8 { get; set; } |
| public int Last { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class EvolvingOverrideStruct |
| { |
| public string F1 { get; set; } = string.Empty; |
| } |
| |
| [ForyObject(Evolving = false)] |
| public sealed class FixedOverrideStruct |
| { |
| public string F1 { get; set; } = string.Empty; |
| } |
| |
| [ForyObject] |
| public sealed class Item1 |
| { |
| public int F1 { get; set; } |
| public int F2 { get; set; } |
| public int F3 { get; set; } |
| public int F4 { get; set; } |
| public int F5 { get; set; } |
| public int F6 { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class StructWithList |
| { |
| public List<string?> Items { get; set; } = []; |
| } |
| |
| [ForyObject] |
| public sealed class StructWithMap |
| { |
| public NullableKeyDictionary<string, string?> Data { get; set; } = new(); |
| } |
| |
| [ForyObject] |
| public sealed class StructWithUnion2 |
| { |
| public Union2<string, long> Union { get; set; } = Union2<string, long>.OfT1(string.Empty); |
| } |
| |
| [ForyObject] |
| public sealed class MyStruct |
| { |
| public int Id { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class MyExt |
| { |
| public int Id { get; set; } |
| } |
| |
| public sealed class MyExtSerializer : Serializer<MyExt> |
| { |
| public override MyExt DefaultValue => null!; |
| |
| public override void WriteData(WriteContext context, in MyExt value, bool hasGenerics) |
| { |
| _ = hasGenerics; |
| context.Writer.WriteVarInt32((value ?? new MyExt()).Id); |
| } |
| |
| public override MyExt ReadData(ReadContext context) |
| { |
| return new MyExt { Id = context.Reader.ReadVarInt32() }; |
| } |
| } |
| |
| [ForyObject] |
| public sealed class MyWrapper |
| { |
| public Color Color { get; set; } |
| public MyExt MyExt { get; set; } = new(); |
| public MyStruct MyStruct { get; set; } = new(); |
| } |
| |
| [ForyObject] |
| public sealed class EmptyWrapper |
| { |
| } |
| |
| [ForyObject] |
| public sealed class VersionCheckStruct |
| { |
| public int F1 { get; set; } |
| public string? F2 { get; set; } |
| public double F3 { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class Dog |
| { |
| public int Age { get; set; } |
| public string? Name { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class Cat |
| { |
| public int Age { get; set; } |
| public int Lives { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class AnimalListHolder |
| { |
| public List<object?> Animals { get; set; } = []; |
| } |
| |
| [ForyObject] |
| public sealed class AnimalMapHolder |
| { |
| public Dictionary<string, object?> AnimalMap { get; set; } = []; |
| } |
| |
| [ForyObject] |
| public sealed class OneFieldStruct |
| { |
| public int Value { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class OneStringFieldStruct |
| { |
| public string? F1 { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class TwoStringFieldStruct |
| { |
| public string F1 { get; set; } = string.Empty; |
| public string F2 { get; set; } = string.Empty; |
| } |
| |
| [ForyObject] |
| public enum TestEnum |
| { |
| ValueA, |
| ValueB, |
| ValueC, |
| } |
| |
| [ForyObject] |
| public sealed class OneEnumFieldStruct |
| { |
| public TestEnum F1 { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class TwoEnumFieldStruct |
| { |
| public TestEnum F1 { get; set; } |
| public TestEnum F2 { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class NullableComprehensiveSchemaConsistent |
| { |
| public sbyte ByteField { get; set; } |
| public short ShortField { get; set; } |
| public int IntField { get; set; } |
| public long LongField { get; set; } |
| public float FloatField { get; set; } |
| public double DoubleField { get; set; } |
| public bool BoolField { get; set; } |
| |
| public string StringField { get; set; } = string.Empty; |
| public List<string> ListField { get; set; } = []; |
| public HashSet<string> SetField { get; set; } = []; |
| public NullableKeyDictionary<string, string> MapField { get; set; } = new(); |
| |
| public int? NullableInt { get; set; } |
| public long? NullableLong { get; set; } |
| public float? NullableFloat { get; set; } |
| public double? NullableDouble { get; set; } |
| public bool? NullableBool { get; set; } |
| public string? NullableString { get; set; } |
| public List<string>? NullableList { get; set; } |
| public HashSet<string>? NullableSet { get; set; } |
| public NullableKeyDictionary<string, string>? NullableMap { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class NullableComprehensiveCompatible |
| { |
| public sbyte ByteField { get; set; } |
| public short ShortField { get; set; } |
| public int IntField { get; set; } |
| public long LongField { get; set; } |
| public float FloatField { get; set; } |
| public double DoubleField { get; set; } |
| public bool BoolField { get; set; } |
| |
| public int BoxedInt { get; set; } |
| public long BoxedLong { get; set; } |
| public float BoxedFloat { get; set; } |
| public double BoxedDouble { get; set; } |
| public bool BoxedBool { get; set; } |
| |
| public string StringField { get; set; } = string.Empty; |
| public List<string> ListField { get; set; } = []; |
| public HashSet<string> SetField { get; set; } = []; |
| public NullableKeyDictionary<string, string> MapField { get; set; } = new(); |
| |
| public int NullableInt1 { get; set; } |
| public long NullableLong1 { get; set; } |
| public float NullableFloat1 { get; set; } |
| public double NullableDouble1 { get; set; } |
| public bool NullableBool1 { get; set; } |
| |
| public string NullableString2 { get; set; } = string.Empty; |
| public List<string> NullableList2 { get; set; } = []; |
| public HashSet<string> NullableSet2 { get; set; } = []; |
| public NullableKeyDictionary<string, string> NullableMap2 { get; set; } = new(); |
| } |
| |
| [ForyObject] |
| public sealed class RefInnerSchemaConsistent |
| { |
| public int Id { get; set; } |
| public string Name { get; set; } = string.Empty; |
| } |
| |
| [ForyObject] |
| public sealed class RefOuterSchemaConsistent |
| { |
| public RefInnerSchemaConsistent? Inner1 { get; set; } |
| public RefInnerSchemaConsistent? Inner2 { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class RefInnerCompatible |
| { |
| public int Id { get; set; } |
| public string Name { get; set; } = string.Empty; |
| } |
| |
| [ForyObject] |
| public sealed class RefOuterCompatible |
| { |
| public RefInnerCompatible? Inner1 { get; set; } |
| public RefInnerCompatible? Inner2 { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class RefOverrideElement |
| { |
| public int Id { get; set; } |
| public string Name { get; set; } = string.Empty; |
| } |
| |
| [ForyObject] |
| public sealed class RefOverrideContainer |
| { |
| public List<RefOverrideElement?> ListField { get; set; } = []; |
| public Dictionary<string, RefOverrideElement?> MapField { get; set; } = []; |
| } |
| |
| [ForyObject] |
| public sealed class CircularRefStruct |
| { |
| public string Name { get; set; } = string.Empty; |
| public CircularRefStruct? SelfRef { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class UnsignedSchemaConsistentSimple |
| { |
| [Field(Encoding = FieldEncoding.Tagged)] |
| public ulong U64Tagged { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Tagged)] |
| public ulong? U64TaggedNullable { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class UnsignedSchemaConsistent |
| { |
| public byte U8Field { get; set; } |
| public ushort U16Field { get; set; } |
| public uint U32VarField { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Fixed)] |
| public uint U32FixedField { get; set; } |
| |
| public ulong U64VarField { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Fixed)] |
| public ulong U64FixedField { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Tagged)] |
| public ulong U64TaggedField { get; set; } |
| |
| public byte? U8NullableField { get; set; } |
| public ushort? U16NullableField { get; set; } |
| public uint? U32VarNullableField { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Fixed)] |
| public uint? U32FixedNullableField { get; set; } |
| |
| public ulong? U64VarNullableField { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Fixed)] |
| public ulong? U64FixedNullableField { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Tagged)] |
| public ulong? U64TaggedNullableField { get; set; } |
| } |
| |
| [ForyObject] |
| public sealed class UnsignedSchemaCompatible |
| { |
| public byte? U8Field1 { get; set; } |
| public ushort? U16Field1 { get; set; } |
| public uint? U32VarField1 { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Fixed)] |
| public uint? U32FixedField1 { get; set; } |
| |
| public ulong? U64VarField1 { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Fixed)] |
| public ulong? U64FixedField1 { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Tagged)] |
| public ulong? U64TaggedField1 { get; set; } |
| |
| public byte U8Field2 { get; set; } |
| public ushort U16Field2 { get; set; } |
| public uint U32VarField2 { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Fixed)] |
| public uint U32FixedField2 { get; set; } |
| |
| public ulong U64VarField2 { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Fixed)] |
| public ulong U64FixedField2 { get; set; } |
| |
| [Field(Encoding = FieldEncoding.Tagged)] |
| public ulong U64TaggedField2 { get; set; } |
| } |