From 818b306a597fb2c6ede4e1e4b1f2d609705fa1b7 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 5cc1985..6921bf9 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1198,15 +1198,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 fc69abe9325a375dd529cb88fbf6e7220e5922c0 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 6921bf9..261a969 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1194,7 +1194,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 ce039a94ae3e7bf0691f97a80f60f58c6e9d4f37 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 261a969..e0e9cac 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1194,7 +1194,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)}"); @@ -1208,14 +1209,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 6fae063672e4545e595c66d8cfb51fceb833d0d0 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 e0e9cac..c12fb9e 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1196,7 +1196,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 7aa3119728cc0165e3892d6e27c3678dfa9679d2 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 c12fb9e..3e95d23 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1197,7 +1197,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 e55f88448f3804bcc551c9e1feefe1b129062d3b 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 f0bd69e..d7ae7ec 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 962246655aa8e8f53f06f919133551e4f4624244 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 3e95d23..273582f 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -328,6 +328,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. @@ -362,7 +363,9 @@ private static TypeGenerationModel CreateGenerationModel( continue; } + propertyModel.BlittableByteOffset = blittableByteOffset; generationModel.Fields.Add(propertyModel); + blittableByteOffset += propertyModel.ElementByteCount; } return generationModel; @@ -1204,6 +1207,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 11bec983f9222379ade8480e24dd073638429034 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 d7ae7ec..ec5a641 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 22129ce5909bad1d5acf3c31fda7cd97d46133b0 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 ec5a641..2aee138 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 79b07ab95868cf9163aedb55d20896a35c2e2145 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 273582f..67f254a 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1199,7 +1199,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 2c5478b62fc52d9bc6e76b16d0d12d42372019c1 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 67f254a..82ac9ab 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -1199,7 +1199,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 ab9bb9248ed1096a3e981ee35920f673d11eb385 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 2aee138..4b94dd2 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 a065c586aca814b1e6236d243d984f047cb01959 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 40a306e..7335716 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 a00371e7f5c067a20681884ab3882ea59c57ef7f 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 8b24985d63b01a755880ad4f18915273550b2dee 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 1479b5b64213778ca2ab03c2d00c29133fe572f4 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 7335716..cb28888 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 936a51e14209d17a6c507c4a0ffbccc9db4ef099 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 cb28888..206bd2a 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 f9c5a5e265899016c607af61d1b503b1d5726d73 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 206bd2a..9538560 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 c3b71125f78e82db964ddb8ac9c9d248ba84c09a 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 9538560..b54df8e 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 3df67eb074b982d2bb04c5bd57df3e2420ee1d79 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 b54df8e..dc4d757 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 7c19ea23d7192ade4bb3cde88638531ee0533001 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Fri, 21 Aug 2026 14:31:15 +0900 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 dc4d757..aed98f0 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));