// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace FisheryLib.Utility.Diagnostics; /// public static partial class Guard { /// /// Asserts that the input value must be . /// /// The input to test. /// The name of the input parameter being tested. /// Thrown if is . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsTrue([DoesNotReturnIf(false)] bool value, [CallerArgumentExpression("value")] string name = "") { if (value) return; ThrowHelper.ThrowArgumentExceptionForIsTrue(name); } /// /// Asserts that the input value must be . /// /// The input to test. /// The name of the input parameter being tested. /// A message to display if is . /// Thrown if is . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsTrue([DoesNotReturnIf(false)] bool value, string name, string message) { if (value) return; ThrowHelper.ThrowArgumentExceptionForIsTrue(name, message); } /// /// Asserts that the input value must be . /// /// The input to test. /// The name of the input parameter being tested. /// Thrown if is . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsFalse([DoesNotReturnIf(true)] bool value, [CallerArgumentExpression("value")] string name = "") { if (!value) return; ThrowHelper.ThrowArgumentExceptionForIsFalse(name); } /// /// Asserts that the input value must be . /// /// The input to test. /// The name of the input parameter being tested. /// A message to display if is . /// Thrown if is . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsFalse([DoesNotReturnIf(true)] bool value, string name, string message) { if (!value) return; ThrowHelper.ThrowArgumentExceptionForIsFalse(name, message); } #if NET6_0_OR_GREATER /// /// Asserts that the input value must be . /// /// The input to test. /// The name of the input parameter being tested. /// A message to display if is . /// Thrown if is . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsTrue([DoesNotReturnIf(false)] bool value, string name, [InterpolatedStringHandlerArgument("value")] ref IsTrueInterpolatedStringHandler message) { if (value) { return; } ThrowHelper.ThrowArgumentExceptionForIsTrue(name, message.ToStringAndClear()); } /// /// Asserts that the input value must be . /// /// The input to test. /// The name of the input parameter being tested. /// A message to display if is . /// Thrown if is . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsFalse([DoesNotReturnIf(true)] bool value, string name, [InterpolatedStringHandlerArgument("value")] ref IsFalseInterpolatedStringHandler message) { if (!value) { return; } ThrowHelper.ThrowArgumentExceptionForIsFalse(name, message.ToStringAndClear()); } /// /// Provides an interpolated string handler for that only performs formatting if the assert fails. /// [EditorBrowsable(EditorBrowsableState.Never)] [InterpolatedStringHandler] public struct IsTrueInterpolatedStringHandler { /// /// The handler used to perform the formatting. /// private StringBuilder.AppendInterpolatedStringHandler handler; /// /// The underlying instance used by , if any. /// private StringBuilder? builder; /// /// Creates an instance of the handler. /// /// The number of constant characters outside of interpolation expressions in the interpolated string. /// The number of interpolation expressions in the interpolated string. /// The condition passed to the method. /// A value indicating whether formatting should proceed. /// This is intended to be called only by compiler-generated code. Arguments are not validated as they'd otherwise be for members intended to be used directly. public IsTrueInterpolatedStringHandler(int literalLength, int formattedCount, bool condition, out bool shouldAppend) { if (condition) { this.handler = default; this.builder = null; shouldAppend = false; } else { StringBuilder builder = new(); this.handler = new StringBuilder.AppendInterpolatedStringHandler(literalLength, formattedCount, builder); this.builder = builder; shouldAppend = true; } } /// /// Extracts the built string from the handler. /// internal string ToStringAndClear() { string message = this.builder?.ToString() ?? string.Empty; this = default; return message; } /// public void AppendLiteral(string value) { this.handler.AppendLiteral(value); } /// public void AppendFormatted(T value) { this.handler.AppendFormatted(value); } /// public void AppendFormatted(T value, string? format) { this.handler.AppendFormatted(value, format); } /// public void AppendFormatted(T value, int alignment) { this.handler.AppendFormatted(value, alignment); } /// public void AppendFormatted(T value, int alignment, string? format) { this.handler.AppendFormatted(value, alignment, format); } /// public void AppendFormatted(ReadOnlySpan value) { this.handler.AppendFormatted(value); } /// public void AppendFormatted(ReadOnlySpan value, int alignment = 0, string? format = null) { this.handler.AppendFormatted(value, alignment, format); } /// public void AppendFormatted(string? value) { this.handler.AppendFormatted(value); } /// public void AppendFormatted(string? value, int alignment = 0, string? format = null) { this.handler.AppendFormatted(value, alignment, format); } /// public void AppendFormatted(object? value, int alignment = 0, string? format = null) { this.handler.AppendFormatted(value, alignment, format); } } /// /// Provides an interpolated string handler for that only performs formatting if the assert fails. /// [EditorBrowsable(EditorBrowsableState.Never)] [InterpolatedStringHandler] public struct IsFalseInterpolatedStringHandler { /// /// The handler used to perform the formatting. /// private StringBuilder.AppendInterpolatedStringHandler handler; /// /// The underlying instance used by , if any. /// private StringBuilder? builder; /// /// Creates an instance of the handler. /// /// The number of constant characters outside of interpolation expressions in the interpolated string. /// The number of interpolation expressions in the interpolated string. /// The condition passed to the method. /// A value indicating whether formatting should proceed. /// This is intended to be called only by compiler-generated code. Arguments are not validated as they'd otherwise be for members intended to be used directly. public IsFalseInterpolatedStringHandler(int literalLength, int formattedCount, bool condition, out bool shouldAppend) { if (!condition) { this.handler = default; this.builder = null; shouldAppend = false; } else { StringBuilder builder = new(); this.handler = new StringBuilder.AppendInterpolatedStringHandler(literalLength, formattedCount, builder); this.builder = builder; shouldAppend = true; } } /// /// Extracts the built string from the handler. /// internal string ToStringAndClear() { string message = this.builder?.ToString() ?? string.Empty; this = default; return message; } /// public void AppendLiteral(string value) { this.handler.AppendLiteral(value); } /// public void AppendFormatted(T value) { this.handler.AppendFormatted(value); } /// public void AppendFormatted(T value, string? format) { this.handler.AppendFormatted(value, format); } /// public void AppendFormatted(T value, int alignment) { this.handler.AppendFormatted(value, alignment); } /// public void AppendFormatted(T value, int alignment, string? format) { this.handler.AppendFormatted(value, alignment, format); } /// public void AppendFormatted(ReadOnlySpan value) { this.handler.AppendFormatted(value); } /// public void AppendFormatted(ReadOnlySpan value, int alignment = 0, string? format = null) { this.handler.AppendFormatted(value, alignment, format); } /// public void AppendFormatted(string? value) { this.handler.AppendFormatted(value); } /// public void AppendFormatted(string? value, int alignment = 0, string? format = null) { this.handler.AppendFormatted(value, alignment, format); } /// public void AppendFormatted(object? value, int alignment = 0, string? format = null) { this.handler.AppendFormatted(value, alignment, format); } } #endif }