M Core/NosSmooth.Core/Extensions/ServiceCollectionExtensions.cs => Core/NosSmooth.Core/Extensions/ServiceCollectionExtensions.cs +13 -0
@@ 166,4 166,17 @@ public static class ServiceCollectionExtensions
return serviceCollection;
}
+
+ /// <summary>
+ /// Adds the specified packet converter.
+ /// </summary>
+ /// <param name="serviceCollection">The service collection to register the responder to.</param>
+ /// <typeparam name="TPacketConverter">The type of the packet.</typeparam>
+ /// <exception cref="ArgumentException">Thrown if the type of the responder is incorrect.</exception>
+ /// <returns>The collection.</returns>
+ public static IServiceCollection AddSpecificPacketConverter<TPacketConverter>(this IServiceCollection serviceCollection)
+ where TPacketConverter : class, ISpecificPacketSerializer
+ {
+ return serviceCollection.AddSingleton<ISpecificPacketSerializer, TPacketConverter>();
+ }
}=
\ No newline at end of file
A Core/NosSmooth.Core/Packets/Converters/ISpecificPacketSerializer.cs => Core/NosSmooth.Core/Packets/Converters/ISpecificPacketSerializer.cs +132 -0
@@ 0,0 1,132 @@
+//
+// ISpecificPacketSerializer.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.Reflection;
+using NosCore.Packets.Attributes;
+using NosCore.Packets.Interfaces;
+using Remora.Results;
+
+namespace NosSmooth.Core.Packets.Converters;
+
+/// <summary>
+/// Converts packets that cannot be handled easily by the default serializer.
+/// </summary>
+public interface ISpecificPacketSerializer
+{
+ /// <summary>
+ /// Gets whether this is a serializer.
+ /// </summary>
+ public bool Serializer { get; }
+
+ /// <summary>
+ /// Gets whether this is a deserializer.
+ /// </summary>
+ public bool Deserializer { get; }
+
+ /// <summary>
+ /// Whether the current packet serializer should handle the packet.
+ /// </summary>
+ /// <param name="packetString">The string of the packet.</param>
+ /// <returns>If this serializer should be used for handling.</returns>
+ public bool ShouldHandle(string packetString);
+
+ /// <summary>
+ /// Whether the current packet serializer should handle the packet.
+ /// </summary>
+ /// <param name="packet">The packet object.</param>
+ /// <returns>If this serializer should be used for handling.</returns>
+ public bool ShouldHandle(IPacket packet);
+
+ /// <summary>
+ /// Serialize the given packet into string.
+ /// </summary>
+ /// <param name="packet">The string of the packet.</param>
+ /// <returns>The serialized packet or an error.</returns>
+ public Result<string> Serialize(IPacket packet);
+
+ /// <summary>
+ /// Deserialize the given packet to its type.
+ /// </summary>
+ /// <param name="packetString">The string of the packet.</param>
+ /// <returns>The deserialized packet or an error.</returns>
+ public Result<IPacket> Deserialize(string packetString);
+}
+
+/// <summary>
+/// Converts packets that cannot be handled easily by the default serializer.
+/// </summary>
+/// <typeparam name="TPacket">The packet.</typeparam>
+public abstract class SpecificPacketSerializer<TPacket> : ISpecificPacketSerializer
+ where TPacket : IPacket
+{
+ private string? _packetHeader;
+
+ /// <summary>
+ /// Gets the packet header identifier.
+ /// </summary>
+ public string PacketHeader
+ {
+ get
+ {
+ if (_packetHeader is null)
+ {
+ _packetHeader = typeof(TPacket).GetCustomAttribute<PacketHeaderAttribute>()!.Identification + " ";
+ }
+
+ return _packetHeader;
+ }
+ }
+
+ /// <inheritdoc />
+ public abstract bool Serializer { get; }
+
+ /// <inheritdoc />
+ public abstract bool Deserializer { get; }
+
+ /// <inheritdoc />
+ public bool ShouldHandle(string packetString)
+ {
+ return packetString.StartsWith(PacketHeader);
+ }
+
+ /// <inheritdoc />
+ public bool ShouldHandle(IPacket packet)
+ {
+ return typeof(TPacket) == packet.GetType();
+ }
+
+ /// <inheritdoc/>
+ Result<string> ISpecificPacketSerializer.Serialize(IPacket packet)
+ {
+ return Serialize((TPacket)packet);
+ }
+
+ /// <inheritdoc/>
+ Result<IPacket> ISpecificPacketSerializer.Deserialize(string packetString)
+ {
+ var result = Deserialize(packetString);
+ if (!result.IsSuccess)
+ {
+ return Result<IPacket>.FromError(result);
+ }
+
+ return Result<IPacket>.FromSuccess(result.Entity);
+ }
+
+ /// <summary>
+ /// Serialize the given packet into string.
+ /// </summary>
+ /// <param name="packet">The string of the packet.</param>
+ /// <returns>The serialized packet or an error.</returns>
+ public abstract Result<string> Serialize(TPacket packet);
+
+ /// <summary>
+ /// Deserialize the given packet to its type.
+ /// </summary>
+ /// <param name="packetString">The string of the packet.</param>
+ /// <returns>The deserialized packet or an error.</returns>
+ public abstract Result<TPacket> Deserialize(string packetString);
+}<
\ No newline at end of file
M Core/NosSmooth.Core/Packets/IPacketSerializer.cs => Core/NosSmooth.Core/Packets/IPacketSerializer.cs +14 -0
@@ 4,6 4,8 @@
// 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 NosCore.Packets;
using NosCore.Packets.Interfaces;
using Remora.Results;
@@ 27,4 29,16 @@ public interface IPacketSerializer
/// <param name="packetString">The packet to deserialize.</param>
/// <returns>The deserialized packet.</returns>
public Result<IPacket> Deserialize(string packetString);
+
+ /// <summary>
+ /// Gets the inner serializer from NosCore.
+ /// </summary>
+ [Obsolete("May be removed anytime.")]
+ public Serializer Serializer { get; }
+
+ /// <summary>
+ /// Gets the inner deserializer from NosCore.
+ /// </summary>
+ [Obsolete("May be removed anytime.")]
+ public Deserializer Deserializer { get; }
}=
\ No newline at end of file
M Core/NosSmooth.Core/Packets/PacketSerializer.cs => Core/NosSmooth.Core/Packets/PacketSerializer.cs +33 -2
@@ 5,9 5,10 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
-using System.Threading.Tasks;
+using System.Collections.Generic;
using NosCore.Packets;
using NosCore.Packets.Interfaces;
+using NosSmooth.Core.Packets.Converters;
using Remora.Results;
namespace NosSmooth.Core.Packets;
@@ 17,16 18,24 @@ public class PacketSerializer : IPacketSerializer
{
private readonly Serializer _serializer;
private readonly Deserializer _deserializer;
+ private readonly IEnumerable<ISpecificPacketSerializer> _specificPacketSerializers;
/// <summary>
/// Initializes a new instance of the <see cref="PacketSerializer"/> class.
/// </summary>
/// <param name="serializer">The NosCore serializer.</param>
/// <param name="deserializer">The NosCore deserializer.</param>
- public PacketSerializer(Serializer serializer, Deserializer deserializer)
+ /// <param name="specificPacketSerializers">The specific packet serializers.</param>
+ public PacketSerializer
+ (
+ Serializer serializer,
+ Deserializer deserializer,
+ IEnumerable<ISpecificPacketSerializer> specificPacketSerializers
+ )
{
_serializer = serializer;
_deserializer = deserializer;
+ _specificPacketSerializers = specificPacketSerializers;
}
/// <inheritdoc />
@@ 34,6 43,14 @@ public class PacketSerializer : IPacketSerializer
{
try
{
+ foreach (var specificPacketSerializer in _specificPacketSerializers)
+ {
+ if (specificPacketSerializer.Serializer && specificPacketSerializer.ShouldHandle(packet))
+ {
+ return specificPacketSerializer.Serialize(packet);
+ }
+ }
+
return _serializer.Serialize(packet);
}
catch (Exception e)
@@ 47,6 64,14 @@ public class PacketSerializer : IPacketSerializer
{
try
{
+ foreach (var specificPacketSerializer in _specificPacketSerializers)
+ {
+ if (specificPacketSerializer.Deserializer && specificPacketSerializer.ShouldHandle(packetString))
+ {
+ return specificPacketSerializer.Deserialize(packetString);
+ }
+ }
+
return Result<IPacket>.FromSuccess(_deserializer.Deserialize(packetString));
}
catch (Exception e)
@@ 54,4 79,10 @@ public class PacketSerializer : IPacketSerializer
return e;
}
}
+
+ /// <inheritdoc />
+ public Serializer Serializer => _serializer;
+
+ /// <inheritdoc />
+ public Deserializer Deserializer => _deserializer;
}=
\ No newline at end of file
M Core/NosSmooth.Core/Packets/PacketSerializerProvider.cs => Core/NosSmooth.Core/Packets/PacketSerializerProvider.cs +18 -3
@@ 6,7 6,9 @@
using System;
using System.Collections.Generic;
+using Microsoft.Extensions.DependencyInjection;
using NosCore.Packets;
+using NosSmooth.Core.Packets.Converters;
namespace NosSmooth.Core.Packets;
@@ 20,16 22,19 @@ public class PacketSerializerProvider
private IPacketSerializer? _serverSerializer;
private IPacketSerializer? _clientSerializer;
+ private IServiceProvider _serviceProvider;
/// <summary>
/// Initializes a new instance of the <see cref="PacketSerializerProvider"/> class.
/// </summary>
/// <param name="clientPacketTypes">The types of client packets.</param>
/// <param name="serverPacketTypes">The types of server packets.</param>
- public PacketSerializerProvider(List<Type> clientPacketTypes, List<Type> serverPacketTypes)
+ /// <param name="serviceProvider">The service provider for dependency injection.</param>
+ public PacketSerializerProvider(List<Type> clientPacketTypes, List<Type> serverPacketTypes, IServiceProvider serviceProvider)
{
_clientPacketTypes = clientPacketTypes;
_serverPacketTypes = serverPacketTypes;
+ _serviceProvider = serviceProvider;
}
/// <summary>
@@ 42,7 47,12 @@ public class PacketSerializerProvider
if (_serverSerializer is null)
{
_serverSerializer =
- new PacketSerializer(new Serializer(_serverPacketTypes), new Deserializer(_serverPacketTypes));
+ new PacketSerializer
+ (
+ new Serializer(_serverPacketTypes),
+ new Deserializer(_serverPacketTypes),
+ _serviceProvider.GetServices<ISpecificPacketSerializer>()
+ );
}
return _serverSerializer;
@@ 59,7 69,12 @@ public class PacketSerializerProvider
if (_clientSerializer is null)
{
_clientSerializer =
- new PacketSerializer(new Serializer(_clientPacketTypes), new Deserializer(_clientPacketTypes));
+ new PacketSerializer
+ (
+ new Serializer(_clientPacketTypes),
+ new Deserializer(_clientPacketTypes),
+ _serviceProvider.GetServices<ISpecificPacketSerializer>()
+ );
}
return _clientSerializer;