// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace SixLabors {
///
/// Provides methods to protect against invalid parameters for a DEBUG build.
///
[DebuggerStepThrough]
#pragma warning disable RCS1043 // Remove 'partial' modifier from type with a single part.
internal static partial class DebugGuard
#pragma warning restore RCS1043 // Remove 'partial' modifier from type with a single part.
{
///
/// Ensures that the value is not null.
///
/// The target object, which cannot be null.
/// The name of the parameter that is to be checked.
/// The type of the value.
/// is null.
[Conditional("DEBUG")]
public static void NotNull([NotNull] TValue? value, [CallerArgumentExpression("value")] string? parameterName = null)
where TValue : class =>
ArgumentNullException.ThrowIfNull(value, parameterName);
///
/// Ensures that the target value is not null, empty, or whitespace.
///
/// The target string, which should be checked against being null or empty.
/// Name of the parameter.
/// is null.
/// is empty or contains only blanks.
[Conditional("DEBUG")]
public static void NotNullOrWhiteSpace([NotNull] string? value, [CallerArgumentExpression("value")] string? paramName = null)
{
ArgumentNullException.ThrowIfNull(value);
if (string.IsNullOrWhiteSpace(value))
{
ThrowArgumentException("Must not be empty or whitespace.", paramName!);
}
}
///
/// Ensures that the specified value is less than a maximum value.
///
/// The target value, which should be validated.
/// The maximum value.
/// The name of the parameter that is to be checked.
/// The type of the value.
///
/// is greater than the maximum value.
///
[Conditional("DEBUG")]
public static void MustBeLessThan(TValue value, TValue max, string parameterName)
where TValue : IComparable
{
if (value.CompareTo(max) >= 0)
{
ThrowArgumentOutOfRangeException(parameterName, $"Value {value} must be less than {max}.");
}
}
///
/// Verifies that the specified value is less than or equal to a maximum value
/// and throws an exception if it is not.
///
/// The target value, which should be validated.
/// The maximum value.
/// The name of the parameter that is to be checked.
/// The type of the value.
///
/// is greater than the maximum value.
///
[Conditional("DEBUG")]
public static void MustBeLessThanOrEqualTo(TValue value, TValue max, string parameterName)
where TValue : IComparable
{
if (value.CompareTo(max) > 0)
{
ThrowArgumentOutOfRangeException(parameterName, $"Value {value} must be less than or equal to {max}.");
}
}
///
/// Verifies that the specified value is greater than a minimum value
/// and throws an exception if it is not.
///
/// The target value, which should be validated.
/// The minimum value.
/// The name of the parameter that is to be checked.
/// The type of the value.
///
/// is less than the minimum value.
///
[Conditional("DEBUG")]
public static void MustBeGreaterThan(TValue value, TValue min, string parameterName)
where TValue : IComparable
{
if (value.CompareTo(min) <= 0)
{
ThrowArgumentOutOfRangeException(
parameterName,
$"Value {value} must be greater than {min}.");
}
}
///
/// Verifies that the specified value is greater than or equal to a minimum value
/// and throws an exception if it is not.
///
/// The target value, which should be validated.
/// The minimum value.
/// The name of the parameter that is to be checked.
/// The type of the value.
///
/// is less than the minimum value.
///
[Conditional("DEBUG")]
public static void MustBeGreaterThanOrEqualTo(TValue value, TValue min, string parameterName)
where TValue : IComparable
{
if (value.CompareTo(min) < 0)
{
ThrowArgumentOutOfRangeException(parameterName, $"Value {value} must be greater than or equal to {min}.");
}
}
///
/// Verifies that the specified value is greater than or equal to a minimum value and less than
/// or equal to a maximum value and throws an exception if it is not.
///
/// The target value, which should be validated.
/// The minimum value.
/// The maximum value.
/// The name of the parameter that is to be checked.
/// The type of the value.
///
/// is less than the minimum value of greater than the maximum value.
///
[Conditional("DEBUG")]
public static void MustBeBetweenOrEqualTo(TValue value, TValue min, TValue max, string parameterName)
where TValue : IComparable
{
if (value.CompareTo(min) < 0 || value.CompareTo(max) > 0)
{
ThrowArgumentOutOfRangeException(
parameterName,
$"Value {value} must be greater than or equal to {min} and less than or equal to {max}.");
}
}
///
/// Verifies, that the method parameter with specified target value is true
/// and throws an exception if it is found to be so.
///
/// The target value, which cannot be false.
/// The name of the parameter that is to be checked.
/// The error message, if any to add to the exception.
///
/// is false.
///
[Conditional("DEBUG")]
public static void IsTrue(bool target, string parameterName, string message)
{
if (!target)
{
ThrowArgumentException(message, parameterName);
}
}
///
/// Verifies, that the method parameter with specified target value is false
/// and throws an exception if it is found to be so.
///
/// The target value, which cannot be true.
/// The name of the parameter that is to be checked.
/// The error message, if any to add to the exception.
///
/// is true.
///
[Conditional("DEBUG")]
public static void IsFalse(bool target, string parameterName, string message)
{
if (target)
{
ThrowArgumentException(message, parameterName);
}
}
///
/// Verifies, that the `source` span has the length of 'minLength', or longer.
///
/// The element type of the spans.
/// The source span.
/// The minimum length.
/// The name of the parameter that is to be checked.
///
/// has less than items.
///
[Conditional("DEBUG")]
public static void MustBeSizedAtLeast(ReadOnlySpan source, int minLength, string parameterName)
{
if (source.Length < minLength)
{
ThrowArgumentException($"Span-s must be at least of length {minLength}!", parameterName);
}
}
///
/// Verifies, that the `source` span has the length of 'minLength', or longer.
///
/// The element type of the spans.
/// The target span.
/// The minimum length.
/// The name of the parameter that is to be checked.
///
/// has less than items.
///
[Conditional("DEBUG")]
public static void MustBeSizedAtLeast(Span source, int minLength, string parameterName)
{
if (source.Length < minLength)
{
ThrowArgumentException($"The size must be at least {minLength}.", parameterName);
}
}
///
/// Verifies that the 'destination' span is not shorter than 'source'.
///
/// The source element type.
/// The destination element type.
/// The source span.
/// The destination span.
/// The name of the argument for 'destination'.
[Conditional("DEBUG")]
public static void DestinationShouldNotBeTooShort(
ReadOnlySpan source,
Span destination,
string destinationParamName)
{
if (destination.Length < source.Length)
{
ThrowArgumentException($"Destination span is too short!", destinationParamName);
}
}
///
/// Verifies that the 'destination' span is not shorter than 'source'.
///
/// The source element type.
/// The destination element type.
/// The source span.
/// The destination span.
/// The name of the argument for 'destination'.
[Conditional("DEBUG")]
public static void DestinationShouldNotBeTooShort(
Span source,
Span destination,
string destinationParamName)
{
if (destination.Length < source.Length)
{
ThrowArgumentException($"Destination span is too short!", destinationParamName);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowArgumentException(string message, string parameterName) =>
throw new ArgumentException(message, parameterName);
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowArgumentOutOfRangeException(string parameterName, string message) =>
throw new ArgumentOutOfRangeException(parameterName, message);
}
}