~ruther/NosSmooth

5b880eadd917d5af4c6f84bea3b1640d63a65722 — František Boháček 3 years ago b528a6c
feat(packets)!: let the user add the default packet converters
A Packets/NosSmooth.PacketSerializer/Extensions/PacketTypesRepositoryExtensions.cs => Packets/NosSmooth.PacketSerializer/Extensions/PacketTypesRepositoryExtensions.cs +42 -0
@@ 0,0 1,42 @@
//
//  PacketTypesRepositoryExtensions.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.Linq;
using System.Reflection;
using NosSmooth.Packets.Packets;
using Remora.Results;

namespace NosSmooth.Packets.Extensions;

/// <summary>
/// Extension methods for <see cref="IPacketTypesRepository"/>.
/// </summary>
public static class PacketTypesRepositoryExtensions
{
    /// <summary>
    /// Add packets from the given assembly.
    /// </summary>
    /// <param name="packetTypesRepository">The packet types repository.</param>
    /// <param name="assembly">The assembly to add packets from.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public static Result AddPacketTypes(this IPacketTypesRepository packetTypesRepository, Assembly assembly)
    {
        var packetTypes = assembly
            .GetExportedTypes()
            .Where(x => x != typeof(UnresolvedPacket) && !x.IsAbstract && typeof(IPacket).IsAssignableFrom(x));
        return packetTypesRepository.AddPacketTypes(packetTypes);
    }

    /// <summary>
    /// Adds the default NosSmooth packets.
    /// </summary>
    /// <param name="packetTypesRepository">The packet types repository.</param>
    /// <returns>A result tht may or may not have succeeded.</returns>
    public static Result AddDefaultPackets(this IPacketTypesRepository packetTypesRepository)
    {
        return packetTypesRepository.AddPacketTypes(typeof(IPacket).Assembly);
    }
}
\ No newline at end of file

M Packets/NosSmooth.PacketSerializer/Extensions/ServiceCollectionExtensions.cs => Packets/NosSmooth.PacketSerializer/Extensions/ServiceCollectionExtensions.cs +1 -18
@@ 38,24 38,7 @@ public static class ServiceCollectionExtensions
            .AddSingleton<IStringConverterRepository, StringConverterRepository>()
            .AddSingleton<IStringSerializer, StringSerializer>()
            .AddSingleton<IPacketSerializer, PacketSerializer>()
            .AddSingleton<IPacketTypesRepository>(p =>
            {
                var repository = new PacketTypesRepository(p.GetRequiredService<IStringConverterRepository>());
                var packetTypes = typeof(IPacket).Assembly
                    .GetExportedTypes()
                    .Where(x => x != typeof(UnresolvedPacket) && !x.IsAbstract && typeof(IPacket).IsAssignableFrom(x));
                foreach (var packetType in packetTypes)
                {
                    var result = repository.AddPacketType(packetType);
                    if (!result.IsSuccess)
                    {
                        // TODO: figure out how to handle this.
                        throw new Exception(packetType + ": " + result.Error.Message);
                    }
                }

                return repository;
            })
            .AddSingleton<IPacketTypesRepository, PacketTypesRepository>()
            .AddGeneratedSerializers(typeof(IPacket).Assembly)
            .AddBasicConverters();
    }

M Packets/NosSmooth.PacketSerializer/Packets/IPacketTypesRepository.cs => Packets/NosSmooth.PacketSerializer/Packets/IPacketTypesRepository.cs +13 -0
@@ 26,6 26,19 @@ public interface IPacketTypesRepository
    public Result AddPacketType(Type type);

    /// <summary>
    /// Add all of the given packet types.
    /// </summary>
    /// <remarks>
    /// If there is an error, it will continue to add the rest of the types
    /// and then return an aggregate error containing all the errors.
    ///
    /// The application can still run, but without the errorful packets.
    /// </remarks>
    /// <param name="packetTypes">The types add.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Result AddPacketTypes(IEnumerable<Type> packetTypes);

    /// <summary>
    /// Gets the type of a packet that corresponds to the given header.
    /// </summary>
    /// <param name="header">The header of the packet.</param>

M Packets/NosSmooth.PacketSerializer/Packets/PacketTypesRepository.cs => Packets/NosSmooth.PacketSerializer/Packets/PacketTypesRepository.cs +25 -3
@@ 46,13 46,13 @@ public class PacketTypesRepository : IPacketTypesRepository
    {
        if (!typeof(IPacket).IsAssignableFrom(type))
        {
            return new ArgumentInvalidError(nameof(type), "The type has to be assignable to IPacket.");
            return new ArgumentInvalidError(nameof(type), $"The type has to be assignable to IPacket. {type.FullName} isn't.");
        }

        var header = type.GetCustomAttribute<PacketHeaderAttribute>();
        if (header is null)
        {
            return new ArgumentInvalidError(nameof(type), "Every packet has to specify the header.");
            return new ArgumentInvalidError(nameof(type), $"Every packet has to specify the header. {type.FullName} didn't.");
        }

        var converterResult = _stringConverterRepository.GetTypeConverter(type);


@@ 91,6 91,27 @@ public class PacketTypesRepository : IPacketTypesRepository
        return Result.FromSuccess();
    }

    /// <inheritdoc />
    public Result AddPacketTypes(IEnumerable<Type> packetTypes)
    {
        var errorResults = new List<IResult>();
        foreach (var packetType in packetTypes)
        {
            var result = AddPacketType(packetType);
            if (!result.IsSuccess)
            {
                errorResults.Add(result);
            }
        }

        return errorResults.Count switch
        {
            0 => Result.FromSuccess(),
            1 => (Result)errorResults[0],
            _ => new AggregateError(errorResults)
        };
    }

    /// <summary>
    /// Gets the type of a packet that corresponds to the given header.
    /// </summary>


@@ 133,7 154,8 @@ public class PacketTypesRepository : IPacketTypesRepository
    /// </summary>
    /// <typeparam name="TPacket">The type of the packet.</typeparam>
    /// <returns>Info that stores the packet's info. Or an error, if not found.</returns>
    public Result<PacketInfo> FindPacketInfo<TPacket>() where TPacket : IPacket
    public Result<PacketInfo> FindPacketInfo<TPacket>()
        where TPacket : IPacket
        => FindPacketInfo(typeof(TPacket));

    /// <summary>

Do not follow this link