From 7dbc666493f91e282ad0518e786d6e4c3ebe07bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sat, 18 Feb 2023 11:46:14 +0100 Subject: [PATCH] feat: use stackalloc and Span for packet serialization --- Core/NosSmooth.Core/NosSmooth.Core.csproj | 2 +- .../BaseStringConverter.cs | 6 +- .../IStringConverter.cs | 4 +- .../IStringSerializer.cs | 4 +- ...mooth.PacketSerializer.Abstractions.csproj | 2 +- .../PacketStringBuilder.cs | 131 +++++++++--------- .../Converters/Basic/BasicTypeConverter.cs | 2 +- .../Converters/Basic/BoolStringConverter.cs | 2 +- .../Converters/Basic/ByteStringConverter.cs | 2 +- .../Converters/Basic/IntStringConverter.cs | 2 +- .../Converters/Basic/LongStringConverter.cs | 2 +- .../Converters/Basic/ShortStringConverter.cs | 2 +- .../Basic/SpanFormattableTypeConverter.cs | 34 +++++ .../Converters/Basic/UIntStringConverter.cs | 2 +- .../Converters/Basic/ULongStringConverter.cs | 2 +- .../Converters/Basic/UShortStringConverter.cs | 2 +- .../Converters/Common/NameStringConverter.cs | 2 +- .../Common/NullableWrapperConverter.cs | 4 +- .../Common/OptionalWrapperConverter.cs | 4 +- .../Packets/UpgradeRareSubPacketConverter.cs | 2 +- .../Special/Converters/EnumStringConverter.cs | 2 +- .../Special/Converters/ListStringConverter.cs | 4 +- .../Converters/NullableStringConverter.cs | 4 +- .../Converters/Special/StringSerializer.cs | 8 +- .../NosSmooth.PacketSerializer.csproj | 2 +- .../PacketSerializer.cs | 4 +- .../FallbackInlineConverterGenerator.cs | 2 +- .../PacketConverterGenerator.cs | 2 +- .../NosSmooth.Packets.csproj | 2 +- .../Basic/BoolStringConverterTests.cs | 4 +- .../Converters/Basic/StringConverterTests.cs | 4 +- .../PacketStringBuilderTests.cs | 4 +- 32 files changed, 145 insertions(+), 110 deletions(-) create mode 100644 Packets/NosSmooth.PacketSerializer/Converters/Basic/SpanFormattableTypeConverter.cs diff --git a/Core/NosSmooth.Core/NosSmooth.Core.csproj b/Core/NosSmooth.Core/NosSmooth.Core.csproj index 40ef2b6e6f30870df6d70eb3427df56ea00157a2..aba22a1151d116e1da5c20cf04c29f524b69f3a3 100644 --- a/Core/NosSmooth.Core/NosSmooth.Core.csproj +++ b/Core/NosSmooth.Core/NosSmooth.Core.csproj @@ -3,11 +3,11 @@ enable 10 - net7.0;netstandard2.1 Rutherther NosSmooth Core library allowing implementing nostale client, handling packets and commands. 5.0.0 Move PetWalkCommand to MateWalkCommand. + net7.0 diff --git a/Packets/NosSmooth.PacketSerializer.Abstractions/BaseStringConverter.cs b/Packets/NosSmooth.PacketSerializer.Abstractions/BaseStringConverter.cs index f1c8ef929dcc89aaeb2739cdb3c57f311094beb8..94a98e787c8faaf98f5d33a843674c576bfcae88 100644 --- a/Packets/NosSmooth.PacketSerializer.Abstractions/BaseStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer.Abstractions/BaseStringConverter.cs @@ -16,7 +16,7 @@ namespace NosSmooth.PacketSerializer.Abstractions; public abstract class BaseStringConverter : IStringConverter { /// - public abstract Result Serialize(TParseType? obj, PacketStringBuilder builder); + public abstract Result Serialize(TParseType? obj, ref PacketStringBuilder builder); /// public abstract Result Deserialize(ref PacketStringEnumerator stringEnumerator, DeserializeOptions options); @@ -34,13 +34,13 @@ public abstract class BaseStringConverter : IStringConverter - Result IStringConverter.Serialize(object? obj, PacketStringBuilder builder) + Result IStringConverter.Serialize(object? obj, ref PacketStringBuilder builder) { if (!(obj is TParseType parseType)) { return new WrongTypeError(this, typeof(TParseType), obj); } - return Serialize(parseType, builder); + return Serialize(parseType, ref builder); } } diff --git a/Packets/NosSmooth.PacketSerializer.Abstractions/IStringConverter.cs b/Packets/NosSmooth.PacketSerializer.Abstractions/IStringConverter.cs index 3c4d6e935776537dc76b2b3af666145b97bcd286..584ee9d2193130eadee3cdee43dea9f2a5e72538 100644 --- a/Packets/NosSmooth.PacketSerializer.Abstractions/IStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer.Abstractions/IStringConverter.cs @@ -27,7 +27,7 @@ public interface IStringConverter /// The object to serialize. /// The string builder to append to. /// A result that may or may not have succeeded. - public Result Serialize(object? obj, PacketStringBuilder builder); + public Result Serialize(object? obj, ref PacketStringBuilder builder); } /// @@ -53,5 +53,5 @@ public interface IStringConverter : IStringConverter /// The object to serialize. /// The string builder to append to. /// A result that may or may not have succeeded. - public Result Serialize(TParseType? obj, PacketStringBuilder builder); + public Result Serialize(TParseType? obj, ref PacketStringBuilder builder); } \ No newline at end of file diff --git a/Packets/NosSmooth.PacketSerializer.Abstractions/IStringSerializer.cs b/Packets/NosSmooth.PacketSerializer.Abstractions/IStringSerializer.cs index 501d1fd1a9a56ca31873b080313d9f5bddfd8b0c..99a1741cf8590ea41bb5f009d099792b0630687f 100644 --- a/Packets/NosSmooth.PacketSerializer.Abstractions/IStringSerializer.cs +++ b/Packets/NosSmooth.PacketSerializer.Abstractions/IStringSerializer.cs @@ -29,7 +29,7 @@ public interface IStringSerializer /// The object to serialize. /// The string builder to append to. /// A result that may or may not have succeeded. - public Result Serialize(Type parseType, object? obj, PacketStringBuilder builder); + public Result Serialize(Type parseType, object? obj, ref PacketStringBuilder builder); /// /// Convert the data from the enumerator to the given type. @@ -47,5 +47,5 @@ public interface IStringSerializer /// The string builder to append to. /// The type of the object to deserialize. /// A result that may or may not have succeeded. - public Result Serialize(TParseType? obj, PacketStringBuilder builder); + public Result Serialize(TParseType? obj, ref PacketStringBuilder builder); } \ No newline at end of file diff --git a/Packets/NosSmooth.PacketSerializer.Abstractions/NosSmooth.PacketSerializer.Abstractions.csproj b/Packets/NosSmooth.PacketSerializer.Abstractions/NosSmooth.PacketSerializer.Abstractions.csproj index ea78bf9a7ad922103b39958503eaf9c9335621a5..7dcb3b99f62295ccd6f07a0f82a559597db561af 100644 --- a/Packets/NosSmooth.PacketSerializer.Abstractions/NosSmooth.PacketSerializer.Abstractions.csproj +++ b/Packets/NosSmooth.PacketSerializer.Abstractions/NosSmooth.PacketSerializer.Abstractions.csproj @@ -6,8 +6,8 @@ 10 NosSmooth's packet serializer abstractions that hold all interfaces, classes, errors needed for creating assemblies with packets that can have generated serializers. 1.3.2 - net7.0;netstandard2.1 Accept ReadOnlySpan in PacketStringEnumerator. + net7.0 diff --git a/Packets/NosSmooth.PacketSerializer.Abstractions/PacketStringBuilder.cs b/Packets/NosSmooth.PacketSerializer.Abstractions/PacketStringBuilder.cs index 95131c49a64ccbeabadb0272ca1412cfc93c6100..1ee285c98c75d63abcbd5e5255d07961e143db23 100644 --- a/Packets/NosSmooth.PacketSerializer.Abstractions/PacketStringBuilder.cs +++ b/Packets/NosSmooth.PacketSerializer.Abstractions/PacketStringBuilder.cs @@ -4,6 +4,7 @@ // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Buffers; using System.Text; using Remora.Results; @@ -12,21 +13,24 @@ namespace NosSmooth.PacketSerializer.Abstractions; /// /// String builder for packets. /// -public class PacketStringBuilder +public ref struct PacketStringBuilder { - private readonly StringBuilder _builder; + private Span _buffer; + private int _position; private StringBuilderLevel _currentLevel; private char? _insertSeparator; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the struct. /// + /// The initial buffer to store the packet to. Will grow in size if needed. /// The top level separator. - public PacketStringBuilder(char separator = ' ') + public PacketStringBuilder(Span initialBuffer, char separator = ' ') { _currentLevel = new StringBuilderLevel(null, separator); _insertSeparator = null; - _builder = new StringBuilder(); + _buffer = initialBuffer; + _position = 0; } /// @@ -113,153 +117,150 @@ public class PacketStringBuilder } /// - /// Appends the value to the string. + /// Appends a value that is span formattable. /// /// The value to append. - public void Append(string value) + /// The span formattable type. + public void Append(T value) + where T : ISpanFormattable { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); + AppendSpanFormattable(value); } /// /// Appends the value to the string. /// /// The value to append. - public void Append(int value) + public void Append(ReadOnlySpan value) { BeforeAppend(); - _builder.Append(value); + if (!value.TryCopyTo(_buffer.Slice(_position))) + { + GrowBuffer(value.Length); + } + _position += value.Length; AfterAppend(); } + /// + /// Appends the value to the string. + /// + /// The value to append. + public void Append(int value) + => AppendSpanFormattable(value); + /// /// Appends the value to the string. /// /// The value to append. public void Append(uint value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(short value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(char value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(ushort value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(long value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(ulong value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(byte value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(sbyte value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(float value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(double value) - { - BeforeAppend(); - _builder.Append(value); - AfterAppend(); - } + => AppendSpanFormattable(value); /// /// Appends the value to the string. /// /// The value to append. public void Append(decimal value) + => AppendSpanFormattable(value); + + private void AppendSpanFormattable(T value) + where T : ISpanFormattable { BeforeAppend(); - _builder.Append(value); + int charsWritten; + while (!value.TryFormat(_buffer.Slice(_position), out charsWritten, default, null)) + { + GrowBuffer(); + } + _position += charsWritten; AfterAppend(); } + private void GrowBuffer(int needed = 0) + { + var sizeNeeded = _buffer.Length + needed; + var doubleSize = _buffer.Length * 2; + var newSize = Math.Max(doubleSize, sizeNeeded); + var newBuffer = ArrayPool.Shared.Rent(newSize); + + _buffer.CopyTo(newBuffer); + _buffer = newBuffer; + } + private void BeforeAppend() { if (_insertSeparator is not null) { - _builder.Append(_insertSeparator); + if (_buffer.Length <= _position + 1) + { + GrowBuffer(); + } + + _buffer[_position] = _insertSeparator.Value; + _position += 1; _insertSeparator = null; } } @@ -288,7 +289,7 @@ public class PacketStringBuilder /// public override string ToString() { - return _builder.ToString(); + return _buffer.Slice(0, _position).ToString(); } private class StringBuilderLevel diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/BasicTypeConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/BasicTypeConverter.cs index 249faddf086654a0f97a03198e07888f4992953e..f0f182d9cc76bf09744d709bca29ffb537cac890 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Basic/BasicTypeConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/BasicTypeConverter.cs @@ -17,7 +17,7 @@ namespace NosSmooth.PacketSerializer.Converters.Basic; public abstract class BasicTypeConverter : BaseStringConverter { /// - public override Result Serialize(TBasicType? obj, PacketStringBuilder builder) + public override Result Serialize(TBasicType? obj, ref PacketStringBuilder builder) { builder.Append(obj?.ToString() ?? GetNullSymbol()); return Result.FromSuccess(); diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/BoolStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/BoolStringConverter.cs index e9c8cc0837ac12c0b2e7cdb570e313d0fac5ec8e..2ef932a0b48beeff585d69725a00e5b0a483ebe6 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Basic/BoolStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/BoolStringConverter.cs @@ -16,7 +16,7 @@ namespace NosSmooth.PacketSerializer.Converters.Basic; public class BoolStringConverter : BasicTypeConverter { /// - public override Result Serialize(bool obj, PacketStringBuilder builder) + public override Result Serialize(bool obj, ref PacketStringBuilder builder) { builder.Append(obj ? '1' : '0'); return Result.FromSuccess(); diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/ByteStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/ByteStringConverter.cs index aa42104ab3585b50e4ad928ee90138f6790c5076..abc2e3851f0d8da351d2b475905bc614f50ba449 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Basic/ByteStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/ByteStringConverter.cs @@ -13,7 +13,7 @@ namespace NosSmooth.PacketSerializer.Converters.Basic; /// /// Converter of . /// -public class ByteStringConverter : BasicTypeConverter +public class ByteStringConverter : SpanFormattableTypeConverter { /// protected override Result Deserialize(ReadOnlySpan value) diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/IntStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/IntStringConverter.cs index 7d328e4a4c67318cbc226472c6abd81732091ff1..973aec01ec4ba0f896b4b4f96f053ad006f66440 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Basic/IntStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/IntStringConverter.cs @@ -13,7 +13,7 @@ namespace NosSmooth.PacketSerializer.Converters.Basic; /// /// Converter of . /// -public class IntStringConverter : BasicTypeConverter +public class IntStringConverter : SpanFormattableTypeConverter { /// protected override Result Deserialize(ReadOnlySpan value) diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/LongStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/LongStringConverter.cs index 6bc5d1873f88128a1a2f2972d52b45632b310347..b2e5c871aff9da54fb80e70b3bd302cd73b19647 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Basic/LongStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/LongStringConverter.cs @@ -13,7 +13,7 @@ namespace NosSmooth.PacketSerializer.Converters.Basic; /// /// Converter of . /// -public class LongStringConverter : BasicTypeConverter +public class LongStringConverter : SpanFormattableTypeConverter { /// protected override Result Deserialize(ReadOnlySpan value) diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/ShortStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/ShortStringConverter.cs index 22865a6d81b093bdadbbe97e477abbfcae051226..8dd4d4541773ceddeeafbd7443f381535ae0ccc0 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Basic/ShortStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/ShortStringConverter.cs @@ -13,7 +13,7 @@ namespace NosSmooth.PacketSerializer.Converters.Basic; /// /// Converter of . /// -public class ShortStringConverter : BasicTypeConverter +public class ShortStringConverter : SpanFormattableTypeConverter { /// protected override Result Deserialize(ReadOnlySpan value) diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/SpanFormattableTypeConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/SpanFormattableTypeConverter.cs new file mode 100644 index 0000000000000000000000000000000000000000..8530330fafc906a21b306b8e7e233910cf2c187d --- /dev/null +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/SpanFormattableTypeConverter.cs @@ -0,0 +1,34 @@ +// +// SpanFormattableTypeConverter.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using NosSmooth.PacketSerializer.Abstractions; +using Remora.Results; + +namespace NosSmooth.PacketSerializer.Converters.Basic; + +/// +/// A converter for types such as int, long etc.. +/// +/// The span formattable type. +public abstract class SpanFormattableTypeConverter : BasicTypeConverter + where T : ISpanFormattable +{ + /// + public override Result Serialize(T? obj, ref PacketStringBuilder builder) + { + if (obj is not null) + { + builder.Append(obj); + } + else + { + builder.Append(GetNullSymbol()); + } + + return Result.FromSuccess(); + } +} \ No newline at end of file diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/UIntStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/UIntStringConverter.cs index 6f59521e75cebec8006ffdcef5c59bf3aa6ea8bc..1603058c05342ab7f5cf3250bf3cdc9221ca8559 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Basic/UIntStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/UIntStringConverter.cs @@ -13,7 +13,7 @@ namespace NosSmooth.PacketSerializer.Converters.Basic; /// /// Converter of . /// -public class UIntStringConverter : BasicTypeConverter +public class UIntStringConverter : SpanFormattableTypeConverter { /// protected override Result Deserialize(ReadOnlySpan value) diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/ULongStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/ULongStringConverter.cs index fbcb030701f7e644d5cf1949b3f22da9d9be12af..6ab2639a2d5983ee6a1e30e010a8b2a66c7bc9ad 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Basic/ULongStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/ULongStringConverter.cs @@ -13,7 +13,7 @@ namespace NosSmooth.PacketSerializer.Converters.Basic; /// /// Converter of . /// -public class ULongStringConverter : BasicTypeConverter +public class ULongStringConverter : SpanFormattableTypeConverter { /// protected override Result Deserialize(ReadOnlySpan value) diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Basic/UShortStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Basic/UShortStringConverter.cs index 8986929d7e83d55c901558623b3a891917487b36..e559f33a4bbf35ad1c9146280a23e7c475f54e73 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Basic/UShortStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Basic/UShortStringConverter.cs @@ -13,7 +13,7 @@ namespace NosSmooth.PacketSerializer.Converters.Basic; /// /// Converter of . /// -public class UShortStringConverter : BasicTypeConverter +public class UShortStringConverter : SpanFormattableTypeConverter { /// protected override Result Deserialize(ReadOnlySpan value) diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Common/NameStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Common/NameStringConverter.cs index a1f511f230650edbde13d08f1640d684d37aba6d..7941e8d72db6c57f8955e4cff7b608f706610f4f 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Common/NameStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Common/NameStringConverter.cs @@ -16,7 +16,7 @@ namespace NosSmooth.PacketSerializer.Converters.Common; public class NameStringConverter : BaseStringConverter { /// - public override Result Serialize(NameString? obj, PacketStringBuilder builder) + public override Result Serialize(NameString? obj, ref PacketStringBuilder builder) { if (obj is null) { diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Common/NullableWrapperConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Common/NullableWrapperConverter.cs index aa18184f8b207d648612f3ecd44cf57d07f1227f..e27adc7f66ab5825834c9d1fec43980b3987bd96 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Common/NullableWrapperConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Common/NullableWrapperConverter.cs @@ -28,7 +28,7 @@ public class NullableWrapperConverter : BaseStringConverter - public override Result Serialize(NullableWrapper obj, PacketStringBuilder builder) + public override Result Serialize(NullableWrapper obj, ref PacketStringBuilder builder) { if (obj.Value is null) { @@ -42,7 +42,7 @@ public class NullableWrapperConverter : BaseStringConverter : BaseStringConverter - public override Result Serialize(OptionalWrapper obj, PacketStringBuilder builder) + public override Result Serialize(OptionalWrapper obj, ref PacketStringBuilder builder) { if (obj.Value is null) { @@ -41,7 +41,7 @@ public class OptionalWrapperConverter : BaseStringConverter { /// - public override Result Serialize(UpgradeRareSubPacket? obj, PacketStringBuilder builder) + public override Result Serialize(UpgradeRareSubPacket? obj, ref PacketStringBuilder builder) { if (obj is null) { diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Special/Converters/EnumStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Special/Converters/EnumStringConverter.cs index b8d2453886ea4f0d34437c3fd4d4b0fc794f3bef..12ea7921034620e7cef92c438aa3ce78472d9a9a 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Special/Converters/EnumStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Special/Converters/EnumStringConverter.cs @@ -28,7 +28,7 @@ public class EnumStringConverter : BaseStringConverter - public override Result Serialize(TEnum? obj, PacketStringBuilder builder) + public override Result Serialize(TEnum? obj, ref PacketStringBuilder builder) { builder.Append(((TUnderlyingType?)(object?)obj)?.ToString() ?? "-"); return Result.FromSuccess(); diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Special/Converters/ListStringConverter.cs b/Packets/NosSmooth.PacketSerializer/Converters/Special/Converters/ListStringConverter.cs index 3ec3db7d1c07a79f5d6636a3d684ebce2847be91..96c2d25b5fb518b28ac83dc1fd7ba13d1eae26af 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Special/Converters/ListStringConverter.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Special/Converters/ListStringConverter.cs @@ -29,7 +29,7 @@ public class ListStringConverter : BaseStringConverter - public override Result Serialize(IReadOnlyList? obj, PacketStringBuilder builder) + public override Result Serialize(IReadOnlyList? obj, ref PacketStringBuilder builder) { if (obj is null) { @@ -44,7 +44,7 @@ public class ListStringConverter : BaseStringConverter : BaseStringConverter> } /// - public override Result Serialize(T? obj, PacketStringBuilder builder) + public override Result Serialize(T? obj, ref PacketStringBuilder builder) { if (obj is null) { @@ -39,7 +39,7 @@ public class NullableStringConverter : BaseStringConverter> return Result.FromSuccess(); } - return _stringSerializer.Serialize(obj.Value, builder); + return _stringSerializer.Serialize(obj.Value, ref builder); } /// diff --git a/Packets/NosSmooth.PacketSerializer/Converters/Special/StringSerializer.cs b/Packets/NosSmooth.PacketSerializer/Converters/Special/StringSerializer.cs index 9c1bbab40f4e28307eefe486a2646f0b82e2f443..f5eedc9b26299afebb8c92977dc574321714005a 100644 --- a/Packets/NosSmooth.PacketSerializer/Converters/Special/StringSerializer.cs +++ b/Packets/NosSmooth.PacketSerializer/Converters/Special/StringSerializer.cs @@ -43,7 +43,7 @@ public class StringSerializer : IStringSerializer } /// - public Result Serialize(Type parseType, object? obj, PacketStringBuilder builder) + public Result Serialize(Type parseType, object? obj, ref PacketStringBuilder builder) { var converterResult = _converterRepository.GetTypeConverter(parseType); if (!converterResult.IsSuccess) @@ -51,7 +51,7 @@ public class StringSerializer : IStringSerializer return Result.FromError(converterResult); } - return converterResult.Entity.Serialize(obj, builder); + return converterResult.Entity.Serialize(obj, ref builder); } /// @@ -67,7 +67,7 @@ public class StringSerializer : IStringSerializer } /// - public Result Serialize(TParseType? obj, PacketStringBuilder builder) + public Result Serialize(TParseType? obj, ref PacketStringBuilder builder) { var converterResult = _converterRepository.GetTypeConverter(); if (!converterResult.IsSuccess) @@ -75,6 +75,6 @@ public class StringSerializer : IStringSerializer return Result.FromError(converterResult); } - return converterResult.Entity.Serialize(obj, builder); + return converterResult.Entity.Serialize(obj, ref builder); } } \ No newline at end of file diff --git a/Packets/NosSmooth.PacketSerializer/NosSmooth.PacketSerializer.csproj b/Packets/NosSmooth.PacketSerializer/NosSmooth.PacketSerializer.csproj index 6058f0735750785eccd39e282c37d22272cc2a4b..54d83bb45b078c5d9e25b66c1ef2d651b40ff7f4 100644 --- a/Packets/NosSmooth.PacketSerializer/NosSmooth.PacketSerializer.csproj +++ b/Packets/NosSmooth.PacketSerializer/NosSmooth.PacketSerializer.csproj @@ -4,10 +4,10 @@ 10 NosSmooth.PacketSerializer NosSmooth.PacketSerializer - net7.0;netstandard2.1 NosSmooth's packet string serializer implementation. 2.2.7 Make IPacketSerializer work with ReadOnlySpan. + net7.0 diff --git a/Packets/NosSmooth.PacketSerializer/PacketSerializer.cs b/Packets/NosSmooth.PacketSerializer/PacketSerializer.cs index 7e6fd6567f452a6672930041b342b7d9ca4d3e9b..7f306798e59cf5078a1fc56bff6bacec5159c4c0 100644 --- a/Packets/NosSmooth.PacketSerializer/PacketSerializer.cs +++ b/Packets/NosSmooth.PacketSerializer/PacketSerializer.cs @@ -34,7 +34,7 @@ public class PacketSerializer : IPacketSerializer /// public Result Serialize(IPacket obj) { - var stringBuilder = new PacketStringBuilder(); + var stringBuilder = new PacketStringBuilder(stackalloc char[500]); var infoResult = _packetTypesRepository.FindPacketInfo(obj.GetType()); if (!infoResult.IsSuccess) { @@ -48,7 +48,7 @@ public class PacketSerializer : IPacketSerializer } stringBuilder.Append(info.Header); - var serializeResult = info.PacketConverter.Serialize(obj, stringBuilder); + var serializeResult = info.PacketConverter.Serialize(obj, ref stringBuilder); if (!serializeResult.IsSuccess) { return Result.FromError(serializeResult); diff --git a/Packets/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/FallbackInlineConverterGenerator.cs b/Packets/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/FallbackInlineConverterGenerator.cs index 27ea1c541e53d68a86b0f3c691cfd8363badb0d1..dd760f2c5b218a51f5a368aa905aa0ddba652a94 100644 --- a/Packets/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/FallbackInlineConverterGenerator.cs +++ b/Packets/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/FallbackInlineConverterGenerator.cs @@ -32,7 +32,7 @@ public class FallbackInlineConverterGenerator : IInlineConverterGenerator var resultName = $"{variableName.Replace(".", string.Empty)}Result"; textWriter.WriteLine ( - $"var {resultName} = _stringSerializer.Serialize<{(typeSyntax?.ToString() ?? typeSymbol!.ToString()).TrimEnd('?')}?>({variableName}, builder);" + $"var {resultName} = _stringSerializer.Serialize<{(typeSyntax?.ToString() ?? typeSymbol!.ToString()).TrimEnd('?')}?>({variableName}, ref builder);" ); textWriter.WriteLine($"if (!{resultName}.IsSuccess)"); textWriter.WriteLine("{"); diff --git a/Packets/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs b/Packets/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs index 733f03104d19333fd0f3efd6a02cff5ab7c75169..5a43051c1eadb530c5b205013b45d80842505982 100644 --- a/Packets/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs +++ b/Packets/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs @@ -75,7 +75,7 @@ public {_packetInfo.Name}Converter(IStringSerializer stringSerializer) }} /// -public override Result Serialize({_packetInfo.Name}? obj, PacketStringBuilder builder) +public override Result Serialize({_packetInfo.Name}? obj, ref PacketStringBuilder builder) {{ if (obj is null) {{ diff --git a/Packets/NosSmooth.Packets/NosSmooth.Packets.csproj b/Packets/NosSmooth.Packets/NosSmooth.Packets.csproj index 82e7ffb76c9e4c5f328002649851a933583c8222..593c8097a71a6b778fe80661b8748a73aac6c5cd 100644 --- a/Packets/NosSmooth.Packets/NosSmooth.Packets.csproj +++ b/Packets/NosSmooth.Packets/NosSmooth.Packets.csproj @@ -6,8 +6,8 @@ 10 Contains default NosTale packets. 3.6.0 - net7.0;netstandard2.1 Add missing ptctl fields. + net7.0 diff --git a/Tests/NosSmooth.Packets.Tests/Converters/Basic/BoolStringConverterTests.cs b/Tests/NosSmooth.Packets.Tests/Converters/Basic/BoolStringConverterTests.cs index 1c660740d9d8bb987b397a665f87ee83e9e40540..e5f1429713c3b65a7f9722d24e537243d8412a0d 100644 --- a/Tests/NosSmooth.Packets.Tests/Converters/Basic/BoolStringConverterTests.cs +++ b/Tests/NosSmooth.Packets.Tests/Converters/Basic/BoolStringConverterTests.cs @@ -38,8 +38,8 @@ public class BoolStringConverterTests public void TestsTreatsNullAsMinusOne() { bool? test = null; - var stringBuilder = new PacketStringBuilder(); - var serializeResult = _stringSerializer.Serialize(test, stringBuilder); + var stringBuilder = new PacketStringBuilder(stackalloc char[500]); + var serializeResult = _stringSerializer.Serialize(test, ref stringBuilder); Assert.True(serializeResult.IsSuccess, !serializeResult.IsSuccess ? serializeResult.Error.Message : string.Empty); Assert.Equal("-1", stringBuilder.ToString()); } diff --git a/Tests/NosSmooth.Packets.Tests/Converters/Basic/StringConverterTests.cs b/Tests/NosSmooth.Packets.Tests/Converters/Basic/StringConverterTests.cs index fde0180d241c3aee7d795b6ade50e694f16aa704..5e8347fe4550b730dd7b7515908ed53416ed1300 100644 --- a/Tests/NosSmooth.Packets.Tests/Converters/Basic/StringConverterTests.cs +++ b/Tests/NosSmooth.Packets.Tests/Converters/Basic/StringConverterTests.cs @@ -38,8 +38,8 @@ public class StringConverterTests public void TestsTreatsNullAsMinus() { string? test = null; - var stringBuilder = new PacketStringBuilder(); - var serializeResult = _stringSerializer.Serialize(test, stringBuilder); + var stringBuilder = new PacketStringBuilder(stackalloc char[500]); + var serializeResult = _stringSerializer.Serialize(test, ref stringBuilder); Assert.True(serializeResult.IsSuccess, !serializeResult.IsSuccess ? serializeResult.Error.Message : string.Empty); Assert.Equal("-", stringBuilder.ToString()); } diff --git a/Tests/NosSmooth.Packets.Tests/PacketStringBuilderTests.cs b/Tests/NosSmooth.Packets.Tests/PacketStringBuilderTests.cs index 8e2bed20b537fbd85123b5f402c9c73d55adaab0..c4d2c060bb5e165f3436cd2486f3f7ef9773c879 100644 --- a/Tests/NosSmooth.Packets.Tests/PacketStringBuilderTests.cs +++ b/Tests/NosSmooth.Packets.Tests/PacketStringBuilderTests.cs @@ -21,7 +21,7 @@ public class PacketStringBuilderTests public void BuilderCorrectlyBuildsComplexArray() { // in 1 11.12.13|14.15.16|17.18.19 - var stringBuilder = new PacketStringBuilder(); + var stringBuilder = new PacketStringBuilder(stackalloc char[500]); stringBuilder.Append("in"); stringBuilder.Append("1"); @@ -48,7 +48,7 @@ public class PacketStringBuilderTests [Fact] public void BuilderCorrectlyUsesOnceSeparator() { - var stringBuilder = new PacketStringBuilder(); + var stringBuilder = new PacketStringBuilder(stackalloc char[500]); stringBuilder.Append("in"); stringBuilder.SetAfterSeparatorOnce('.');