// 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. <#@include file="TypeInfo.ttinclude" #> using System; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace CommunityToolkit.Diagnostics { /// /// Helper methods to verify conditions when running code. /// public static partial class Guard { <# GenerateTextForItems(EnumerableTypes, item => { #> /// /// Asserts that the input <#=item.XmlType#> instance must be empty. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input <#=item.XmlType#> instance to check the size for. /// The name of the input parameter being tested. /// Thrown if the size of is != 0. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsEmpty(<#=item.Type#> <#=item.Name#>, [CallerArgumentExpression("<#=item.Name#>")] string name = "") { if (<#=item.Name#>.<#=item.Size#> == 0) { return; } ThrowHelper.ThrowArgumentExceptionForIsEmpty(<#=item.Cast#><#=item.Name#>, name); } /// /// Asserts that the input <#=item.XmlType#> instance must not be empty. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input <#=item.XmlType#> instance to check the size for. /// The name of the input parameter being tested. /// Thrown if the size of is == 0. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsNotEmpty(<#=item.Type#> <#=item.Name#>, [CallerArgumentExpression("<#=item.Name#>")] string name = "") { if (<#=item.Name#>.<#=item.Size#> != 0) { return; } <# if (item.Type == "Span") { #> ThrowHelper.ThrowArgumentExceptionForIsNotEmptyWithSpan(name); <# } else if (item.Type == "ReadOnlySpan") { #> ThrowHelper.ThrowArgumentExceptionForIsNotEmptyWithReadOnlySpan(name); <# } else { #> ThrowHelper.ThrowArgumentExceptionForIsNotEmpty<<#=item.Type#>>(name); <# } #> } /// /// Asserts that the input <#=item.XmlType#> instance must have a size of a specified value. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input <#=item.XmlType#> instance to check the size for. /// The target size to test. /// The name of the input parameter being tested. /// Thrown if the size of is != . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void HasSizeEqualTo(<#=item.Type#> <#=item.Name#>, int size, [CallerArgumentExpression("<#=item.Name#>")] string name = "") { if (<#=item.Name#>.<#=item.Size#> == size) { return; } ThrowHelper.ThrowArgumentExceptionForHasSizeEqualTo(<#=item.Cast#><#=item.Name#>, size, name); } /// /// Asserts that the input <#=item.XmlType#> instance must have a size not equal to a specified value. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input <#=item.XmlType#> instance to check the size for. /// The target size to test. /// The name of the input parameter being tested. /// Thrown if the size of is == . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void HasSizeNotEqualTo(<#=item.Type#> <#=item.Name#>, int size, [CallerArgumentExpression("<#=item.Name#>")] string name = "") { if (<#=item.Name#>.<#=item.Size#> != size) { return; } ThrowHelper.ThrowArgumentExceptionForHasSizeNotEqualTo(<#=item.Cast#><#=item.Name#>, size, name); } /// /// Asserts that the input <#=item.XmlType#> instance must have a size over a specified value. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input <#=item.XmlType#> instance to check the size for. /// The target size to test. /// The name of the input parameter being tested. /// Thrown if the size of is <= . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void HasSizeGreaterThan(<#=item.Type#> <#=item.Name#>, int size, [CallerArgumentExpression("<#=item.Name#>")] string name = "") { if (<#=item.Name#>.<#=item.Size#> > size) { return; } ThrowHelper.ThrowArgumentExceptionForHasSizeGreaterThan(<#=item.Cast#><#=item.Name#>, size, name); } /// /// Asserts that the input <#=item.XmlType#> instance must have a size of at least or equal to a specified value. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input <#=item.XmlType#> instance to check the size for. /// The target size to test. /// The name of the input parameter being tested. /// Thrown if the size of is < . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void HasSizeGreaterThanOrEqualTo(<#=item.Type#> <#=item.Name#>, int size, [CallerArgumentExpression("<#=item.Name#>")] string name = "") { if (<#=item.Name#>.<#=item.Size#> >= size) { return; } ThrowHelper.ThrowArgumentExceptionForHasSizeGreaterThanOrEqualTo(<#=item.Cast#><#=item.Name#>, size, name); } /// /// Asserts that the input <#=item.XmlType#> instance must have a size of less than a specified value. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input <#=item.XmlType#> instance to check the size for. /// The target size to test. /// The name of the input parameter being tested. /// Thrown if the size of is >= . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void HasSizeLessThan(<#=item.Type#> <#=item.Name#>, int size, [CallerArgumentExpression("<#=item.Name#>")] string name = "") { if (<#=item.Name#>.<#=item.Size#> < size) { return; } ThrowHelper.ThrowArgumentExceptionForHasSizeLessThan(<#=item.Cast#><#=item.Name#>, size, name); } /// /// Asserts that the input <#=item.XmlType#> instance must have a size of less than or equal to a specified value. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input <#=item.XmlType#> instance to check the size for. /// The target size to test. /// The name of the input parameter being tested. /// Thrown if the size of is > . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void HasSizeLessThanOrEqualTo(<#=item.Type#> <#=item.Name#>, int size, [CallerArgumentExpression("<#=item.Name#>")] string name = "") { if (<#=item.Name#>.<#=item.Size#> <= size) { return; } ThrowHelper.ThrowArgumentExceptionForHasSizeLessThanOrEqualTo(<#=item.Cast#><#=item.Name#>, size, name); } /// /// Asserts that the source <#=item.XmlType#> instance must have the same size of a destination <#=item.XmlType#> instance. /// /// The item of items in the input <#=item.XmlType#> instance. /// The source <#=item.XmlType#> instance to check the size for. /// The destination <#=item.XmlType#> instance to check the size for. /// The name of the input parameter being tested. /// Thrown if the size of is != the one of . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void HasSizeEqualTo(<#=item.Type#> source, <#=item.DestinationType#> destination, [CallerArgumentExpression("source")] string name = "") { if (source.<#=item.Size#> == destination.<#=item.Size#>) { return; } <# if (item.HasCountProperty) { #> ThrowHelper.ThrowArgumentExceptionForHasSizeEqualTo(<#=item.Cast#>source, destination.<#=item.Size#>, name); <# } else { #> ThrowHelper.ThrowArgumentExceptionForHasSizeEqualTo(source, <#=item.Cast#>destination, name); <# } #> } /// /// Asserts that the source <#=item.XmlType#> instance must have a size of less than or equal to that of a destination <#=item.XmlType#> instance. /// /// The item of items in the input <#=item.XmlType#> instance. /// The source <#=item.XmlType#> instance to check the size for. /// The destination <#=item.XmlType#> instance to check the size for. /// The name of the input parameter being tested. /// Thrown if the size of is > the one of . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void HasSizeLessThanOrEqualTo(<#=item.Type#> source, <#=item.DestinationType#> destination, [CallerArgumentExpression("source")] string name = "") { if (source.<#=item.Size#> <= destination.<#=item.Size#>) { return; } <# if (item.HasCountProperty) { #> ThrowHelper.ThrowArgumentExceptionForHasSizeEqualTo(<#=item.Cast#>source, destination.<#=item.Size#>, name); <# } else { #> ThrowHelper.ThrowArgumentExceptionForHasSizeLessThanOrEqualTo(source, <#=item.Cast#>destination, name); <# } #> } /// /// Asserts that the input index is valid for a given <#=item.XmlType#> instance. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input index to be used to access . /// The input <#=item.XmlType#> instance to use to validate . /// The name of the input parameter being tested. /// Thrown if is not valid to access . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsInRangeFor(int index, <#=item.Type#> <#=item.Name#>, [CallerArgumentExpression("index")] string name = "") { <# // Here we're leveraging the fact that signed integers are represented // in 2-complement to perform the bounds check with a single compare operation. // This is the same trick used throughout CoreCLR as well. // For more info and code sample, see the original conversation here: // https://github.com/CommunityToolkit/WindowsCommunityToolkit/pull/3131#discussion_r390682835 #> if ((uint)index < (uint)<#=item.Name#>.<#=item.Size#>) { return; } ThrowHelper.ThrowArgumentOutOfRangeExceptionForIsInRangeFor(index, <#=item.Cast#><#=item.Name#>, name); } /// /// Asserts that the input index is not valid for a given <#=item.XmlType#> instance. /// /// The item of items in the input <#=item.XmlType#> instance. /// The input index to be used to access . /// The input <#=item.XmlType#> instance to use to validate . /// The name of the input parameter being tested. /// Thrown if is valid to access . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsNotInRangeFor(int index, <#=item.Type#> <#=item.Name#>, [CallerArgumentExpression("index")] string name = "") { if ((uint)index >= (uint)<#=item.Name#>.<#=item.Size#>) { return; } ThrowHelper.ThrowArgumentOutOfRangeExceptionForIsNotInRangeFor(index, <#=item.Cast#><#=item.Name#>, name); } <# }); #> } }