M Core/NosSmooth.PacketSerializersGenerator/ConverterDeserializationGenerator.cs => Core/NosSmooth.PacketSerializersGenerator/ConverterDeserializationGenerator.cs +1 -1
@@ 94,7 94,7 @@ public class ConverterDeserializationGenerator
_textWriter.WriteLine($@"while ({_stringEnumeratorVariable}.IsOnLastToken() == false)");
_textWriter.WriteLine("{");
_textWriter.Indent++;
- _textWriter.WriteLine($"{_stringEnumeratorVariable}.GetNextToken();");
+ _textWriter.WriteLine($"{_stringEnumeratorVariable}.GetNextToken(out _);");
_textWriter.Indent--;
_textWriter.WriteLine("}");
}
M Core/NosSmooth.PacketSerializersGenerator/Extensions/ParameterInfoExtensions.cs => Core/NosSmooth.PacketSerializersGenerator/Extensions/ParameterInfoExtensions.cs +10 -0
@@ 38,6 38,16 @@ public static class ParameterInfoExtensions
}
/// <summary>
+ /// Gets the name of the token variable.
+ /// </summary>
+ /// <param name="parameterInfo">The parameter.</param>
+ /// <returns>The name of the token variable.</returns>
+ public static string GetTokenVariableName(this ParameterInfo parameterInfo)
+ {
+ return $"{parameterInfo.Name}Token";
+ }
+
+ /// <summary>
/// Gets the name of the error variable.
/// </summary>
/// <param name="parameterInfo">The parameter.</param>
M Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/BasicInlineConverterGenerator.cs => Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/BasicInlineConverterGenerator.cs +1 -1
@@ 91,4 91,4 @@ public static Result<{type}?> ParseBasic{type}(IStringConverter typeConverter, P
");
}
}
-}>
\ No newline at end of file
+}
M Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/BoolInlineConverterGenerator.cs => Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/BoolInlineConverterGenerator.cs +1 -1
@@ 70,4 70,4 @@ public static Result<bool?> ParseBool(PacketStringEnumerator stringEnumerator)
}}
");
}
-}>
\ No newline at end of file
+}
M Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/EnumInlineConverterGenerator.cs => Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/EnumInlineConverterGenerator.cs +1 -1
@@ 105,4 105,4 @@ public static Result<{type}?> ParseEnum{type.ToString().Replace('.', '_')}(IStri
);
}
}
-}>
\ No newline at end of file
+}
M Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/FallbackInlineConverterGenerator.cs => Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/FallbackInlineConverterGenerator.cs +1 -1
@@ 58,4 58,4 @@ public class FallbackInlineConverterGenerator : IInlineConverterGenerator
{
// ignore
}
-}>
\ No newline at end of file
+}
M Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/StringInlineConverterGenerator.cs => Core/NosSmooth.PacketSerializersGenerator/InlineConverterGenerators/StringInlineConverterGenerator.cs +1 -1
@@ 53,4 53,4 @@ public static Result<string?> ParseString(PacketStringEnumerator stringEnumerato
"
);
}
-}>
\ No newline at end of file
+}
M Core/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs => Core/NosSmooth.PacketSerializersGenerator/PacketConverterGenerator.cs +3 -3
@@ 95,7 95,7 @@ public override Result Serialize({_packetInfo.Name}? obj, PacketStringBuilder bu
}}
/// <inheritdoc />
-public override Result<{_packetInfo.Name}?> Deserialize(PacketStringEnumerator stringEnumerator)
+public override Result<{_packetInfo.Name}?> Deserialize(ref PacketStringEnumerator stringEnumerator)
{{
var typeConverter = this;
"
@@ 176,7 176,7 @@ public override Result<{_packetInfo.Name}?> Deserialize(PacketStringEnumerator s
textWriter.WriteLine("IResultError? skipError;");
skipped = true;
}
- textWriter.WriteLine($@"skipResult = stringEnumerator.GetNextToken();");
+ textWriter.WriteLine($@"skipResult = stringEnumerator.GetNextToken(out _);");
textWriter.WriteLine
("skipError = CheckDeserializationResult(result, \"None\", stringEnumerator, false);");
textWriter.WriteMultiline
@@ 246,4 246,4 @@ public override Result<{_packetInfo.Name}?> Deserialize(PacketStringEnumerator s
return null;
}
-}>
\ No newline at end of file
+}
M Core/NosSmooth.PacketSerializersGenerator/SourceGenerator.cs => Core/NosSmooth.PacketSerializersGenerator/SourceGenerator.cs +5 -0
@@ 130,6 130,11 @@ public class SourceGenerator : ISourceGenerator
$"{packetRecord.GetPrefix()}.{packetRecord.Identifier.NormalizeWhitespace().ToFullString()}Converter.g.cs",
stringWriter.GetStringBuilder().ToString()
);
+ File.WriteAllText
+ (
+ $"/tmp/{packetRecord.GetPrefix()}.{packetRecord.Identifier.NormalizeWhitespace().ToFullString()}Converter.g.cs",
+ stringWriter.GetStringBuilder().ToString()
+ );
}
}
M Core/NosSmooth.Packets/Converters/BaseStringConverter.cs => Core/NosSmooth.Packets/Converters/BaseStringConverter.cs +4 -4
@@ 19,12 19,12 @@ public abstract class BaseStringConverter<TParseType> : IStringConverter<TParseT
public abstract Result Serialize(TParseType? obj, PacketStringBuilder builder);
/// <inheritdoc />
- public abstract Result<TParseType?> Deserialize(PacketStringEnumerator stringEnumerator);
+ public abstract Result<TParseType?> Deserialize(ref PacketStringEnumerator stringEnumerator);
/// <inheritdoc/>
- Result<object?> IStringConverter.Deserialize(PacketStringEnumerator stringEnumerator)
+ Result<object?> IStringConverter.Deserialize(ref PacketStringEnumerator stringEnumerator)
{
- var result = Deserialize(stringEnumerator);
+ var result = Deserialize(ref stringEnumerator);
if (!result.IsSuccess)
{
return Result<object?>.FromError(result);
@@ 43,4 43,4 @@ public abstract class BaseStringConverter<TParseType> : IStringConverter<TParseT
return Serialize(parseType, builder);
}
-}>
\ No newline at end of file
+}
M Core/NosSmooth.Packets/Converters/Basic/BasicTypeConverter.cs => Core/NosSmooth.Packets/Converters/Basic/BasicTypeConverter.cs +5 -5
@@ 23,20 23,20 @@ public abstract class BasicTypeConverter<TBasicType> : BaseStringConverter<TBasi
}
/// <inheritdoc />
- public override Result<TBasicType?> Deserialize(PacketStringEnumerator stringEnumerator)
+ public override Result<TBasicType?> Deserialize(ref PacketStringEnumerator stringEnumerator)
{
- var nextTokenResult = stringEnumerator.GetNextToken();
+ var nextTokenResult = stringEnumerator.GetNextToken(out var packetToken);
if (!nextTokenResult.IsSuccess)
{
return Result<TBasicType?>.FromError(nextTokenResult);
}
- if (nextTokenResult.Entity.Token == "-")
+ if (packetToken.Token[0] == '-' && packetToken.Token.Length == 1)
{
return Result<TBasicType?>.FromSuccess(default);
}
- return Deserialize(nextTokenResult.Entity.Token);
+ return Deserialize(packetToken.Token);
}
/// <summary>
@@ 44,5 44,5 @@ public abstract class BasicTypeConverter<TBasicType> : BaseStringConverter<TBasi
/// </summary>
/// <param name="value">The value to deserialize.</param>
/// <returns>The deserialized value or an error.</returns>
- protected abstract Result<TBasicType?> Deserialize(string value);
+ protected abstract Result<TBasicType?> Deserialize(ReadOnlySpan<char> value);
}=
\ No newline at end of file
M Core/NosSmooth.Packets/Converters/Basic/BoolStringConverter.cs => Core/NosSmooth.Packets/Converters/Basic/BoolStringConverter.cs +3 -8
@@ 22,19 22,14 @@ public class BoolStringConverter : BaseStringConverter<bool>
}
/// <inheritdoc />
- public override Result<bool> Deserialize(PacketStringEnumerator stringEnumerator)
+ public override Result<bool> Deserialize(ref PacketStringEnumerator stringEnumerator)
{
- var nextTokenResult = stringEnumerator.GetNextToken();
+ var nextTokenResult = stringEnumerator.GetNextToken(out var packetToken);
if (!nextTokenResult.IsSuccess)
{
return Result<bool>.FromError(nextTokenResult);
}
- if (nextTokenResult.Entity.Token == "-")
- {
- return Result<bool>.FromSuccess(default);
- }
-
- return nextTokenResult.Entity.Token == "1" ? true : false;
+ return packetToken.Token[0] == '1' ? true : false;
}
}=
\ No newline at end of file
M Core/NosSmooth.Packets/Converters/Basic/ByteStringConverter.cs => Core/NosSmooth.Packets/Converters/Basic/ByteStringConverter.cs +3 -2
@@ 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;
using NosSmooth.Packets.Errors;
using Remora.Results;
@@ 15,11 16,11 @@ namespace NosSmooth.Packets.Converters.Basic;
public class ByteStringConverter : BasicTypeConverter<byte>
{
/// <inheritdoc />
- protected override Result<byte> Deserialize(string value)
+ protected override Result<byte> Deserialize(ReadOnlySpan<char> value)
{
if (!byte.TryParse(value, out var parsed))
{
- return new CouldNotConvertError(this, value, "Could not parse as an byte.");
+ return new CouldNotConvertError(this, value.ToString(), "Could not parse as an byte.");
}
return parsed;
M Core/NosSmooth.Packets/Converters/Basic/CharStringConverter.cs => Core/NosSmooth.Packets/Converters/Basic/CharStringConverter.cs +3 -2
@@ 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;
using NosSmooth.Packets.Errors;
using Remora.Results;
@@ 15,11 16,11 @@ namespace NosSmooth.Packets.Converters.Basic;
public class CharStringConverter : BasicTypeConverter<char>
{
/// <inheritdoc />
- protected override Result<char> Deserialize(string value)
+ protected override Result<char> Deserialize(ReadOnlySpan<char> value)
{
if (value.Length != 1)
{
- return new CouldNotConvertError(this, value, "The token is not one character long.");
+ return new CouldNotConvertError(this, value.ToString(), "The token is not one character long.");
}
return value[0];
M Core/NosSmooth.Packets/Converters/Basic/IntStringConverter.cs => Core/NosSmooth.Packets/Converters/Basic/IntStringConverter.cs +3 -2
@@ 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;
using NosSmooth.Packets.Errors;
using Remora.Results;
@@ 15,11 16,11 @@ namespace NosSmooth.Packets.Converters.Basic;
public class IntStringConverter : BasicTypeConverter<int>
{
/// <inheritdoc />
- protected override Result<int> Deserialize(string value)
+ protected override Result<int> Deserialize(ReadOnlySpan<char> value)
{
if (!int.TryParse(value, out var parsed))
{
- return new CouldNotConvertError(this, value, "Could not parse as int.");
+ return new CouldNotConvertError(this, value.ToString(), "Could not parse as int.");
}
return parsed;
M Core/NosSmooth.Packets/Converters/Basic/LongStringConverter.cs => Core/NosSmooth.Packets/Converters/Basic/LongStringConverter.cs +3 -2
@@ 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;
using NosSmooth.Packets.Errors;
using Remora.Results;
@@ 15,11 16,11 @@ namespace NosSmooth.Packets.Converters.Basic;
public class LongStringConverter : BasicTypeConverter<long>
{
/// <inheritdoc />
- protected override Result<long> Deserialize(string value)
+ protected override Result<long> Deserialize(ReadOnlySpan<char> value)
{
if (!long.TryParse(value, out var parsed))
{
- return new CouldNotConvertError(this, value, "Could not parse as a long.");
+ return new CouldNotConvertError(this, value.ToString(), "Could not parse as a long.");
}
return parsed;
M Core/NosSmooth.Packets/Converters/Basic/ShortStringConverter.cs => Core/NosSmooth.Packets/Converters/Basic/ShortStringConverter.cs +3 -2
@@ 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;
using NosSmooth.Packets.Errors;
using Remora.Results;
@@ 15,11 16,11 @@ namespace NosSmooth.Packets.Converters.Basic;
public class ShortStringConverter : BasicTypeConverter<short>
{
/// <inheritdoc />
- protected override Result<short> Deserialize(string value)
+ protected override Result<short> Deserialize(ReadOnlySpan<char> value)
{
if (!short.TryParse(value, out var parsed))
{
- return new CouldNotConvertError(this, value, "Could not parse as short.");
+ return new CouldNotConvertError(this, value.ToString(), "Could not parse as short.");
}
return parsed;
M Core/NosSmooth.Packets/Converters/Basic/StringTypeConverter.cs => Core/NosSmooth.Packets/Converters/Basic/StringTypeConverter.cs +3 -2
@@ 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;
using Remora.Results;
namespace NosSmooth.Packets.Converters.Basic;
@@ 14,8 15,8 @@ namespace NosSmooth.Packets.Converters.Basic;
public class StringTypeConverter : BasicTypeConverter<string>
{
/// <inheritdoc />
- protected override Result<string?> Deserialize(string value)
+ protected override Result<string?> Deserialize(ReadOnlySpan<char> value)
{
- return value;
+ return value.ToString();
}
}=
\ No newline at end of file
M Core/NosSmooth.Packets/Converters/Basic/UIntStringConverter.cs => Core/NosSmooth.Packets/Converters/Basic/UIntStringConverter.cs +3 -2
@@ 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;
using NosSmooth.Packets.Errors;
using Remora.Results;
@@ 15,11 16,11 @@ namespace NosSmooth.Packets.Converters.Basic;
public class UIntStringConverter : BasicTypeConverter<uint>
{
/// <inheritdoc />
- protected override Result<uint> Deserialize(string value)
+ protected override Result<uint> Deserialize(ReadOnlySpan<char> value)
{
if (!uint.TryParse(value, out var parsed))
{
- return new CouldNotConvertError(this, value, "Could not parse as uint");
+ return new CouldNotConvertError(this, value.ToString(), "Could not parse as uint");
}
return parsed;
M Core/NosSmooth.Packets/Converters/Basic/ULongStringConverter.cs => Core/NosSmooth.Packets/Converters/Basic/ULongStringConverter.cs +3 -2
@@ 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;
using NosSmooth.Packets.Errors;
using Remora.Results;
@@ 15,11 16,11 @@ namespace NosSmooth.Packets.Converters.Basic;
public class ULongStringConverter : BasicTypeConverter<ulong>
{
/// <inheritdoc />
- protected override Result<ulong> Deserialize(string value)
+ protected override Result<ulong> Deserialize(ReadOnlySpan<char> value)
{
if (!ulong.TryParse(value, out var parsed))
{
- return new CouldNotConvertError(this, value, "Could not parse as an ulong.");
+ return new CouldNotConvertError(this, value.ToString(), "Could not parse as an ulong.");
}
return parsed;
M Core/NosSmooth.Packets/Converters/Basic/UShortStringConverter.cs => Core/NosSmooth.Packets/Converters/Basic/UShortStringConverter.cs +3 -2
@@ 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;
using NosSmooth.Packets.Errors;
using Remora.Results;
@@ 15,11 16,11 @@ namespace NosSmooth.Packets.Converters.Basic;
public class UShortStringConverter : BasicTypeConverter<ushort>
{
/// <inheritdoc />
- protected override Result<ushort> Deserialize(string value)
+ protected override Result<ushort> Deserialize(ReadOnlySpan<char> value)
{
if (!ushort.TryParse(value, out var parsed))
{
- return new CouldNotConvertError(this, value, "Could not parse as an ushort.");
+ return new CouldNotConvertError(this, value.ToString(), "Could not parse as an ushort.");
}
return parsed;
M Core/NosSmooth.Packets/Converters/Common/NameStringConverter.cs => Core/NosSmooth.Packets/Converters/Common/NameStringConverter.cs +4 -4
@@ 29,19 29,19 @@ public class NameStringConverter : BaseStringConverter<NameString>
}
/// <inheritdoc />
- public override Result<NameString?> Deserialize(PacketStringEnumerator stringEnumerator)
+ public override Result<NameString?> Deserialize(ref PacketStringEnumerator stringEnumerator)
{
- var tokenResult = stringEnumerator.GetNextToken();
+ var tokenResult = stringEnumerator.GetNextToken(out var packetToken);
if (!tokenResult.IsSuccess)
{
return Result<NameString?>.FromError(tokenResult);
}
- if (tokenResult.Entity.Token == "-")
+ if (packetToken.Token[0] == '-' && packetToken.Token.Length == 1)
{
return Result<NameString?>.FromSuccess(null);
}
- return NameString.FromPacket(tokenResult.Entity.Token);
+ return NameString.FromPacket(packetToken.Token.ToString());
}
}=
\ No newline at end of file
M Core/NosSmooth.Packets/Converters/IStringConverter.cs => Core/NosSmooth.Packets/Converters/IStringConverter.cs +2 -2
@@ 18,7 18,7 @@ public interface IStringConverter
/// </summary>
/// <param name="stringEnumerator">The packet string enumerator with the current position.</param>
/// <returns>The parsed object or an error.</returns>
- public Result<object?> Deserialize(PacketStringEnumerator stringEnumerator);
+ public Result<object?> Deserialize(ref PacketStringEnumerator stringEnumerator);
/// <summary>
/// Serializes the given object to string by appending to the packet string builder.
@@ 43,7 43,7 @@ public interface IStringConverter<TParseType> : IStringConverter
/// </summary>
/// <param name="stringEnumerator">The packet string enumerator with the current position.</param>
/// <returns>The parsed object or an error.</returns>
- public new Result<TParseType?> Deserialize(PacketStringEnumerator stringEnumerator);
+ public new Result<TParseType?> Deserialize(ref PacketStringEnumerator stringEnumerator);
/// <summary>
/// Serializes the given object to string by appending to the packet string builder.
M Core/NosSmooth.Packets/Converters/IStringSerializer.cs => Core/NosSmooth.Packets/Converters/IStringSerializer.cs +2 -2
@@ 20,7 20,7 @@ public interface IStringSerializer
/// <param name="parseType">The type of the object to serialize.</param>
/// <param name="stringEnumerator">The packet string enumerator with the current position.</param>
/// <returns>The parsed object or an error.</returns>
- public Result<object?> Deserialize(Type parseType, PacketStringEnumerator stringEnumerator);
+ public Result<object?> Deserialize(Type parseType, ref PacketStringEnumerator stringEnumerator);
/// <summary>
/// Serializes the given object to string by appending to the packet string builder.
@@ 37,7 37,7 @@ public interface IStringSerializer
/// <param name="stringEnumerator">The packet string enumerator with the current position.</param>
/// <typeparam name="TParseType">The type of the object to serialize.</typeparam>
/// <returns>The parsed object or an error.</returns>
- public Result<TParseType?> Deserialize<TParseType>(PacketStringEnumerator stringEnumerator);
+ public Result<TParseType?> Deserialize<TParseType>(ref PacketStringEnumerator stringEnumerator);
/// <summary>
/// Serializes the given object to string by appending to the packet string builder.
M Core/NosSmooth.Packets/Converters/Packets/UpgradeRareSubPacketConverter.cs => Core/NosSmooth.Packets/Converters/Packets/UpgradeRareSubPacketConverter.cs +8 -8
@@ 28,31 28,31 @@ public class UpgradeRareSubPacketConverter : BaseStringConverter<UpgradeRareSubP
}
/// <inheritdoc />
- public override Result<UpgradeRareSubPacket?> Deserialize(PacketStringEnumerator stringEnumerator)
+ public override Result<UpgradeRareSubPacket?> Deserialize(ref PacketStringEnumerator stringEnumerator)
{
- var tokenResult = stringEnumerator.GetNextToken();
+ var tokenResult = stringEnumerator.GetNextToken(out var packetToken);
if (!tokenResult.IsSuccess)
{
return Result<UpgradeRareSubPacket?>.FromError(tokenResult);
}
+ var token = packetToken.Token;
- var token = tokenResult.Entity.Token;
if (token.Length > 3)
{
- return new CouldNotConvertError(this, token, "The string is not two/three characters long.");
+ return new CouldNotConvertError(this, token.ToString(), "The string is not two/three characters long.");
}
- var upgradeString = token.Substring(0, token.Length - 1);
- var rareString = token[token.Length - 1].ToString();
+ var upgradeString = token.Slice(0, token.Length - 1);
+ var rareString = token.Slice(token.Length - 1);
if (!byte.TryParse(upgradeString, out var upgrade))
{
- return new CouldNotConvertError(this, upgradeString, "Could not parse as byte");
+ return new CouldNotConvertError(this, upgradeString.ToString(), "Could not parse as byte");
}
if (!sbyte.TryParse(rareString, out var rare))
{
- return new CouldNotConvertError(this, rareString, "Could not parse as byte");
+ return new CouldNotConvertError(this, rareString.ToString(), "Could not parse as byte");
}
return new UpgradeRareSubPacket(upgrade, rare);
A Core/NosSmooth.Packets/Converters/Special/EnumTypeConverter.cs => Core/NosSmooth.Packets/Converters/Special/EnumTypeConverter.cs +0 -0
A Core/NosSmooth.Packets/Converters/Special/ISpecialTypeConverter.cs => Core/NosSmooth.Packets/Converters/Special/ISpecialTypeConverter.cs +0 -0
A Core/NosSmooth.Packets/Converters/Special/ListTypeConverter.cs => Core/NosSmooth.Packets/Converters/Special/ListTypeConverter.cs +0 -0
A Core/NosSmooth.Packets/Converters/Special/NullableTypeConverter.cs => Core/NosSmooth.Packets/Converters/Special/NullableTypeConverter.cs +0 -0
A Core/NosSmooth.Packets/Converters/TypeConverterRepository.cs => Core/NosSmooth.Packets/Converters/TypeConverterRepository.cs +0 -0
M Core/NosSmooth.Packets/Errors/CouldNotConvertError.cs => Core/NosSmooth.Packets/Errors/CouldNotConvertError.cs +1 -0
@@ 5,6 5,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.Buffers;
using NosSmooth.Packets.Converters;
using Remora.Results;
M Core/NosSmooth.Packets/NosSmooth.Packets.csproj => Core/NosSmooth.Packets/NosSmooth.Packets.csproj +1 -1
@@ 2,9 2,9 @@
<PropertyGroup>
<LangVersion>10</LangVersion>
- <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<AssemblyName>NosSmooth.Packets</AssemblyName>
<RootNamespace>NosSmooth.Packets</RootNamespace>
+ <TargetFrameworks>net6.0;netstandard2.1</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
M Core/NosSmooth.Packets/PacketSerializer.cs => Core/NosSmooth.Packets/PacketSerializer.cs +3 -3
@@ 59,20 59,20 @@ public class PacketSerializer : IPacketSerializer
public Result<IPacket> Deserialize(string packetString, PacketSource preferredSource)
{
var packetStringEnumerator = new PacketStringEnumerator(packetString);
- var headerTokenResult = packetStringEnumerator.GetNextToken();
+ var headerTokenResult = packetStringEnumerator.GetNextToken(out var packetToken);
if (!headerTokenResult.IsSuccess)
{
return Result<IPacket>.FromError(headerTokenResult);
}
- var packetInfoResult = _packetTypesRepository.FindPacketInfo(headerTokenResult.Entity.Token, preferredSource);
+ var packetInfoResult = _packetTypesRepository.FindPacketInfo(packetToken.Token.ToString(), preferredSource);
if (!packetInfoResult.IsSuccess)
{
return Result<IPacket>.FromError(packetInfoResult);
}
var packetInfo = packetInfoResult.Entity;
- var deserializedResult = packetInfo.PacketConverter.Deserialize(packetStringEnumerator);
+ var deserializedResult = packetInfo.PacketConverter.Deserialize(ref packetStringEnumerator);
if (!deserializedResult.IsSuccess)
{
return Result<IPacket>.FromError(deserializedResult);
M Core/NosSmooth.Packets/PacketStringEnumerator.cs => Core/NosSmooth.Packets/PacketStringEnumerator.cs +47 -91
@@ 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;
using System.Collections.Generic;
using System.Text;
using NosSmooth.Packets.Errors;
@@ 14,15 15,18 @@ namespace NosSmooth.Packets;
/// <summary>
/// Enumerator for packet strings.
/// </summary>
-public struct PacketStringEnumerator
+public ref struct PacketStringEnumerator
{
- private readonly EnumeratorData _data;
+ private readonly ReadOnlySpan<char> _data;
private readonly Dictionary<char, ushort> _numberOfSeparators;
private EnumeratorLevel _currentLevel;
private (char Separator, uint? MaxTokens)? _preparedLevel;
- private PacketToken? _currentToken;
+ private bool _currentTokenRead;
+ private PacketToken _currentToken;
private bool _readToLast;
+ private int _cursor;
+
/// <summary>
/// Initializes a new instance of the <see cref="PacketStringEnumerator"/> struct.
/// </summary>
@@ 31,30 35,14 @@ public struct PacketStringEnumerator
public PacketStringEnumerator(string data, char separator = ' ')
{
_currentLevel = new EnumeratorLevel(null, separator);
- _data = new EnumeratorData(data);
+ _data = new ReadOnlySpan<char>(data.ToCharArray());
+ _cursor = 0;
_numberOfSeparators = new Dictionary<char, ushort>();
_numberOfSeparators.Add(separator, 1);
- _currentToken = null;
- _preparedLevel = null;
- _readToLast = false;
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="PacketStringEnumerator"/> struct.
- /// </summary>
- /// <param name="data">The data of the enumerator.</param>
- /// <param name="level">The current enumerator level.</param>
- /// <param name="numberOfSeparators">The number of separators.</param>
- private PacketStringEnumerator(EnumeratorData data, EnumeratorLevel level, Dictionary<char, ushort> numberOfSeparators)
- {
- _currentLevel = level;
- _data = data;
-
- // TODO: use something less heavy than copying everything from the dictionary.
- _numberOfSeparators = new Dictionary<char, ushort>(numberOfSeparators);
- _currentToken = null;
+ _currentToken = new PacketToken(default, default, default, default);
_preparedLevel = null;
_readToLast = false;
+ _currentTokenRead = false;
}
/// <summary>
@@ 66,7 54,7 @@ public struct PacketStringEnumerator
/// <param name="separator">The separator to look for.</param>
public void SetAfterSeparatorOnce(char separator)
{
- _currentToken = null;
+ _currentTokenRead = false;
_currentLevel.SeparatorOnce = separator;
}
@@ 97,19 85,6 @@ public struct PacketStringEnumerator
}
/// <summary>
- /// Create next level with the separator given in the prepared level.
- /// </summary>
- /// <remarks>
- /// Level of the current enumerator will stay the same.
- /// Will return null, if there is not a level prepared.
- /// </remarks>
- /// <returns>An enumerator with the new level pushed.</returns>
- public PacketStringEnumerator? CreatePreparedLevel()
- {
- return _preparedLevel is not null ? CreateLevel(_preparedLevel.Value.Separator, _preparedLevel.Value.MaxTokens) : null;
- }
-
- /// <summary>
/// Push next level with the separator given in the prepared level.
/// </summary>
/// <returns>Whether there is a prepared level present.</returns>
@@ 120,7 95,7 @@ public struct PacketStringEnumerator
return false;
}
- _currentToken = null;
+ _currentTokenRead = false;
_currentLevel = new EnumeratorLevel(_currentLevel, _preparedLevel.Value.Separator, _preparedLevel.Value.MaxTokens)
{
ReachedEnd = _currentLevel.ReachedEnd
@@ 136,25 111,6 @@ public struct PacketStringEnumerator
}
/// <summary>
- /// Create next level with the given separator and maximum number of tokens.
- /// </summary>
- /// <remarks>
- /// Level of the current enumerator will stay the same.
- /// The maximum number of tokens indicates how many tokens can be read ie. in lists,
- /// the enumerator won't allow reading more than that many tokens, error will be thrown if the user tries to read more.
- /// </remarks>
- /// <param name="separator">The separator of the new level.</param>
- /// <param name="maxTokens">The maximum number of tokens to read.</param>
- /// <returns>An enumerator with the new level pushed.</returns>
- public PacketStringEnumerator CreateLevel(char separator, uint? maxTokens = default)
- {
- _currentToken = null;
- var stringEnumerator = new PacketStringEnumerator(_data, _currentLevel, _numberOfSeparators);
- stringEnumerator.PushLevel(separator, maxTokens);
- return stringEnumerator;
- }
-
- /// <summary>
/// Push new separator level to the stack.
/// </summary>
/// <remarks>
@@ 166,7 122,7 @@ public struct PacketStringEnumerator
public void PushLevel(char separator, uint? maxTokens = default)
{
_preparedLevel = null;
- _currentToken = null;
+ _currentTokenRead = false;
_currentLevel = new EnumeratorLevel(_currentLevel, separator, maxTokens)
{
ReachedEnd = _currentLevel.ReachedEnd
@@ 197,36 153,50 @@ public struct PacketStringEnumerator
}
/// <summary>
+ /// Skip the given amount of characters.
+ /// </summary>
+ /// <param name="count">The count of characters to skip.</param>
+ public void Skip(int count)
+ {
+ _cursor += count;
+ }
+
+ /// <summary>
/// Get the next token.
/// </summary>
+ /// <param name="packetToken">The resulting token.</param>
/// <param name="seek">Whether to seek the cursor to the end of the token.</param>
/// <returns>The found token.</returns>
- public Result<PacketToken> GetNextToken(bool seek = true)
+ public Result GetNextToken(out PacketToken packetToken, bool seek = true)
{
// The token is cached if seek was false to speed things up.
- if (_currentToken != null)
+ if (_currentTokenRead)
{
- var cachedToken = _currentToken.Value;
+ var cachedToken = _currentToken;
if (seek)
{
UpdateCurrentAndParentLevels(cachedToken);
_currentLevel.TokensRead++;
- _currentToken = null;
- _data.Cursor += cachedToken.Token.Length + 1;
+ _currentTokenRead = false;
+ _cursor += cachedToken.Token.Length + 1;
_currentLevel.SeparatorOnce = null;
}
- return cachedToken;
+ packetToken = new PacketToken(default, default, default, default);
+ packetToken = cachedToken;
+ return Result.FromSuccess();
}
- if (_data.ReachedEnd || (_currentLevel.ReachedEnd ?? false))
+ if ((_cursor >= _data.Length) || (_currentLevel.ReachedEnd ?? false))
{
- return new PacketEndReachedError(_data.Data, _currentLevel.ReachedEnd ?? false);
+ packetToken = new PacketToken(default, default, default, default);
+ return new PacketEndReachedError(_data.ToString(), _currentLevel.ReachedEnd ?? false);
}
- var currentIndex = _data.Cursor;
- char currentCharacter = _data.Data[currentIndex];
- StringBuilder tokenString = new StringBuilder();
+ var currentIndex = _cursor;
+ var length = 0;
+ var startIndex = currentIndex;
+ char currentCharacter = _data[currentIndex];
bool? isLast, encounteredUpperLevel;
@@ 234,27 204,27 @@ public struct PacketStringEnumerator
// If should read to last, then read until isLast is null or true.
while (!IsSeparator(currentCharacter, out isLast, out encounteredUpperLevel) || (_readToLast && !(isLast ?? true)))
{
- tokenString.Append(currentCharacter);
+ length++;
currentIndex++;
- if (currentIndex == _data.Data.Length)
+ if (currentIndex >= _data.Length)
{
isLast = true;
encounteredUpperLevel = true;
break;
}
- currentCharacter = _data.Data[currentIndex];
+ currentCharacter = _data[currentIndex];
}
_readToLast = false;
currentIndex++;
- var token = new PacketToken(tokenString.ToString(), isLast, encounteredUpperLevel, _data.ReachedEnd);
+ var token = new PacketToken(_data.Slice(startIndex, length), isLast, encounteredUpperLevel, _cursor >= _data.Length);
if (seek)
{
UpdateCurrentAndParentLevels(token);
- _data.Cursor = currentIndex;
+ _cursor = currentIndex;
_currentLevel.TokensRead++;
}
else
@@ 262,7 232,8 @@ public struct PacketStringEnumerator
_currentToken = token;
}
- return token;
+ packetToken = token;
+ return Result.FromSuccess();
}
/// <summary>
@@ 312,7 283,7 @@ public struct PacketStringEnumerator
/// <returns>Whether the last token was read. Null if cannot determine (ie. there are multiple levels with the same separator.)</returns>
public bool? IsOnLastToken()
{
- if (_data.ReachedEnd)
+ if (_cursor >= _data.Length)
{
return true;
}
@@ 376,21 347,6 @@ public struct PacketStringEnumerator
return true;
}
- private class EnumeratorData
- {
- public EnumeratorData(string data)
- {
- Data = data;
- Cursor = 0;
- }
-
- public string Data { get; }
-
- public int Cursor { get; set; }
-
- public bool ReachedEnd => Cursor >= Data.Length;
- }
-
private class EnumeratorLevel
{
public EnumeratorLevel(EnumeratorLevel? parent, char separator, uint? maxTokens = default)
M Core/NosSmooth.Packets/PacketToken.cs => Core/NosSmooth.Packets/PacketToken.cs +50 -6
@@ 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;
using System.Diagnostics.CodeAnalysis;
namespace NosSmooth.Packets;
@@ 11,9 12,52 @@ namespace NosSmooth.Packets;
/// <summary>
/// The single token from a packet.
/// </summary>
-/// <param name="Token">The token.</param>
-/// <param name="IsLast">Whether the token is last in the current level. Null if it cannot be determined.</param>
-/// <param name="EncounteredUpperLevel">Whether the current separator was from an upper stack level than the parent. That could mean some kind of an error if not etc. at the end of parsing a last entry of a list and last entry of a subpacket.</param>
-/// <param name="PacketEndReached">Whether the packet's end was reached.</param>
-[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "Record struct creates the underlying properties.")]
-public readonly record struct PacketToken(string Token, bool? IsLast, bool? EncounteredUpperLevel, bool PacketEndReached);>
\ No newline at end of file
+[SuppressMessage
+(
+ "StyleCop.CSharp.NamingRules",
+ "SA1313:Parameter names should begin with lower-case letter",
+ Justification = "Record struct creates the underlying properties."
+)]
+public readonly ref struct PacketToken
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PacketToken"/> struct.
+ /// </summary>
+ /// <param name="token">The token.</param>
+ /// <param name="isLast">Whether this is the last token in the current level.</param>
+ /// <param name="encounteredUpperLevel">Whether upper level separator was encountered.</param>
+ /// <param name="packetEndReached">Whether the packet end was reached.</param>
+ public PacketToken
+ (
+ ReadOnlySpan<char> token,
+ bool? isLast,
+ bool? encounteredUpperLevel,
+ bool packetEndReached
+ )
+ {
+ Token = token;
+ IsLast = isLast;
+ EncounteredUpperLevel = encounteredUpperLevel;
+ PacketEndReached = packetEndReached;
+ }
+
+ /// <summary>
+ /// The token.
+ /// </summary>
+ public ReadOnlySpan<char> Token { get; }
+
+ /// <summary>
+ /// Whether the token is last in the current level. Null if it cannot be determined.
+ /// </summary>
+ public bool? IsLast { get; }
+
+ /// <summary>
+ /// Whether the current separator was from an upper stack level than the parent. That could mean some kind of an error if not etc. at the end of parsing a last entry of a list and last entry of a subpacket.
+ /// </summary>
+ public bool? EncounteredUpperLevel { get; }
+
+ /// <summary>
+ /// Whether the packet's end was reached.
+ /// </summary>
+ public bool PacketEndReached { get; }
+}<
\ No newline at end of file
M Tests/NosSmooth.Packets.Tests/PacketStringBuilderTests.cs => Tests/NosSmooth.Packets.Tests/PacketStringBuilderTests.cs +0 -1
@@ 55,7 55,6 @@ public class PacketStringBuilderTests
stringBuilder.Append("a");
stringBuilder.Append("b");
stringBuilder.Append("c");
- stringBuilder.ReplaceWithParentSeparator();
stringBuilder.PopLevel();
stringBuilder.Append("d");
M Tests/NosSmooth.Packets.Tests/PacketStringEnumeratorTests.cs => Tests/NosSmooth.Packets.Tests/PacketStringEnumeratorTests.cs +67 -62
@@ 23,64 23,65 @@ public class PacketStringEnumeratorTests
public void EnumeratorListComplexStringGivesCorrectResult()
{
var stringEnumerator = new PacketStringEnumerator("in 1 11.12.13|14.15.16|17.18.19");
- var headerTokenResult = stringEnumerator.GetNextToken();
+ var headerTokenResult = stringEnumerator.GetNextToken(out var packetToken);
Assert.True(headerTokenResult.IsSuccess);
- Assert.False(headerTokenResult.Entity.PacketEndReached);
- Assert.NotNull(headerTokenResult.Entity.IsLast);
- Assert.NotNull(headerTokenResult.Entity.EncounteredUpperLevel);
- Assert.False(headerTokenResult.Entity.IsLast);
- Assert.False(headerTokenResult.Entity.EncounteredUpperLevel);
- Assert.Matches("in", headerTokenResult.Entity.Token);
-
- var firstToken = stringEnumerator.GetNextToken();
+ Assert.False(packetToken.PacketEndReached);
+ Assert.NotNull(packetToken.IsLast);
+ Assert.NotNull(packetToken.EncounteredUpperLevel);
+ Assert.False(packetToken.IsLast);
+ Assert.False(packetToken.EncounteredUpperLevel);
+ Assert.Matches("in", packetToken.Token.ToString());
+
+ var firstToken = stringEnumerator.GetNextToken(out packetToken);
Assert.True(firstToken.IsSuccess);
- Assert.False(firstToken.Entity.PacketEndReached);
- Assert.NotNull(firstToken.Entity.IsLast);
- Assert.NotNull(firstToken.Entity.EncounteredUpperLevel);
- Assert.False(firstToken.Entity.IsLast);
- Assert.False(firstToken.Entity.EncounteredUpperLevel);
- Assert.Matches("1", firstToken.Entity.Token);
+ Assert.False(packetToken.PacketEndReached);
+ Assert.NotNull(packetToken.IsLast);
+ Assert.NotNull(packetToken.EncounteredUpperLevel);
+ Assert.False(packetToken.IsLast);
+ Assert.False(packetToken.EncounteredUpperLevel);
+ Assert.Matches("1", packetToken.Token.ToString());
- var listEnumerator = stringEnumerator.CreateLevel('|');
- listEnumerator.PrepareLevel('.');
+ stringEnumerator.PushLevel('|');
+ stringEnumerator.PrepareLevel('.');
for (int i = 0; i < 3; i++)
{
- var preparedLevel = listEnumerator.CreatePreparedLevel();
- Assert.NotNull(preparedLevel);
+ stringEnumerator.PushPreparedLevel();
for (int j = 0; j < 3; j++)
{
string currentNum = (j + (i * 3) + 1 + 10).ToString();
- var currentToken = preparedLevel!.Value.GetNextToken();
+ var currentToken = stringEnumerator.GetNextToken(out packetToken);
Assert.True(currentToken.IsSuccess);
- Assert.False(currentToken.Entity.PacketEndReached);
- Assert.NotNull(currentToken.Entity.IsLast);
- Assert.NotNull(currentToken.Entity.EncounteredUpperLevel);
+ Assert.False(packetToken.PacketEndReached);
+ Assert.NotNull(packetToken.IsLast);
+ Assert.NotNull(packetToken.EncounteredUpperLevel);
if (j == 2 && i == 2)
{
- Assert.True(currentToken.Entity.EncounteredUpperLevel);
+ Assert.True(packetToken.EncounteredUpperLevel);
}
else
{
- Assert.False(currentToken.Entity.EncounteredUpperLevel);
+ Assert.False(packetToken.EncounteredUpperLevel);
}
if (j != 2)
{
- Assert.False(currentToken.Entity.IsLast);
+ Assert.False(packetToken.IsLast);
}
else
{
- Assert.True(currentToken.Entity.IsLast);
+ Assert.True(packetToken.IsLast);
}
- Assert.Matches(currentNum, currentToken.Entity.Token);
+ Assert.Matches(currentNum, packetToken.Token.ToString());
}
- Assert.True(preparedLevel!.Value.IsOnLastToken());
+ Assert.True(stringEnumerator.IsOnLastToken());
+ stringEnumerator.PopLevel();
}
+ stringEnumerator.PopLevel();
Assert.True(stringEnumerator.IsOnLastToken());
}
@@ 91,18 92,18 @@ public class PacketStringEnumeratorTests
public void EnumeratorDoesNotAllowOvereachingPacketEnd()
{
var stringEnumerator = new PacketStringEnumerator("in 1 2 3 4");
- var tokenResult = stringEnumerator.GetNextToken();
+ var tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess); // in
- tokenResult = stringEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess); // 1
- tokenResult = stringEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess); // 2
- tokenResult = stringEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess); // 3
- tokenResult = stringEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess); // 4
- tokenResult = stringEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.False(tokenResult.IsSuccess);
Assert.IsType<PacketEndReachedError>(tokenResult.Error);
}
@@ 114,20 115,20 @@ public class PacketStringEnumeratorTests
public void EnumeratorDoesNotAllowOvereachingListComplexTypeEnd()
{
var stringEnumerator = new PacketStringEnumerator("in 1|2.2|3.3|4.4|5");
- var tokenResult = stringEnumerator.GetNextToken();
+ var tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess); // in
- var listEnumerator = stringEnumerator.CreateLevel('.');
- var itemEnumerator = listEnumerator.CreateLevel('|');
+ stringEnumerator.PushLevel('.');
+ stringEnumerator.PushLevel('|');
- tokenResult = itemEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess); // 1
- tokenResult = itemEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out var packetToken);
Assert.True(tokenResult.IsSuccess); // 2
- Assert.True(tokenResult.Entity.IsLast);
+ Assert.True(packetToken.IsLast);
- tokenResult = itemEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.False(tokenResult.IsSuccess);
Assert.IsType<PacketEndReachedError>(tokenResult.Error);
Assert.True(((PacketEndReachedError)tokenResult.Error!).LevelEnd);
@@ 140,33 141,37 @@ public class PacketStringEnumeratorTests
public void EnumeratorDoesNotAllowOvereachingListLength()
{
var stringEnumerator = new PacketStringEnumerator("in 1|2.2|3.3|4.4|5");
- var tokenResult = stringEnumerator.GetNextToken();
+ var tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess); // in
- var listEnumerator = stringEnumerator.CreateLevel('.', 2);
- var itemEnumerator = listEnumerator.CreateLevel('|');
+ stringEnumerator.PushLevel('.', 2);
+ stringEnumerator.PushLevel('|');
// first item
- tokenResult = itemEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess);
- tokenResult = itemEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out var packetToken);
Assert.True(tokenResult.IsSuccess);
- Assert.True(tokenResult.Entity.IsLast);
+ Assert.True(packetToken.IsLast);
+
+ stringEnumerator.PopLevel();
// second item
- itemEnumerator = listEnumerator.CreateLevel('|');
- tokenResult = itemEnumerator.GetNextToken();
+ stringEnumerator.PushLevel('|');
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess);
- tokenResult = itemEnumerator.GetNextToken();
+ stringEnumerator.GetNextToken(out packetToken);
Assert.True(tokenResult.IsSuccess);
- Assert.True(tokenResult.Entity.IsLast);
+ Assert.True(packetToken.IsLast);
+
+ stringEnumerator.PopLevel();
// cannot reach third item
- Assert.True(listEnumerator.IsOnLastToken());
- itemEnumerator = listEnumerator.CreateLevel('|');
- tokenResult = itemEnumerator.GetNextToken();
+ Assert.True(stringEnumerator.IsOnLastToken());
+ stringEnumerator.PushLevel('|');
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.False(tokenResult.IsSuccess);
Assert.IsType<PacketEndReachedError>(tokenResult.Error);
Assert.True(((PacketEndReachedError)tokenResult.Error!).LevelEnd);
@@ 179,18 184,18 @@ public class PacketStringEnumeratorTests
public void EnumeratorReturnsEncounteredUpperLevel()
{
var stringEnumerator = new PacketStringEnumerator("in 1|2 1");
- var tokenResult = stringEnumerator.GetNextToken();
+ var tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess); // in
- var listEnumerator = stringEnumerator.CreateLevel('.');
- var itemEnumerator = listEnumerator.CreateLevel('|');
+ stringEnumerator.PushLevel('.');
+ stringEnumerator.PushLevel('|');
- tokenResult = itemEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out _);
Assert.True(tokenResult.IsSuccess);
- tokenResult = itemEnumerator.GetNextToken();
+ tokenResult = stringEnumerator.GetNextToken(out var packetToken);
Assert.True(tokenResult.IsSuccess);
- Assert.True(tokenResult.Entity.IsLast);
- Assert.True(tokenResult.Entity.EncounteredUpperLevel);
+ Assert.True(packetToken.IsLast);
+ Assert.True(packetToken.EncounteredUpperLevel);
}
}=
\ No newline at end of file