From b2bcb2186b0ea8c979cb8671d30c85404c7ff5be Mon Sep 17 00:00:00 2001 From: SlejmUr Date: Tue, 24 Feb 2026 21:43:22 +0100 Subject: [PATCH 1/4] Implement support for netstandard --- EIV_Pack.Example/EIV_Pack.Example.csproj | 10 +++- EIV_Pack.Generator/MainGenerator.cs | 22 ++++++- EIV_Pack.Generator/PackGenerator.cs | 66 +++++++++++++++------ EIV_Pack.Test/ArrayFormatterTests.cs | 8 +++ EIV_Pack.Test/AssemblyInfo.cs | 1 + EIV_Pack.Test/EIV_Pack.Test.csproj | 11 +++- EIV_Pack.Test/OtherFormatterTests.cs | 2 +- EIV_Pack.Test/ProviderTests.cs | 2 +- EIV_Pack.Test/UnmanagedTests.cs | 24 ++++++++ EIV_Pack/EIV_Pack.csproj | 6 +- EIV_Pack/FormatterProvider.cs | 12 +++- EIV_Pack/Formatters/ArrayFormatters.cs | 4 ++ EIV_Pack/Formatters/CollectionFormatters.cs | 8 +++ EIV_Pack/Formatters/DictionaryFormatters.cs | 7 +++ EIV_Pack/Formatters/IFormatter.cs | 5 +- EIV_Pack/Formatters/LazyFormatter.cs | 12 +++- EIV_Pack/PackException.cs | 12 +++- EIV_Pack/PackReader.cs | 30 +++++++++- EIV_Pack/PackWriter.FormatterWrite.cs | 6 ++ EIV_Pack/PackWriter.Retrieve.cs | 7 ++- EIV_Pack/PackWriter.Writers.cs | 7 ++- EIV_Pack/Serializer.cs | 8 ++- 22 files changed, 227 insertions(+), 43 deletions(-) create mode 100644 EIV_Pack.Test/AssemblyInfo.cs diff --git a/EIV_Pack.Example/EIV_Pack.Example.csproj b/EIV_Pack.Example/EIV_Pack.Example.csproj index a421745..824e599 100644 --- a/EIV_Pack.Example/EIV_Pack.Example.csproj +++ b/EIV_Pack.Example/EIV_Pack.Example.csproj @@ -1,9 +1,10 @@  - net10.0 + net10.0;net8.0;net472 enable enable + latest @@ -13,10 +14,13 @@ - + diff --git a/EIV_Pack.Generator/MainGenerator.cs b/EIV_Pack.Generator/MainGenerator.cs index ac31fd1..75e6a88 100644 --- a/EIV_Pack.Generator/MainGenerator.cs +++ b/EIV_Pack.Generator/MainGenerator.cs @@ -24,9 +24,27 @@ or StructDeclarationSyntax }) .WithTrackingName("EIV_Pack.EIV_Packable.1_ForAttributeEIV_PackableAttribute"); - context.RegisterSourceOutput(typeDeclarations.Combine(context.CompilationProvider), static (context, source) => + var options = context.ParseOptionsProvider.Select((option, token) => { - PackGenerator.Generate(source.Left, source.Right, context); + return option.PreprocessorSymbolNames.Contains("NET8_0_OR_GREATER"); + }); + + context.RegisterSourceOutput(typeDeclarations.Combine(context.CompilationProvider).Combine(options), static (context, source) => + { + GeneratorClass generatorClass = new() + { + Syntax = source.Left.Left, + Compilation = source.Left.Right, + IsNet8OrGreater = source.Right, + }; + PackGenerator.Generate(generatorClass, context); }); } } + +public class GeneratorClass +{ + public TypeDeclarationSyntax Syntax { get; set; } = default!; + public Compilation Compilation { get; set; } = default!; + public bool IsNet8OrGreater { get; set; } = default!; +} diff --git a/EIV_Pack.Generator/PackGenerator.cs b/EIV_Pack.Generator/PackGenerator.cs index 6715525..1a098fb 100644 --- a/EIV_Pack.Generator/PackGenerator.cs +++ b/EIV_Pack.Generator/PackGenerator.cs @@ -7,9 +7,10 @@ namespace EIV_Pack.Generator; internal static class PackGenerator { - internal static void Generate(TypeDeclarationSyntax syntax, Compilation compilation, SourceProductionContext context) + internal static void Generate(GeneratorClass generatorClass, SourceProductionContext context) { - var semanticModel = compilation.GetSemanticModel(syntax.SyntaxTree); + TypeDeclarationSyntax syntax = generatorClass.Syntax; + var semanticModel = generatorClass.Compilation.GetSemanticModel(syntax.SyntaxTree); var typeSymbol = semanticModel.GetDeclaredSymbol(syntax, context.CancellationToken); if (typeSymbol == null) @@ -53,7 +54,13 @@ internal static void Generate(TypeDeclarationSyntax syntax, Compilation compilat sb.AppendLine("// Generated with EIV_Pack.Generator."); sb.AppendLine("using EIV_Pack;"); sb.AppendLine("using EIV_Pack.Formatters;"); - sb.AppendLine("#nullable enable"); + sb.AppendLine(); + + if (generatorClass.IsNet8OrGreater) + { + sb.AppendLine("#nullable enable"); + sb.AppendLine(); + } List names = []; INamespaceSymbol namespaceSymbol = typeSymbol.ContainingNamespace; @@ -77,8 +84,17 @@ internal static void Generate(TypeDeclarationSyntax syntax, Compilation compilat namespaceStr = namespaceStr.Substring(1); if (!string.IsNullOrEmpty(namespaceStr)) - sb.AppendLine($"namespace {namespaceStr};"); - + { + if (generatorClass.IsNet8OrGreater) + { + sb.AppendLine($"namespace {namespaceStr};"); + } + else + { + sb.AppendLine($"namespace {namespaceStr}"); + sb.AppendLine("{"); + } + } sb.AppendLine(); sb.AppendLine($"partial {classOrStructOrRecord} {typeSymbol.Name} : IPackable<{typeSymbol.Name}>, IFormatter<{typeSymbol.Name}>"); @@ -86,17 +102,21 @@ internal static void Generate(TypeDeclarationSyntax syntax, Compilation compilat if (!typeSymbol.GetMembers().Any(x => x.IsStatic && x.Kind == SymbolKind.Method && x.Name == ".cctor")) { - sb.AppendLine($$""" + string register = generatorClass.IsNet8OrGreater ? $"FormatterProvider.Register<{typeSymbol.Name}>" : "RegisterFormatter"; + + sb.AppendLine( + $$""" static {{typeSymbol.Name}}() { - FormatterProvider.Register<{{typeSymbol.Name}}>(); + {{register}}(); } - + """); } - sb.AppendLine($$""" + sb.AppendLine( + $$""" public static void RegisterFormatter() { @@ -110,33 +130,43 @@ public static void RegisterFormatter() FormatterProvider.Register(new ArrayFormatter<{{typeSymbol.Name}}>()); } } - + """); - GeneratePackable(ref syntax, ref typeSymbol, ref sb, ref fieldOrParamList); + GeneratePackable(ref syntax, ref typeSymbol, ref sb, ref fieldOrParamList, generatorClass.IsNet8OrGreater); - sb.AppendLine($$""" - public void Deserialize(ref PackReader reader, scoped ref {{typeSymbol.Name}}{{(typeSymbol.IsValueType ? string.Empty : "?")}} value) + + sb.AppendLine( + $$""" + + public void Deserialize(ref PackReader reader, scoped ref {{typeSymbol.Name}}{{(typeSymbol.IsValueType ? string.Empty : generatorClass.IsNet8OrGreater ? "?" : string.Empty)}} value) { DeserializePackable(ref reader, ref value); } - public void Serialize(ref PackWriter writer, scoped ref readonly {{typeSymbol.Name}}{{(typeSymbol.IsValueType ? string.Empty : "?")}} value) + public void Serialize(ref PackWriter writer, scoped ref readonly {{typeSymbol.Name}}{{(typeSymbol.IsValueType ? string.Empty : generatorClass.IsNet8OrGreater ? "?" : string.Empty)}} value) { SerializePackable(ref writer, in value); } - + """); sb.AppendLine("}"); + + if (!string.IsNullOrEmpty(namespaceStr) && !generatorClass.IsNet8OrGreater) + { + sb.AppendLine(); + sb.AppendLine("}"); + } + context.AddSource($"{fullType}.g.cs", sb.ToString()); } - internal static void GeneratePackable(ref TypeDeclarationSyntax _, ref INamedTypeSymbol typeSymbol, ref StringBuilder sb, ref List FieldAndParamList) + internal static void GeneratePackable(ref TypeDeclarationSyntax _, ref INamedTypeSymbol typeSymbol, ref StringBuilder sb, ref List FieldAndParamList, bool isNet8OrGreater) { - var nullable = typeSymbol.IsValueType ? "" : "?"; + var nullable = typeSymbol.IsValueType ? string.Empty : isNet8OrGreater ? "?" : string.Empty; sb.AppendLine($"\tconst int EIV_PACK_FieldAndParamCount = {FieldAndParamList.Count};"); @@ -165,7 +195,7 @@ internal static void GeneratePackable(ref TypeDeclarationSyntax _, ref INamedTyp } sb.AppendLine("\t}"); - + sb.AppendLine(); sb.AppendLine($"\tpublic static void SerializePackable(ref PackWriter writer, scoped ref readonly {typeSymbol.Name}{nullable} value)"); sb.AppendLine("\t{"); if (!typeSymbol.IsValueType) diff --git a/EIV_Pack.Test/ArrayFormatterTests.cs b/EIV_Pack.Test/ArrayFormatterTests.cs index 80aaa86..deb7811 100644 --- a/EIV_Pack.Test/ArrayFormatterTests.cs +++ b/EIV_Pack.Test/ArrayFormatterTests.cs @@ -6,6 +6,13 @@ namespace EIV_Pack.Test; public class ArrayFormatterTests { + private readonly ITestOutputHelper output; + + public ArrayFormatterTests(ITestOutputHelper output) + { + this.output = output; + } + [Fact] public void ArrayTest() { @@ -16,6 +23,7 @@ public void ArrayTest() writer.WriteValueWithFormatter(intArrayFormatter, ints); var bytes = writer.GetBytes(); Assert.NotEmpty(bytes); + output.WriteLine(BitConverter.ToString(bytes)); PackReader reader = new(bytes); Assert.Equal(ints, reader.ReadValueWithFormatter(intArrayFormatter)); Assert.Equal(0, reader.Remaining); diff --git a/EIV_Pack.Test/AssemblyInfo.cs b/EIV_Pack.Test/AssemblyInfo.cs new file mode 100644 index 0000000..21ea81b --- /dev/null +++ b/EIV_Pack.Test/AssemblyInfo.cs @@ -0,0 +1 @@ +[assembly: CaptureConsole] \ No newline at end of file diff --git a/EIV_Pack.Test/EIV_Pack.Test.csproj b/EIV_Pack.Test/EIV_Pack.Test.csproj index 272ddc6..9189d2b 100644 --- a/EIV_Pack.Test/EIV_Pack.Test.csproj +++ b/EIV_Pack.Test/EIV_Pack.Test.csproj @@ -1,15 +1,20 @@  - net10.0 + net10.0;net8.0;net472 enable enable false + latest + Exe - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/EIV_Pack.Test/OtherFormatterTests.cs b/EIV_Pack.Test/OtherFormatterTests.cs index d8622be..4324a86 100644 --- a/EIV_Pack.Test/OtherFormatterTests.cs +++ b/EIV_Pack.Test/OtherFormatterTests.cs @@ -10,7 +10,7 @@ public void LazyTest() PackWriter writer = new(); var formatter = new LazyFormatter(); Assert.NotNull(formatter); - Lazy val = new(6); + Lazy val = new(() => 6); Lazy? vallNull = null; writer.WriteValueWithFormatter(formatter, val); writer.WriteValueWithFormatter(formatter, vallNull); diff --git a/EIV_Pack.Test/ProviderTests.cs b/EIV_Pack.Test/ProviderTests.cs index 8d7f06a..3a4bce3 100644 --- a/EIV_Pack.Test/ProviderTests.cs +++ b/EIV_Pack.Test/ProviderTests.cs @@ -13,7 +13,7 @@ public void ProviderTest() { Assert.Throws(() => FormatterProvider.GetFormatter()); - FormatterProvider.Register(null); + FormatterProvider.Register(null!); Assert.Throws(() => FormatterProvider.GetFormatter()); } diff --git a/EIV_Pack.Test/UnmanagedTests.cs b/EIV_Pack.Test/UnmanagedTests.cs index 59b2eac..f653d1b 100644 --- a/EIV_Pack.Test/UnmanagedTests.cs +++ b/EIV_Pack.Test/UnmanagedTests.cs @@ -26,10 +26,12 @@ public void UnmangedTest() writer.WriteUnmanaged(long.MaxValue); writer.WriteUnmanaged(ulong.MinValue); writer.WriteUnmanaged(ulong.MaxValue); +#if NET8_0_OR_GREATER writer.WriteUnmanaged(Int128.MinValue); writer.WriteUnmanaged(Int128.MaxValue); writer.WriteUnmanaged(UInt128.MinValue); writer.WriteUnmanaged(UInt128.MaxValue); +#endif writer.WriteUnmanaged(char.MinValue); writer.WriteUnmanaged(char.MaxValue); writer.WriteUnmanaged(float.MinValue); @@ -38,20 +40,24 @@ public void UnmangedTest() writer.WriteUnmanaged(double.MaxValue); writer.WriteUnmanaged(decimal.MinValue); writer.WriteUnmanaged(decimal.MaxValue); +#if NET8_0_OR_GREATER writer.WriteUnmanaged(IntPtr.MinValue); writer.WriteUnmanaged(IntPtr.MaxValue); writer.WriteUnmanaged(UIntPtr.MinValue); writer.WriteUnmanaged(UIntPtr.MaxValue); +#endif writer.WriteUnmanaged(DateTime.MinValue); writer.WriteUnmanaged(DateTime.MaxValue); writer.WriteUnmanaged(DateTimeOffset.MinValue); writer.WriteUnmanaged(DateTimeOffset.MaxValue); writer.WriteUnmanaged(TimeSpan.MinValue); writer.WriteUnmanaged(TimeSpan.MaxValue); +#if NET8_0_OR_GREATER writer.WriteUnmanaged(DateOnly.MinValue); writer.WriteUnmanaged(DateOnly.MaxValue); writer.WriteUnmanaged(TimeOnly.MinValue); writer.WriteUnmanaged(TimeOnly.MaxValue); +#endif writer.WriteUnmanaged(Matrix3x2.Identity); writer.WriteUnmanaged(Matrix4x4.Identity); writer.WriteUnmanaged(Quaternion.Identity); @@ -81,10 +87,12 @@ public void UnmangedTest() Assert.Equal(long.MaxValue, reader.ReadUnmanaged()); Assert.Equal(ulong.MinValue, reader.ReadUnmanaged()); Assert.Equal(ulong.MaxValue, reader.ReadUnmanaged()); +#if NET8_0_OR_GREATER Assert.Equal(Int128.MinValue, reader.ReadUnmanaged()); Assert.Equal(Int128.MaxValue, reader.ReadUnmanaged()); Assert.Equal(UInt128.MinValue, reader.ReadUnmanaged()); Assert.Equal(UInt128.MaxValue, reader.ReadUnmanaged()); +#endif Assert.Equal(char.MinValue, reader.ReadUnmanaged()); Assert.Equal(char.MaxValue, reader.ReadUnmanaged()); Assert.Equal(float.MinValue, reader.ReadUnmanaged()); @@ -93,20 +101,24 @@ public void UnmangedTest() Assert.Equal(double.MaxValue, reader.ReadUnmanaged()); Assert.Equal(decimal.MinValue, reader.ReadUnmanaged()); Assert.Equal(decimal.MaxValue, reader.ReadUnmanaged()); +#if NET8_0_OR_GREATER Assert.Equal(IntPtr.MinValue, reader.ReadUnmanaged()); Assert.Equal(IntPtr.MaxValue, reader.ReadUnmanaged()); Assert.Equal(UIntPtr.MinValue, reader.ReadUnmanaged()); Assert.Equal(UIntPtr.MaxValue, reader.ReadUnmanaged()); +#endif Assert.Equal(DateTime.MinValue, reader.ReadUnmanaged()); Assert.Equal(DateTime.MaxValue, reader.ReadUnmanaged()); Assert.Equal(DateTimeOffset.MinValue, reader.ReadUnmanaged()); Assert.Equal(DateTimeOffset.MaxValue, reader.ReadUnmanaged()); Assert.Equal(TimeSpan.MinValue, reader.ReadUnmanaged()); Assert.Equal(TimeSpan.MaxValue, reader.ReadUnmanaged()); +#if NET8_0_OR_GREATER Assert.Equal(DateOnly.MinValue, reader.ReadUnmanaged()); Assert.Equal(DateOnly.MaxValue, reader.ReadUnmanaged()); Assert.Equal(TimeOnly.MinValue, reader.ReadUnmanaged()); Assert.Equal(TimeOnly.MaxValue, reader.ReadUnmanaged()); +#endif Assert.Equal(Matrix3x2.Identity, reader.ReadUnmanaged()); Assert.Equal(Matrix4x4.Identity, reader.ReadUnmanaged()); Assert.Equal(Quaternion.Identity, reader.ReadUnmanaged()); @@ -140,10 +152,12 @@ public void UnmangedNullableTest() writer.WriteUnmanagedNullable(long.MaxValue); writer.WriteUnmanagedNullable(ulong.MinValue); writer.WriteUnmanagedNullable(ulong.MaxValue); +#if NET8_0_OR_GREATER writer.WriteUnmanagedNullable(Int128.MinValue); writer.WriteUnmanagedNullable(Int128.MaxValue); writer.WriteUnmanagedNullable(UInt128.MinValue); writer.WriteUnmanagedNullable(UInt128.MaxValue); +#endif writer.WriteUnmanagedNullable(char.MinValue); writer.WriteUnmanagedNullable(char.MaxValue); writer.WriteUnmanagedNullable(float.MinValue); @@ -152,20 +166,24 @@ public void UnmangedNullableTest() writer.WriteUnmanagedNullable(double.MaxValue); writer.WriteUnmanagedNullable(decimal.MinValue); writer.WriteUnmanagedNullable(decimal.MaxValue); +#if NET8_0_OR_GREATER writer.WriteUnmanagedNullable(IntPtr.MinValue); writer.WriteUnmanagedNullable(IntPtr.MaxValue); writer.WriteUnmanagedNullable(UIntPtr.MinValue); writer.WriteUnmanagedNullable(UIntPtr.MaxValue); +#endif writer.WriteUnmanagedNullable(DateTime.MinValue); writer.WriteUnmanagedNullable(DateTime.MaxValue); writer.WriteUnmanagedNullable(DateTimeOffset.MinValue); writer.WriteUnmanagedNullable(DateTimeOffset.MaxValue); writer.WriteUnmanagedNullable(TimeSpan.MinValue); writer.WriteUnmanagedNullable(TimeSpan.MaxValue); +#if NET8_0_OR_GREATER writer.WriteUnmanagedNullable(DateOnly.MinValue); writer.WriteUnmanagedNullable(DateOnly.MaxValue); writer.WriteUnmanagedNullable(TimeOnly.MinValue); writer.WriteUnmanagedNullable(TimeOnly.MaxValue); +#endif writer.WriteUnmanagedNullable(Matrix3x2.Identity); writer.WriteUnmanagedNullable(Matrix4x4.Identity); writer.WriteUnmanagedNullable(Quaternion.Identity); @@ -195,10 +213,12 @@ public void UnmangedNullableTest() Assert.Equal(long.MaxValue, reader.ReadUnmanagedNullable()); Assert.Equal(ulong.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(ulong.MaxValue, reader.ReadUnmanagedNullable()); +#if NET8_0_OR_GREATER Assert.Equal(Int128.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(Int128.MaxValue, reader.ReadUnmanagedNullable()); Assert.Equal(UInt128.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(UInt128.MaxValue, reader.ReadUnmanagedNullable()); +#endif Assert.Equal(char.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(char.MaxValue, reader.ReadUnmanagedNullable()); Assert.Equal(float.MinValue, reader.ReadUnmanagedNullable()); @@ -207,20 +227,24 @@ public void UnmangedNullableTest() Assert.Equal(double.MaxValue, reader.ReadUnmanagedNullable()); Assert.Equal(decimal.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(decimal.MaxValue, reader.ReadUnmanagedNullable()); +#if NET8_0_OR_GREATER Assert.Equal(IntPtr.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(IntPtr.MaxValue, reader.ReadUnmanagedNullable()); Assert.Equal(UIntPtr.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(UIntPtr.MaxValue, reader.ReadUnmanagedNullable()); +#endif Assert.Equal(DateTime.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(DateTime.MaxValue, reader.ReadUnmanagedNullable()); Assert.Equal(DateTimeOffset.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(DateTimeOffset.MaxValue, reader.ReadUnmanagedNullable()); Assert.Equal(TimeSpan.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(TimeSpan.MaxValue, reader.ReadUnmanagedNullable()); +#if NET8_0_OR_GREATER Assert.Equal(DateOnly.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(DateOnly.MaxValue, reader.ReadUnmanagedNullable()); Assert.Equal(TimeOnly.MinValue, reader.ReadUnmanagedNullable()); Assert.Equal(TimeOnly.MaxValue, reader.ReadUnmanagedNullable()); +#endif Assert.Equal(Matrix3x2.Identity, reader.ReadUnmanagedNullable()); Assert.Equal(Matrix4x4.Identity, reader.ReadUnmanagedNullable()); Assert.Equal(Quaternion.Identity, reader.ReadUnmanagedNullable()); diff --git a/EIV_Pack/EIV_Pack.csproj b/EIV_Pack/EIV_Pack.csproj index 62da230..a67fca3 100644 --- a/EIV_Pack/EIV_Pack.csproj +++ b/EIV_Pack/EIV_Pack.csproj @@ -1,7 +1,7 @@  - net10.0 + net10.0;net8.0;netstandard2.0 enable enable Serialization for EIV @@ -12,8 +12,8 @@ https://github.com/ExtractIntoVoid/EIV_Pack README.md LICENSE.txt - 2.1 - 2.1 + 2.2 + 2.2 latest true diff --git a/EIV_Pack/FormatterProvider.cs b/EIV_Pack/FormatterProvider.cs index 26e5156..7eaadf7 100644 --- a/EIV_Pack/FormatterProvider.cs +++ b/EIV_Pack/FormatterProvider.cs @@ -1,6 +1,8 @@ using EIV_Pack.Formatters; using System.Numerics; +#if NET8_0_OR_GREATER using System.Text; +#endif namespace EIV_Pack; @@ -41,7 +43,9 @@ public static void Register(IFormatter formatter) /// Type to register. public static void Register() where T : IFormatterRegister { +#if NET8_0_OR_GREATER T.RegisterFormatter(); +#endif } /// @@ -61,7 +65,7 @@ public static IFormatter GetFormatter() if (formatter == null) PackException.ThrowNotRegisteredInProvider(typeof(T)); - return formatter; + return formatter!; } private static void RegisterFormatters() @@ -74,8 +78,10 @@ private static void RegisterFormatters() RegisterToAll(); RegisterToAll(); RegisterToAll(); +#if NET8_0_OR_GREATER RegisterToAll(); RegisterToAll(); +#endif RegisterToAll(); RegisterToAll(); RegisterToAll(); @@ -83,13 +89,17 @@ private static void RegisterFormatters() RegisterToAll(); RegisterToAll(); RegisterToAll(); +#if NET8_0_OR_GREATER RegisterToAll(); +#endif RegisterToAll(); RegisterToAll(); RegisterToAll(); RegisterToAll(); +#if NET8_0_OR_GREATER RegisterToAll(); RegisterToAll(); +#endif RegisterToAll(); RegisterToAll(); RegisterToAll(); diff --git a/EIV_Pack/Formatters/ArrayFormatters.cs b/EIV_Pack/Formatters/ArrayFormatters.cs index eb80fd9..a6b5910 100644 --- a/EIV_Pack/Formatters/ArrayFormatters.cs +++ b/EIV_Pack/Formatters/ArrayFormatters.cs @@ -23,7 +23,11 @@ public void Serialize(ref PackWriter writer, scoped ref readonly ArraySegment value) { T?[] array = reader.ReadArray()!; +#if NET8_0_OR_GREATER value = (ArraySegment)array; +#else + value = new ArraySegment(array); +#endif } } diff --git a/EIV_Pack/Formatters/CollectionFormatters.cs b/EIV_Pack/Formatters/CollectionFormatters.cs index ba47ded..5f778de 100644 --- a/EIV_Pack/Formatters/CollectionFormatters.cs +++ b/EIV_Pack/Formatters/CollectionFormatters.cs @@ -119,7 +119,11 @@ public HashSetFormatter() public override HashSet CreateCollection(int length) { +#if NET8_0_OR_GREATER return new(length, equalityComparer); +#else + return new(equalityComparer); +#endif } } @@ -148,7 +152,9 @@ public class QueueFormatter : ICollectionFormatter> public override void Clear(scoped ref Queue collection, int length) { collection.Clear(); +#if NET8_0_OR_GREATER collection.EnsureCapacity(length); +#endif } public override void Add(scoped ref Queue collection, T? value) @@ -177,7 +183,9 @@ public override void Add(scoped ref Stack collection, T? value) public override void Clear(scoped ref Stack collection, int length) { collection.Clear(); +#if NET8_0_OR_GREATER collection.EnsureCapacity(length); +#endif } public override T? GetValue(scoped ref readonly Stack collection, int index) diff --git a/EIV_Pack/Formatters/DictionaryFormatters.cs b/EIV_Pack/Formatters/DictionaryFormatters.cs index 10f878a..14162a7 100644 --- a/EIV_Pack/Formatters/DictionaryFormatters.cs +++ b/EIV_Pack/Formatters/DictionaryFormatters.cs @@ -45,7 +45,14 @@ public void Serialize(ref PackWriter writer, scoped ref readonly TDictionary? di var valueformatter = FormatterProvider.GetFormatter(); foreach (var item in dictionary) { + +#if NET8_0_OR_GREATER item.Deconstruct(out var key, out var value); +#else + var key = item.Key; + var value = item.Value; +#endif + keyformatter.Serialize(ref writer, ref key); valueformatter.Serialize(ref writer, ref value); } diff --git a/EIV_Pack/Formatters/IFormatter.cs b/EIV_Pack/Formatters/IFormatter.cs index 1363da1..6dc86bc 100644 --- a/EIV_Pack/Formatters/IFormatter.cs +++ b/EIV_Pack/Formatters/IFormatter.cs @@ -2,7 +2,9 @@ public interface IFormatterRegister { +#if NET8_0_OR_GREATER static abstract void RegisterFormatter(); +#endif } public interface IFormatter @@ -14,8 +16,9 @@ public interface IFormatter public interface IPackable : IFormatterRegister { +#if NET8_0_OR_GREATER static abstract void SerializePackable(ref PackWriter writer, scoped ref readonly T? value); static abstract void DeserializePackable(ref PackReader reader, scoped ref T? value); - +#endif } \ No newline at end of file diff --git a/EIV_Pack/Formatters/LazyFormatter.cs b/EIV_Pack/Formatters/LazyFormatter.cs index 30e5827..597aed9 100644 --- a/EIV_Pack/Formatters/LazyFormatter.cs +++ b/EIV_Pack/Formatters/LazyFormatter.cs @@ -1,8 +1,14 @@ -using System.Diagnostics.CodeAnalysis; +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif namespace EIV_Pack.Formatters; -public sealed class LazyFormatter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] T> : IFormatter> +public sealed class LazyFormatter< +#if NET8_0_OR_GREATER + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] +#endif + T> : IFormatter> { public void Deserialize(ref PackReader reader, scoped ref Lazy? value) { @@ -13,7 +19,7 @@ public void Deserialize(ref PackReader reader, scoped ref Lazy? value) } T? v = reader.ReadValue(); - value = new Lazy(v); + value = new Lazy(() => v); } public void Serialize(ref PackWriter writer, scoped ref readonly Lazy? value) diff --git a/EIV_Pack/PackException.cs b/EIV_Pack/PackException.cs index ff6fb80..3454de4 100644 --- a/EIV_Pack/PackException.cs +++ b/EIV_Pack/PackException.cs @@ -1,28 +1,38 @@ -using System.Diagnostics.CodeAnalysis; +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif namespace EIV_Pack; public class PackException(string message) : Exception(message) { +#if NET8_0_OR_GREATER [DoesNotReturn] +#endif public static void ThrowMessage(string message) { throw new PackException(message); } +#if NET8_0_OR_GREATER [DoesNotReturn] +#endif public static void ThrowNotRegisteredInProvider(Type type) { throw new PackException($"{type.FullName} is not registered in this provider."); } +#if NET8_0_OR_GREATER [DoesNotReturn] +#endif public static void ThrowReachedDepthLimit(Type type) { throw new PackException($"Serializing Type '{type}' reached depth limit, maybe detect circular reference."); } +#if NET8_0_OR_GREATER [DoesNotReturn] +#endif public static void ThrowHeaderNotSame(Type type, int expected, int actual) { throw new PackException($"{type.FullName} is failed to deserialize! Expected Header: {expected} actual: {actual}."); diff --git a/EIV_Pack/PackReader.cs b/EIV_Pack/PackReader.cs index d16aa34..f794c2a 100644 --- a/EIV_Pack/PackReader.cs +++ b/EIV_Pack/PackReader.cs @@ -18,7 +18,7 @@ public ref struct PackReader public PackReader(in ReadOnlySequence sequence) { bufferSource = sequence; - currentBuffer = sequence.FirstSpan; + currentBuffer = sequence.First.Span; Length = sequence.Length; TextEncoding = Encoding.UTF8; } @@ -41,7 +41,7 @@ public void Advance(int count) throw new InvalidOperationException("Remaining bytes cannot read this type!"); } - currentBuffer = bufferSource.Slice(Consumed + count, Remaining - count).FirstSpan; + currentBuffer = bufferSource.Slice(Consumed + count, Remaining - count).First.Span; Consumed += count; } @@ -55,7 +55,12 @@ public T ReadUnmanaged() where T : unmanaged throw new InvalidOperationException("Remaining bytes cannot read this type!"); } +#if NET8_0_OR_GREATER T value = MemoryMarshal.Read(currentBuffer[..size]); +#else + T value = MemoryMarshal.Read(currentBuffer.Slice(0, size)); +#endif + Advance(size); return value; } @@ -82,7 +87,12 @@ public readonly bool TryPeekUnmanaged(out T value) where T : unmanaged return false; } +#if NET8_0_OR_GREATER var buffer = currentBuffer[..size]; +#else + var buffer = currentBuffer.Slice(0, size); +#endif + value = MemoryMarshal.Read(buffer); return true; } @@ -134,7 +144,12 @@ public readonly bool PeekIsNullOrEmpty() if (len == 0) return string.Empty; +#if NET8_0_OR_GREATER string str = TextEncoding.GetString(currentBuffer[..len]); +#else + string str = TextEncoding.GetString(currentBuffer.Slice(0, len).ToArray()); +#endif + Advance(len); return str; } @@ -143,7 +158,12 @@ public readonly bool PeekIsNullOrEmpty() public void ReadPackable(scoped ref T? value) where T : IPackable { +#if NET8_0_OR_GREATER T.DeserializePackable(ref this, ref value); +#else + ReadValue(ref value); +#endif + } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -151,7 +171,11 @@ public void ReadPackable(scoped ref T? value) where T : IPackable { T? value = default; +#if NET8_0_OR_GREATER T.DeserializePackable(ref this, ref value); +#else + ReadValue(ref value); +#endif return value; } @@ -211,7 +235,7 @@ public void ReadArray(scoped ref T?[]? value) value = new T[length]; } - var formatter = FormatterProvider.GetFormatter(); + var formatter = FormatterProvider.GetFormatter(); for (int i = 0; i < length; i++) { formatter.Deserialize(ref this, ref value[i]); diff --git a/EIV_Pack/PackWriter.FormatterWrite.cs b/EIV_Pack/PackWriter.FormatterWrite.cs index bb16c14..87ed25f 100644 --- a/EIV_Pack/PackWriter.FormatterWrite.cs +++ b/EIV_Pack/PackWriter.FormatterWrite.cs @@ -13,7 +13,13 @@ public void WritePackable(scoped in T? value) if (depth == DepthLimit) PackException.ThrowReachedDepthLimit(typeof(T)); +#if NET8_0_OR_GREATER T.SerializePackable(ref this, ref Unsafe.AsRef(in value)); +#else + var formatter = FormatterProvider.GetFormatter(); + formatter.Serialize(ref this, ref Unsafe.AsRef(in value)); +#endif + depth--; } diff --git a/EIV_Pack/PackWriter.Retrieve.cs b/EIV_Pack/PackWriter.Retrieve.cs index 0ccb3fa..3062b59 100644 --- a/EIV_Pack/PackWriter.Retrieve.cs +++ b/EIV_Pack/PackWriter.Retrieve.cs @@ -17,6 +17,11 @@ public readonly ArraySegment GetAsSegment() public readonly byte[] GetBytes() { - return recyclable.GetBuffer()[..(int)recyclable.Length]; + int len = (int)recyclable.Length; +#if NET8_0_OR_GREATER + return recyclable.GetBuffer()[..len]; +#else + return [.. recyclable.GetBuffer().Take(len)]; +#endif } } diff --git a/EIV_Pack/PackWriter.Writers.cs b/EIV_Pack/PackWriter.Writers.cs index 4066fa6..866c4d1 100644 --- a/EIV_Pack/PackWriter.Writers.cs +++ b/EIV_Pack/PackWriter.Writers.cs @@ -9,11 +9,16 @@ public readonly unsafe void WriteUnmanaged(scoped in T value) where T : unman { int size = sizeof(T); Span span = recyclable.GetSpan(size); +#if NET8_0_OR_GREATER MemoryMarshal.Write(span, value); +#else + T val = value; + MemoryMarshal.Write(span, ref val); +#endif recyclable.Advance(size); } - public readonly unsafe void WriteUnmanagedNullable(scoped in T? value) where T : unmanaged + public readonly void WriteUnmanagedNullable(scoped in T? value) where T : unmanaged { WriteUnmanaged(value.HasValue); diff --git a/EIV_Pack/Serializer.cs b/EIV_Pack/Serializer.cs index 8e89d53..979dc8e 100644 --- a/EIV_Pack/Serializer.cs +++ b/EIV_Pack/Serializer.cs @@ -25,7 +25,13 @@ public static ArraySegment SerializeArray_Segment(in T?[]? value) return []; if (value.Length == 0) + { +#if NET8_0_OR_GREATER return Constants.EmptyCollection.ToArray(); +#else + return new ArraySegment(Constants.EmptyCollection.ToArray()); +#endif + } using PackWriter writer = new(); writer.WriteArray(value); @@ -78,7 +84,7 @@ public static ReadOnlySequence SerializeArray_Sequence(in T?[]? value) if (bytes.Length == 0) return null; - if (Constants.EmptyCollection.SequenceEqual(bytes.FirstSpan)) + if (Constants.EmptyCollection.SequenceEqual(bytes.First.Span)) return []; PackReader reader = new(bytes); From 41b4bf5a6f3a0c5dbb0de9e4cf4e512f420e44ed Mon Sep 17 00:00:00 2001 From: SlejmUr Date: Tue, 24 Feb 2026 21:52:08 +0100 Subject: [PATCH 2/4] Update Generator to 2.2 removed debug for ArrayFormatter --- EIV_Pack.Generator/EIV_Pack.Generator.csproj | 4 ++-- EIV_Pack.Test/ArrayFormatterTests.cs | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/EIV_Pack.Generator/EIV_Pack.Generator.csproj b/EIV_Pack.Generator/EIV_Pack.Generator.csproj index 387bfb2..ef5c1ea 100644 --- a/EIV_Pack.Generator/EIV_Pack.Generator.csproj +++ b/EIV_Pack.Generator/EIV_Pack.Generator.csproj @@ -19,8 +19,8 @@ true Code generator for EIVPack. - 2.1.2 - 2.1.2 + 2.2 + 2.2 diff --git a/EIV_Pack.Test/ArrayFormatterTests.cs b/EIV_Pack.Test/ArrayFormatterTests.cs index deb7811..80aaa86 100644 --- a/EIV_Pack.Test/ArrayFormatterTests.cs +++ b/EIV_Pack.Test/ArrayFormatterTests.cs @@ -6,13 +6,6 @@ namespace EIV_Pack.Test; public class ArrayFormatterTests { - private readonly ITestOutputHelper output; - - public ArrayFormatterTests(ITestOutputHelper output) - { - this.output = output; - } - [Fact] public void ArrayTest() { @@ -23,7 +16,6 @@ public void ArrayTest() writer.WriteValueWithFormatter(intArrayFormatter, ints); var bytes = writer.GetBytes(); Assert.NotEmpty(bytes); - output.WriteLine(BitConverter.ToString(bytes)); PackReader reader = new(bytes); Assert.Equal(ints, reader.ReadValueWithFormatter(intArrayFormatter)); Assert.Equal(0, reader.Remaining); From a124e2b66108c7b4a2d5947ee98c1c9ffbc76386 Mon Sep 17 00:00:00 2001 From: SlejmUr Date: Tue, 24 Feb 2026 23:11:33 +0100 Subject: [PATCH 3/4] Removing var keywords --- EIV_Pack/Formatters/CollectionFormatters.cs | 8 ++++---- EIV_Pack/Formatters/DictionaryFormatters.cs | 8 ++++---- EIV_Pack/PackReader.cs | 9 +++++---- EIV_Pack/PackWriter.FormatterWrite.cs | 4 ++-- EIV_Pack/PackWriter.Writers.cs | 11 ++++++----- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/EIV_Pack/Formatters/CollectionFormatters.cs b/EIV_Pack/Formatters/CollectionFormatters.cs index 5f778de..b92dd48 100644 --- a/EIV_Pack/Formatters/CollectionFormatters.cs +++ b/EIV_Pack/Formatters/CollectionFormatters.cs @@ -26,7 +26,7 @@ public void Deserialize(ref PackReader reader, scoped ref TCollection? value) else Clear(ref value, len); - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); for (int i = 0; i < len; i++) { T? val = default; @@ -44,7 +44,7 @@ public void Serialize(ref PackWriter writer, scoped ref readonly TCollection? co } writer.WriteHeader(collection.Count); - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); for (int i = 0; i < collection.Count; i++) { T? val = GetValue(in collection, i); @@ -73,7 +73,7 @@ public void Deserialize(ref PackReader reader, scoped ref TCollection? value) else value.Clear(); - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); for (int i = 0; i < len; i++) { T? val = default; @@ -91,7 +91,7 @@ public void Serialize(ref PackWriter writer, scoped ref readonly TCollection? va } writer.WriteHeader(value.Count); - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); foreach (var item in value) { var val = item; diff --git a/EIV_Pack/Formatters/DictionaryFormatters.cs b/EIV_Pack/Formatters/DictionaryFormatters.cs index 14162a7..e8749ee 100644 --- a/EIV_Pack/Formatters/DictionaryFormatters.cs +++ b/EIV_Pack/Formatters/DictionaryFormatters.cs @@ -20,8 +20,8 @@ public void Deserialize(ref PackReader reader, scoped ref TDictionary? value) else value.Clear(); - var keyformatter = FormatterProvider.GetFormatter(); - var valueformatter = FormatterProvider.GetFormatter(); + IFormatter keyformatter = FormatterProvider.GetFormatter(); + IFormatter valueformatter = FormatterProvider.GetFormatter(); for (int i = 0; i < len; i++) { TKey? key = default; @@ -41,8 +41,8 @@ public void Serialize(ref PackWriter writer, scoped ref readonly TDictionary? di } writer.WriteHeader(dictionary.Count); - var keyformatter = FormatterProvider.GetFormatter(); - var valueformatter = FormatterProvider.GetFormatter(); + IFormatter keyformatter = FormatterProvider.GetFormatter(); + IFormatter valueformatter = FormatterProvider.GetFormatter(); foreach (var item in dictionary) { diff --git a/EIV_Pack/PackReader.cs b/EIV_Pack/PackReader.cs index f794c2a..bb70fd3 100644 --- a/EIV_Pack/PackReader.cs +++ b/EIV_Pack/PackReader.cs @@ -87,10 +87,11 @@ public readonly bool TryPeekUnmanaged(out T value) where T : unmanaged return false; } + ReadOnlySpan buffer = currentBuffer #if NET8_0_OR_GREATER - var buffer = currentBuffer[..size]; + [..size]; #else - var buffer = currentBuffer.Slice(0, size); + .Slice(0, size); #endif value = MemoryMarshal.Read(buffer); @@ -235,7 +236,7 @@ public void ReadArray(scoped ref T?[]? value) value = new T[length]; } - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); for (int i = 0; i < length; i++) { formatter.Deserialize(ref this, ref value[i]); @@ -256,7 +257,7 @@ public void ReadArray(scoped ref T?[]? value, int length) value = new T[length]; } - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); for (int i = 0; i < length; i++) { formatter.Deserialize(ref this, ref value[i]); diff --git a/EIV_Pack/PackWriter.FormatterWrite.cs b/EIV_Pack/PackWriter.FormatterWrite.cs index 87ed25f..d3fc1a1 100644 --- a/EIV_Pack/PackWriter.FormatterWrite.cs +++ b/EIV_Pack/PackWriter.FormatterWrite.cs @@ -16,7 +16,7 @@ public void WritePackable(scoped in T? value) #if NET8_0_OR_GREATER T.SerializePackable(ref this, ref Unsafe.AsRef(in value)); #else - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); formatter.Serialize(ref this, ref Unsafe.AsRef(in value)); #endif @@ -30,7 +30,7 @@ public void WriteValue(scoped in T? value) if (depth == DepthLimit) PackException.ThrowReachedDepthLimit(typeof(T)); - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); formatter.Serialize(ref this, ref Unsafe.AsRef(in value)); depth--; } diff --git a/EIV_Pack/PackWriter.Writers.cs b/EIV_Pack/PackWriter.Writers.cs index 866c4d1..40ea277 100644 --- a/EIV_Pack/PackWriter.Writers.cs +++ b/EIV_Pack/PackWriter.Writers.cs @@ -1,4 +1,5 @@ -using System.Runtime.CompilerServices; +using EIV_Pack.Formatters; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace EIV_Pack; @@ -51,7 +52,7 @@ public readonly void WriteString(string? value) } WriteHeader(value.Length); - var data = TextEncoding.GetBytes(value); + byte[] data = TextEncoding.GetBytes(value); recyclable.Write(data); } @@ -64,7 +65,7 @@ public void WriteArray(T?[]? array) } - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); WriteHeader(array.Length); for (int i = 0; i < array.Length; i++) @@ -75,7 +76,7 @@ public void WriteArray(T?[]? array) public void WriteSpan(scoped Span value, bool useHeader = true) { - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); if (useHeader) WriteHeader(value.Length); @@ -88,7 +89,7 @@ public void WriteSpan(scoped Span value, bool useHeader = true) public void WriteSpan(scoped ReadOnlySpan value, bool useHeader = true) { - var formatter = FormatterProvider.GetFormatter(); + IFormatter formatter = FormatterProvider.GetFormatter(); if (useHeader) WriteHeader(value.Length); From 257a0a82c23005a7232341c0105269e38f061f2f Mon Sep 17 00:00:00 2001 From: SlejmUr Date: Wed, 25 Feb 2026 10:42:38 +0100 Subject: [PATCH 4/4] Fix netstandard CustomTypeTest --- EIV_Pack.Test/ProviderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIV_Pack.Test/ProviderTests.cs b/EIV_Pack.Test/ProviderTests.cs index 3a4bce3..9400977 100644 --- a/EIV_Pack.Test/ProviderTests.cs +++ b/EIV_Pack.Test/ProviderTests.cs @@ -26,7 +26,7 @@ public void CustomTypeTest() Value = "sdfsf" }; - FormatterProvider.Register(); + CustomType.RegisterFormatter(); var bytes = Serializer.Serialize(customType); Assert.NotEmpty(bytes);