// This file is provided under The MIT License as part of RiptideNetworking.
// Copyright (c) Tom Weiland
// For additional information please see the included LICENSE.md file or view it on GitHub:
// https://github.com/RiptideNetworking/Riptide/blob/main/LICENSE.md
using Riptide.Utils;
using System;
using System.Reflection;
namespace Riptide
{
/// The exception that is thrown when a does not contain enough unwritten bits to perform an operation.
public class InsufficientCapacityException : Exception
{
/// The message with insufficient remaining capacity.
public readonly Message RiptideMessage;
/// The name of the type which could not be added to the message.
public readonly string TypeName;
/// The number of available bits the type requires in order to be added successfully.
public readonly int RequiredBits;
/// Initializes a new instance.
public InsufficientCapacityException() { }
/// Initializes a new instance with a specified error message.
/// The error message that explains the reason for the exception.
public InsufficientCapacityException(string message) : base(message) { }
/// Initializes a new instance with a specified error message and a reference to the inner exception that is the cause of this exception.
/// The error message that explains the reason for the exception.
/// The exception that is the cause of the current exception. If is not a null reference, the current exception is raised in a catch block that handles the inner exception.
public InsufficientCapacityException(string message, Exception inner) : base(message, inner) { }
/// Initializes a new instance and constructs an error message from the given information.
/// The message with insufficient remaining capacity.
/// The number of bits which were attempted to be reserved.
public InsufficientCapacityException(Message message, int reserveBits) : base(GetErrorMessage(message, reserveBits))
{
RiptideMessage = message;
TypeName = "reservation";
RequiredBits = reserveBits;
}
/// Initializes a new instance and constructs an error message from the given information.
/// The message with insufficient remaining capacity.
/// The name of the type which could not be added to the message.
/// The number of available bits required for the type to be added successfully.
public InsufficientCapacityException(Message message, string typeName, int requiredBits) : base(GetErrorMessage(message, typeName, requiredBits))
{
RiptideMessage = message;
TypeName = typeName;
RequiredBits = requiredBits;
}
/// Initializes a new instance and constructs an error message from the given information.
/// The message with insufficient remaining capacity.
/// The length of the array which could not be added to the message.
/// The name of the array's type.
/// The number of available bits required for a single element of the array to be added successfully.
public InsufficientCapacityException(Message message, int arrayLength, string typeName, int requiredBits) : base(GetErrorMessage(message, arrayLength, typeName, requiredBits))
{
RiptideMessage = message;
TypeName = $"{typeName}[]";
RequiredBits = requiredBits * arrayLength;
}
/// Constructs the error message from the given information.
/// The error message.
private static string GetErrorMessage(Message message, int reserveBits)
{
return $"Cannot reserve {reserveBits} {Helper.CorrectForm(reserveBits, "bit")} in a message with {message.UnwrittenBits} " +
$"{Helper.CorrectForm(message.UnwrittenBits, "bit")} of remaining capacity!";
}
/// Constructs the error message from the given information.
/// The error message.
private static string GetErrorMessage(Message message, string typeName, int requiredBits)
{
return $"Cannot add a value of type '{typeName}' (requires {requiredBits} {Helper.CorrectForm(requiredBits, "bit")}) to " +
$"a message with {message.UnwrittenBits} {Helper.CorrectForm(message.UnwrittenBits, "bit")} of remaining capacity!";
}
/// Constructs the error message from the given information.
/// The error message.
private static string GetErrorMessage(Message message, int arrayLength, string typeName, int requiredBits)
{
requiredBits *= arrayLength;
return $"Cannot add an array of type '{typeName}[]' with {arrayLength} {Helper.CorrectForm(arrayLength, "element")} (requires {requiredBits} {Helper.CorrectForm(requiredBits, "bit")}) " +
$"to a message with {message.UnwrittenBits} {Helper.CorrectForm(message.UnwrittenBits, "bit")} of remaining capacity!";
}
}
/// The exception that is thrown when a method with a is not marked as .
public class NonStaticHandlerException : Exception
{
/// The type containing the handler method.
public readonly Type DeclaringType;
/// The name of the handler method.
public readonly string HandlerMethodName;
/// Initializes a new instance.
public NonStaticHandlerException() { }
/// Initializes a new instance with a specified error message.
/// The error message that explains the reason for the exception.
public NonStaticHandlerException(string message) : base(message) { }
/// Initializes a new instance with a specified error message and a reference to the inner exception that is the cause of this exception.
/// The error message that explains the reason for the exception.
/// The exception that is the cause of the current exception. If is not a null reference, the current exception is raised in a catch block that handles the inner exception.
public NonStaticHandlerException(string message, Exception inner) : base(message, inner) { }
/// Initializes a new instance and constructs an error message from the given information.
/// The type containing the handler method.
/// The name of the handler method.
public NonStaticHandlerException(Type declaringType, string handlerMethodName) : base(GetErrorMessage(declaringType, handlerMethodName))
{
DeclaringType = declaringType;
HandlerMethodName = handlerMethodName;
}
/// Constructs the error message from the given information.
/// The error message.
private static string GetErrorMessage(Type declaringType, string handlerMethodName)
{
return $"'{declaringType.Name}.{handlerMethodName}' is an instance method, but message handler methods must be static!";
}
}
/// The exception that is thrown when a method with a does not have an acceptable message handler method signature (either or ).
public class InvalidHandlerSignatureException : Exception
{
/// The type containing the handler method.
public readonly Type DeclaringType;
/// The name of the handler method.
public readonly string HandlerMethodName;
/// Initializes a new instance.
public InvalidHandlerSignatureException() { }
/// Initializes a new instance with a specified error message.
/// The error message that explains the reason for the exception.
public InvalidHandlerSignatureException(string message) : base(message) { }
/// Initializes a new instance with a specified error message and a reference to the inner exception that is the cause of this exception.
/// The error message that explains the reason for the exception.
/// The exception that is the cause of the current exception. If is not a null reference, the current exception is raised in a catch block that handles the inner exception.
public InvalidHandlerSignatureException(string message, Exception inner) : base(message, inner) { }
/// Initializes a new instance and constructs an error message from the given information.
/// The type containing the handler method.
/// The name of the handler method.
public InvalidHandlerSignatureException(Type declaringType, string handlerMethodName) : base(GetErrorMessage(declaringType, handlerMethodName))
{
DeclaringType = declaringType;
HandlerMethodName = handlerMethodName;
}
/// Constructs the error message from the given information.
/// The error message.
private static string GetErrorMessage(Type declaringType, string handlerMethodName)
{
return $"'{declaringType.Name}.{handlerMethodName}' doesn't match any acceptable message handler method signatures! Server message handler methods should have a 'ushort' and a '{nameof(Riptide.Message)}' parameter, while client message handler methods should only have a '{nameof(Riptide.Message)}' parameter.";
}
}
/// The exception that is thrown when multiple methods with s are set to handle messages with the same ID and have the same method signature.
public class DuplicateHandlerException : Exception
{
/// The message ID with multiple handler methods.
public readonly ushort Id;
/// The type containing the first handler method.
public readonly Type DeclaringType1;
/// The name of the first handler method.
public readonly string HandlerMethodName1;
/// The type containing the second handler method.
public readonly Type DeclaringType2;
/// The name of the second handler method.
public readonly string HandlerMethodName2;
/// Initializes a new instance with a specified error message.
public DuplicateHandlerException() { }
/// Initializes a new instance with a specified error message.
/// The error message that explains the reason for the exception.
public DuplicateHandlerException(string message) : base(message) { }
/// Initializes a new instance with a specified error message and a reference to the inner exception that is the cause of this exception.
/// The error message that explains the reason for the exception.
/// The exception that is the cause of the current exception. If is not a null reference, the current exception is raised in a catch block that handles the inner exception.
public DuplicateHandlerException(string message, Exception inner) : base(message, inner) { }
/// Initializes a new instance and constructs an error message from the given information.
/// The message ID with multiple handler methods.
/// The first handler method's info.
/// The second handler method's info.
public DuplicateHandlerException(ushort id, MethodInfo method1, MethodInfo method2) : base(GetErrorMessage(id, method1, method2))
{
Id = id;
DeclaringType1 = method1.DeclaringType;
HandlerMethodName1 = method1.Name;
DeclaringType2 = method2.DeclaringType;
HandlerMethodName2 = method2.Name;
}
/// Constructs the error message from the given information.
/// The error message.
private static string GetErrorMessage(ushort id, MethodInfo method1, MethodInfo method2)
{
return $"Message handler methods '{method1.DeclaringType.Name}.{method1.Name}' and '{method2.DeclaringType.Name}.{method2.Name}' are both set to handle messages with ID {id}! Only one handler method is allowed per message ID!";
}
}
}