From 8dc82c53023c77b42983f4b336fbed5067536122 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Thu, 13 Aug 2026 15:32:21 +0900 Subject: [PATCH 01/21] remove --- src/ZeroSerializerGenerator.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index bf0ae53..52d7978 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1277,15 +1277,6 @@ private static void EmitViewProperty( sourceBuilder.OpenBlock(); sourceBuilder.AppendLine("get"); sourceBuilder.OpenBlock(); - if (containingModel.IsBlittableStruct) - { - sourceBuilder.AppendLine($"{containingModel.QualifiedSourceTypeName} blittableSourceValue = MemoryMarshal.Read<{containingModel.QualifiedSourceTypeName}>(serializedMemory.Span);"); - sourceBuilder.AppendLine($"return blittableSourceValue.{EscapeIdentifier(field.Symbol.Name)};"); - sourceBuilder.CloseBlock(); - sourceBuilder.CloseBlock(); - return; - } - sourceBuilder.AppendLine("ReadOnlySpan serializedData = serializedMemory.Span;"); sourceBuilder.AppendLine($"int fieldDataOffset = BinaryPrimitives.ReadInt32LittleEndian(serializedData.Slice({fieldIndex * 4}, 4));"); if (IsNullRepresentedByZeroFieldOffset(field)) From 11a7e7ce005c6508d966d8b0053c6d43673ea5df Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Thu, 13 Aug 2026 15:43:39 +0900 Subject: [PATCH 02/21] fix --- src/ZeroSerializerGenerator.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 52d7978..8285965 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1273,7 +1273,10 @@ private static void EmitViewProperty( propertyType = field.Symbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); } - sourceBuilder.AppendLine($"{propertyAccessibility} {propertyType} {EscapeIdentifier(field.Symbol.Name)}"); + var propertyReturnType = field.Kind is FieldSerializationKind.BlittableStruct + ? GetQualifiedViewName(field.NestedSerializableType) + : propertyType; + sourceBuilder.AppendLine($"{propertyAccessibility} {propertyReturnType} {EscapeIdentifier(field.Symbol.Name)}"); sourceBuilder.OpenBlock(); sourceBuilder.AppendLine("get"); sourceBuilder.OpenBlock(); From f795bc71cd62efec913973c806e3a834c79ab304 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 14 Aug 2026 08:42:09 +0900 Subject: [PATCH 03/21] fix --- src/ZeroSerializerGenerator.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 8285965..c7ac886 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1273,7 +1273,8 @@ private static void EmitViewProperty( propertyType = field.Symbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); } - var propertyReturnType = field.Kind is FieldSerializationKind.BlittableStruct + var propertyReturnType + = field.Kind is FieldSerializationKind.BlittableStruct or FieldSerializationKind.Nested ? GetQualifiedViewName(field.NestedSerializableType) : propertyType; sourceBuilder.AppendLine($"{propertyAccessibility} {propertyReturnType} {EscapeIdentifier(field.Symbol.Name)}"); @@ -1287,14 +1288,8 @@ private static void EmitViewProperty( // Null is represented entirely by the offset table; no property payload marker is read. sourceBuilder.AppendLine("if (fieldDataOffset == 0)"); sourceBuilder.OpenBlock(); - if (field.NullableUnderlyingType is not null && field.Kind != FieldSerializationKind.Nested) - { - sourceBuilder.AppendLine("return null;"); - } - else - { - sourceBuilder.AppendLine("return default;"); - } + // Always use 'default' instead of 'null' for reference types. + sourceBuilder.AppendLine("return default;"); sourceBuilder.CloseBlock(); } From 084022f97d6aebd00eb7fde78e7ec8538beb8ee2 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 14 Aug 2026 08:56:08 +0900 Subject: [PATCH 04/21] fix 3 --- src/ZeroSerializerGenerator.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index c7ac886..e100e9c 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1275,7 +1275,9 @@ private static void EmitViewProperty( var propertyReturnType = field.Kind is FieldSerializationKind.BlittableStruct or FieldSerializationKind.Nested - ? GetQualifiedViewName(field.NestedSerializableType) + ? field.NullableUnderlyingType is not null + : GetQualifiedViewName(field.NestedSerializableType) + "?" + : GetQualifiedViewName(field.NestedSerializableType) : propertyType; sourceBuilder.AppendLine($"{propertyAccessibility} {propertyReturnType} {EscapeIdentifier(field.Symbol.Name)}"); sourceBuilder.OpenBlock(); From 3ab413227b69cde8d4a778dbd3f59051b0a5653f Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 14 Aug 2026 08:57:03 +0900 Subject: [PATCH 05/21] fix 4 --- src/ZeroSerializerGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index e100e9c..615f515 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1276,7 +1276,7 @@ private static void EmitViewProperty( var propertyReturnType = field.Kind is FieldSerializationKind.BlittableStruct or FieldSerializationKind.Nested ? field.NullableUnderlyingType is not null - : GetQualifiedViewName(field.NestedSerializableType) + "?" + ? GetQualifiedViewName(field.NestedSerializableType) + "?" : GetQualifiedViewName(field.NestedSerializableType) : propertyType; sourceBuilder.AppendLine($"{propertyAccessibility} {propertyReturnType} {EscapeIdentifier(field.Symbol.Name)}"); From 0db64bfdb53cb71cb9153b9c7b5deb0a1b35f29c Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 14 Aug 2026 09:12:45 +0900 Subject: [PATCH 06/21] fix 5 --- tests-unity/UnityCompatibility.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests-unity/UnityCompatibility.cs b/tests-unity/UnityCompatibility.cs index 31c819c..48cd9a0 100644 --- a/tests-unity/UnityCompatibility.cs +++ b/tests-unity/UnityCompatibility.cs @@ -122,8 +122,8 @@ && variableView.Child.Identifier == 99 && variableView.StructChild.Identifier == 100 && variableView.StructChild.Name.SequenceEqual("struct".AsSpan()) - && variableView.OptionalStructChild.Identifier == 101 - && variableView.OptionalStructChild.Name.SequenceEqual("optional struct".AsSpan()) + && variableView.OptionalStructChild.Value.Identifier == 101 + && variableView.OptionalStructChild.Value.Name.SequenceEqual("optional struct".AsSpan()) && variableView.FloatValues.Length == 3 && variableView.FloatValues[1] == 2.5f && variableView.DoubleValues.Length == 3 From 71078ef196956590faf00eea8ad41e3caaf9d740 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 14 Aug 2026 11:34:19 +0900 Subject: [PATCH 07/21] Fix tests for nullable nested-struct view behavior (#78) * test nullable nested struct views * fix blittable view property reads * test blittable views through materialization * test blittable views as borrowed bytes * test reading blittable view payloads * return nested views from blittable getters * simplify blittable nested view offsets * remove MemoryMarshal from tests * test blittable values through views * remove interop import from Unity tests * preserve view metadata test coverage * remove MemoryMarshal references from tests * revert test changes * restore --- src/FieldGenerationModel.cs | 2 ++ src/ZeroSerializerGenerator.cs | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/FieldGenerationModel.cs b/src/FieldGenerationModel.cs index 0d2d1f0..67e9d56 100644 --- a/src/FieldGenerationModel.cs +++ b/src/FieldGenerationModel.cs @@ -33,6 +33,8 @@ internal FieldGenerationModel( internal int ElementByteCount { get; } + internal int BlittableByteOffset { get; set; } + internal ITypeSymbol? ArrayElementType { get; } internal INamedTypeSymbol? NestedSerializableType { get; } diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 615f515..afa45be 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -339,6 +339,7 @@ private static TypeGenerationModel CreateGenerationModel( } // Roslyn's member order is the wire declaration order; never infer a different order from file paths or spans. + int blittableByteOffset = 0; foreach (ISymbol declaredMember in serializableType.GetMembers()) { // Only public getter properties define the wire contract; fields, setters, and indexers must never leak into it. @@ -373,7 +374,9 @@ private static TypeGenerationModel CreateGenerationModel( continue; } + propertyModel.BlittableByteOffset = blittableByteOffset; generationModel.Fields.Add(propertyModel); + blittableByteOffset += propertyModel.ElementByteCount; } return generationModel; @@ -1283,6 +1286,23 @@ var propertyReturnType sourceBuilder.OpenBlock(); sourceBuilder.AppendLine("get"); sourceBuilder.OpenBlock(); + if (containingModel.IsBlittableStruct) + { + if (field.Kind == FieldSerializationKind.BlittableStruct + && field.NestedSerializableType is not null) + { + sourceBuilder.AppendLine($"return new {GetQualifiedViewName(field.NestedSerializableType)}(serializedMemory.Slice({field.BlittableByteOffset}, {field.ElementByteCount}));"); + } + else + { + sourceBuilder.AppendLine($"{containingModel.QualifiedSourceTypeName} blittableSourceValue = MemoryMarshal.Read<{containingModel.QualifiedSourceTypeName}>(serializedMemory.Span);"); + sourceBuilder.AppendLine($"return blittableSourceValue.{EscapeIdentifier(field.Symbol.Name)};"); + } + sourceBuilder.CloseBlock(); + sourceBuilder.CloseBlock(); + return; + } + sourceBuilder.AppendLine("ReadOnlySpan serializedData = serializedMemory.Span;"); sourceBuilder.AppendLine($"int fieldDataOffset = BinaryPrimitives.ReadInt32LittleEndian(serializedData.Slice({fieldIndex * 4}, 4));"); if (IsNullRepresentedByZeroFieldOffset(field)) From a927661c7614a5cae5eb7574369d78f1fe879c74 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 14 Aug 2026 11:38:10 +0900 Subject: [PATCH 08/21] Apply suggestion from @sator-imaging --- tests-unity/UnityCompatibility.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests-unity/UnityCompatibility.cs b/tests-unity/UnityCompatibility.cs index 48cd9a0..d02b336 100644 --- a/tests-unity/UnityCompatibility.cs +++ b/tests-unity/UnityCompatibility.cs @@ -122,8 +122,8 @@ && variableView.Child.Identifier == 99 && variableView.StructChild.Identifier == 100 && variableView.StructChild.Name.SequenceEqual("struct".AsSpan()) - && variableView.OptionalStructChild.Value.Identifier == 101 - && variableView.OptionalStructChild.Value.Name.SequenceEqual("optional struct".AsSpan()) + && variableView.OptionalStructChild?.Identifier == 101 + && variableView.OptionalStructChild?.Name.SequenceEqual("optional struct".AsSpan()) && variableView.FloatValues.Length == 3 && variableView.FloatValues[1] == 2.5f && variableView.DoubleValues.Length == 3 From c96e2c9c323bae93d08ac1d0e6f6f0f3494456e2 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 14 Aug 2026 11:39:17 +0900 Subject: [PATCH 09/21] Apply suggestion from @sator-imaging --- tests-unity/UnityCompatibility.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-unity/UnityCompatibility.cs b/tests-unity/UnityCompatibility.cs index d02b336..0c525d2 100644 --- a/tests-unity/UnityCompatibility.cs +++ b/tests-unity/UnityCompatibility.cs @@ -123,7 +123,7 @@ && variableView.StructChild.Identifier == 100 && variableView.StructChild.Name.SequenceEqual("struct".AsSpan()) && variableView.OptionalStructChild?.Identifier == 101 - && variableView.OptionalStructChild?.Name.SequenceEqual("optional struct".AsSpan()) + && variableView.OptionalStructChild?.Name.SequenceEqual("optional struct".AsSpan()) == true && variableView.FloatValues.Length == 3 && variableView.FloatValues[1] == 2.5f && variableView.DoubleValues.Length == 3 From 51ec2c60e59e6d0d378e5728c8396120c2d128d2 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Sat, 15 Aug 2026 08:32:16 +0900 Subject: [PATCH 10/21] Apply suggestion from @sator-imaging --- src/ZeroSerializerGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index afa45be..f2ea9c4 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1278,7 +1278,7 @@ private static void EmitViewProperty( var propertyReturnType = field.Kind is FieldSerializationKind.BlittableStruct or FieldSerializationKind.Nested - ? field.NullableUnderlyingType is not null + ? (field.NullableUnderlyingType is not null || field.Symbol.TypeKind is TypeKind.Class) ? GetQualifiedViewName(field.NestedSerializableType) + "?" : GetQualifiedViewName(field.NestedSerializableType) : propertyType; From 3447488c7cee9c7d1e6f9668ec9fda7f3e5f09d8 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Sat, 15 Aug 2026 08:43:48 +0900 Subject: [PATCH 11/21] Apply suggestion from @sator-imaging --- src/ZeroSerializerGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index f2ea9c4..51dbf01 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1278,7 +1278,7 @@ private static void EmitViewProperty( var propertyReturnType = field.Kind is FieldSerializationKind.BlittableStruct or FieldSerializationKind.Nested - ? (field.NullableUnderlyingType is not null || field.Symbol.TypeKind is TypeKind.Class) + ? (field.NullableUnderlyingType is not null || field.Symbol.Type.TypeKind is TypeKind.Class) ? GetQualifiedViewName(field.NestedSerializableType) + "?" : GetQualifiedViewName(field.NestedSerializableType) : propertyType; From 441ce140e696e6c856cf7e9d7e15fe707b7991aa Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Sat, 15 Aug 2026 19:53:09 +0900 Subject: [PATCH 12/21] Apply suggestion from @sator-imaging --- tests-unity/UnityCompatibility.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-unity/UnityCompatibility.cs b/tests-unity/UnityCompatibility.cs index 0c525d2..c1541d2 100644 --- a/tests-unity/UnityCompatibility.cs +++ b/tests-unity/UnityCompatibility.cs @@ -119,7 +119,7 @@ && variableView.OptionalState == PacketState.Ready && variableView.OptionalPosition!.Value.X == 30 && variableView.MissingOptionalPosition is null - && variableView.Child.Identifier == 99 + && variableView.Child?.Identifier == 99 && variableView.StructChild.Identifier == 100 && variableView.StructChild.Name.SequenceEqual("struct".AsSpan()) && variableView.OptionalStructChild?.Identifier == 101 From 0d63406318bc567dd8c58dd6bf25d7cc8de778bb Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Thu, 20 Aug 2026 09:59:56 +0900 Subject: [PATCH 13/21] fix error --- benchmark/Benchmark.cs | 6 +++--- tests/SerializationTests.cs | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/benchmark/Benchmark.cs b/benchmark/Benchmark.cs index f7bd8d2..1908202 100644 --- a/benchmark/Benchmark.cs +++ b/benchmark/Benchmark.cs @@ -126,9 +126,9 @@ public int DeserializeAllProperties() ReadOnlySpan integers = view.Integers; ReadOnlySpan longs = view.Longs; ReadOnlySpan packedValues = view.PackedValues; - NestedPayloadView nested = view.Nested; - int nestedVersion = nested.Version; - ReadOnlySpan nestedLabel = nested.Label; + NestedPayloadView? nested = view.Nested; + int nestedVersion = nested?.Version ?? -1; + ReadOnlySpan nestedLabel = nested?.Label ?? string.Empty; PackedBenchmarkValueView nestedSummary = nested.Summary; NestedStructPayloadView nestedStruct = view.NestedStruct; int nestedStructCode = nestedStruct.Code; diff --git a/tests/SerializationTests.cs b/tests/SerializationTests.cs index f76c11b..2c7f28b 100644 --- a/tests/SerializationTests.cs +++ b/tests/SerializationTests.cs @@ -249,8 +249,8 @@ public void VariableDataRoundTrip() TestAssert.Equal(source.Text, view.Text.ToString(), nameof(view.Text)); TestAssert.SequenceEqual(source.Values, view.Values, nameof(view.Values)); TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(view.OptionalNumber)); - TestAssert.Equal(source.Child.Identifier, view.Child.Identifier, nameof(view.Child.Identifier)); - TestAssert.Equal(source.Child.State, view.Child.State, nameof(view.Child.State)); + TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(view.Child?.Identifier)); + TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(view.Child?.State)); TestAssert.Equal(source.Tail, view.Tail, nameof(view.Tail)); int textFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(0, 4)); int valuesFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(4, 4)); @@ -284,8 +284,8 @@ public void VariableViewOnlyRequiresCorrectSerializedStart() TestAssert.Equal(source.Text, view.Text.ToString(), nameof(view.Text)); TestAssert.SequenceEqual(source.Values, view.Values, nameof(view.Values)); TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(view.OptionalNumber)); - TestAssert.Equal(source.Child.Identifier, view.Child.Identifier, nameof(view.Child.Identifier)); - TestAssert.Equal(source.Child.State, view.Child.State, nameof(view.Child.State)); + TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(view.Child?.Identifier)); + TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(view.Child?.State)); TestAssert.Equal(source.Tail, view.Tail, nameof(view.Tail)); ReadOnlyMemory borrowedSerializedMemory = view; @@ -521,9 +521,9 @@ public void EveryTruncatedSerializedBufferThrowsStandardBoundsExceptionWhenRead( _ = view.Text.Length; _ = view.Values.Length; _ = view.OptionalNumber; - FixedClassView childView = view.Child; - _ = childView.Identifier; - _ = childView.State; + FixedClassView? childView = view.Child; + _ = childView?.Identifier; + _ = childView?.State; _ = view.Tail; }, nameof(VariableRecord)); From f78186fe10df048c9ef1c99fb98c3e1fcf65b8b9 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Thu, 20 Aug 2026 10:05:37 +0900 Subject: [PATCH 14/21] fix error 2 --- benchmark/Benchmark.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark/Benchmark.cs b/benchmark/Benchmark.cs index 1908202..48146d3 100644 --- a/benchmark/Benchmark.cs +++ b/benchmark/Benchmark.cs @@ -128,8 +128,8 @@ public int DeserializeAllProperties() ReadOnlySpan packedValues = view.PackedValues; NestedPayloadView? nested = view.Nested; int nestedVersion = nested?.Version ?? -1; - ReadOnlySpan nestedLabel = nested?.Label ?? string.Empty; - PackedBenchmarkValueView nestedSummary = nested.Summary; + ReadOnlySpan nestedLabel = nested?.Label ?? default; + PackedBenchmarkValueView nestedSummary = nested?.Summary ?? new(); NestedStructPayloadView nestedStruct = view.NestedStruct; int nestedStructCode = nestedStruct.Code; long nestedStructAmount = nestedStruct.Amount; From 58bd2767e0fd5bd286df6b7a30513fa082264f0b Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Thu, 20 Aug 2026 10:44:50 +0900 Subject: [PATCH 15/21] fix error 3 --- benchmark/Benchmark.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/Benchmark.cs b/benchmark/Benchmark.cs index 48146d3..da7bac1 100644 --- a/benchmark/Benchmark.cs +++ b/benchmark/Benchmark.cs @@ -128,7 +128,7 @@ public int DeserializeAllProperties() ReadOnlySpan packedValues = view.PackedValues; NestedPayloadView? nested = view.Nested; int nestedVersion = nested?.Version ?? -1; - ReadOnlySpan nestedLabel = nested?.Label ?? default; + ReadOnlySpan nestedLabel = (nested ?? new()).Label; // Nullable> is invalid PackedBenchmarkValueView nestedSummary = nested?.Summary ?? new(); NestedStructPayloadView nestedStruct = view.NestedStruct; int nestedStructCode = nestedStruct.Code; From 342ff304086eba88a281ba7f8c11e5679e772c97 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Thu, 20 Aug 2026 10:58:37 +0900 Subject: [PATCH 16/21] fix error 4 --- tests/SerializationTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/SerializationTests.cs b/tests/SerializationTests.cs index 2c7f28b..ea84cee 100644 --- a/tests/SerializationTests.cs +++ b/tests/SerializationTests.cs @@ -249,8 +249,8 @@ public void VariableDataRoundTrip() TestAssert.Equal(source.Text, view.Text.ToString(), nameof(view.Text)); TestAssert.SequenceEqual(source.Values, view.Values, nameof(view.Values)); TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(view.OptionalNumber)); - TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(view.Child?.Identifier)); - TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(view.Child?.State)); + TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(view.Child!.Value.Identifier)); + TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(view.Child!.Value.State)); TestAssert.Equal(source.Tail, view.Tail, nameof(view.Tail)); int textFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(0, 4)); int valuesFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(4, 4)); @@ -284,8 +284,8 @@ public void VariableViewOnlyRequiresCorrectSerializedStart() TestAssert.Equal(source.Text, view.Text.ToString(), nameof(view.Text)); TestAssert.SequenceEqual(source.Values, view.Values, nameof(view.Values)); TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(view.OptionalNumber)); - TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(view.Child?.Identifier)); - TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(view.Child?.State)); + TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(view.Child!.Value.Identifier)); + TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(view.Child!.Value.State)); TestAssert.Equal(source.Tail, view.Tail, nameof(view.Tail)); ReadOnlyMemory borrowedSerializedMemory = view; From 65e9ae6c02d5a6e93628463e5fb2eac3f318c871 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Thu, 20 Aug 2026 11:11:08 +0900 Subject: [PATCH 17/21] fix error 5 --- tests/SerializationTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/SerializationTests.cs b/tests/SerializationTests.cs index ea84cee..888a763 100644 --- a/tests/SerializationTests.cs +++ b/tests/SerializationTests.cs @@ -249,8 +249,8 @@ public void VariableDataRoundTrip() TestAssert.Equal(source.Text, view.Text.ToString(), nameof(view.Text)); TestAssert.SequenceEqual(source.Values, view.Values, nameof(view.Values)); TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(view.OptionalNumber)); - TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(view.Child!.Value.Identifier)); - TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(view.Child!.Value.State)); + TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(VariableRecordView.Child.Identifier)); + TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(VariableRecordView.Child.State)); TestAssert.Equal(source.Tail, view.Tail, nameof(view.Tail)); int textFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(0, 4)); int valuesFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(4, 4)); @@ -284,8 +284,8 @@ public void VariableViewOnlyRequiresCorrectSerializedStart() TestAssert.Equal(source.Text, view.Text.ToString(), nameof(view.Text)); TestAssert.SequenceEqual(source.Values, view.Values, nameof(view.Values)); TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(view.OptionalNumber)); - TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(view.Child!.Value.Identifier)); - TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(view.Child!.Value.State)); + TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(VariableRecordView.Child.Identifier)); + TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(VariableRecordView.Child.State)); TestAssert.Equal(source.Tail, view.Tail, nameof(view.Tail)); ReadOnlyMemory borrowedSerializedMemory = view; From d40c38832d4326530cfee2452ab0c1901e267d7e Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 21 Aug 2026 13:53:37 +0900 Subject: [PATCH 18/21] Apply suggestions from code review Co-authored-by: sator-imaging <16752340+sator-imaging@users.noreply.github.com> --- tests/SerializationTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/SerializationTests.cs b/tests/SerializationTests.cs index 888a763..12b749d 100644 --- a/tests/SerializationTests.cs +++ b/tests/SerializationTests.cs @@ -249,8 +249,8 @@ public void VariableDataRoundTrip() TestAssert.Equal(source.Text, view.Text.ToString(), nameof(view.Text)); TestAssert.SequenceEqual(source.Values, view.Values, nameof(view.Values)); TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(view.OptionalNumber)); - TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(VariableRecordView.Child.Identifier)); - TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(VariableRecordView.Child.State)); + TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(FixedClassView.Identifier)); + TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(FixedClassView.State)); TestAssert.Equal(source.Tail, view.Tail, nameof(view.Tail)); int textFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(0, 4)); int valuesFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(4, 4)); @@ -284,8 +284,8 @@ public void VariableViewOnlyRequiresCorrectSerializedStart() TestAssert.Equal(source.Text, view.Text.ToString(), nameof(view.Text)); TestAssert.SequenceEqual(source.Values, view.Values, nameof(view.Values)); TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(view.OptionalNumber)); - TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(VariableRecordView.Child.Identifier)); - TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(VariableRecordView.Child.State)); + TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(FixedClassView.Identifier)); + TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(FixedClassView.State)); TestAssert.Equal(source.Tail, view.Tail, nameof(view.Tail)); ReadOnlyMemory borrowedSerializedMemory = view; From 1e110a05e52a004aabb0a0b5d11acff10807dfc1 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 21 Aug 2026 13:58:53 +0900 Subject: [PATCH 19/21] Apply suggestions from code review Co-authored-by: sator-imaging <16752340+sator-imaging@users.noreply.github.com> --- tests/SerializationTests.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/SerializationTests.cs b/tests/SerializationTests.cs index 12b749d..0d2847d 100644 --- a/tests/SerializationTests.cs +++ b/tests/SerializationTests.cs @@ -246,12 +246,12 @@ public void VariableDataRoundTrip() int expectedRequiredByteLength = -(24 + (4 * IntPtr.Size)); TestAssert.Equal(expectedRequiredByteLength, VariableRecordView.RequiredByteLength, nameof(VariableRecordView.RequiredByteLength)); - TestAssert.Equal(source.Text, view.Text.ToString(), nameof(view.Text)); - TestAssert.SequenceEqual(source.Values, view.Values, nameof(view.Values)); - TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(view.OptionalNumber)); - TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(FixedClassView.Identifier)); - TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(FixedClassView.State)); - TestAssert.Equal(source.Tail, view.Tail, nameof(view.Tail)); +TestAssert.Equal(source.Text, view.Text.ToString(), nameof(source.Text)); +TestAssert.SequenceEqual(source.Values, view.Values, nameof(source.Values)); +TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(source.OptionalNumber)); + TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(source.Child.Identifier)); + TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(source.Child.State)); +TestAssert.Equal(source.Tail, view.Tail, nameof(source.Tail)); int textFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(0, 4)); int valuesFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(4, 4)); int optionalNumberFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(8, 4)); From 08359f5d7993c13eaaf30882d6f9a4cfd258a117 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 21 Aug 2026 05:25:44 +0000 Subject: [PATCH 20/21] fix error --- tests/SerializationTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SerializationTests.cs b/tests/SerializationTests.cs index 0d2847d..7433af1 100644 --- a/tests/SerializationTests.cs +++ b/tests/SerializationTests.cs @@ -777,7 +777,7 @@ public void NestedTypesReturnViewsTest() // 2. Assert that nested non-blittable type returns view PropertyInfo? childProperty = typeof(VariableRecordView).GetProperty(nameof(VariableRecordView.Child)); Assert.NotNull(childProperty); - Assert.Equal(typeof(FixedClassView), childProperty!.PropertyType); + Assert.Equal(typeof(FixedClassView?), childProperty!.PropertyType); } public void StrictBlittableStructTests() From 5a57983502eb228650a2f38a021cef74975fe624 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 21 Aug 2026 07:07:51 +0000 Subject: [PATCH 21/21] Apply suggestion from @sator-imaging --- tests/SerializationTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/SerializationTests.cs b/tests/SerializationTests.cs index 7433af1..58cde54 100644 --- a/tests/SerializationTests.cs +++ b/tests/SerializationTests.cs @@ -246,12 +246,12 @@ public void VariableDataRoundTrip() int expectedRequiredByteLength = -(24 + (4 * IntPtr.Size)); TestAssert.Equal(expectedRequiredByteLength, VariableRecordView.RequiredByteLength, nameof(VariableRecordView.RequiredByteLength)); -TestAssert.Equal(source.Text, view.Text.ToString(), nameof(source.Text)); -TestAssert.SequenceEqual(source.Values, view.Values, nameof(source.Values)); -TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(source.OptionalNumber)); + TestAssert.Equal(source.Text, view.Text.ToString(), nameof(source.Text)); + TestAssert.SequenceEqual(source.Values, view.Values, nameof(source.Values)); + TestAssert.Equal(source.OptionalNumber, view.OptionalNumber, nameof(source.OptionalNumber)); TestAssert.Equal(source.Child.Identifier, view.Child?.Identifier ?? -1, nameof(source.Child.Identifier)); TestAssert.Equal(source.Child.State, view.Child?.State ?? ByteState.None, nameof(source.Child.State)); -TestAssert.Equal(source.Tail, view.Tail, nameof(source.Tail)); + TestAssert.Equal(source.Tail, view.Tail, nameof(source.Tail)); int textFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(0, 4)); int valuesFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(4, 4)); int optionalNumberFieldOffset = BinaryPrimitives.ReadInt32LittleEndian(buffer.AsSpan(8, 4));