From 6d95f6eb088cf9a240addce1725dad4f66cab967 Mon Sep 17 00:00:00 2001 From: KonH Date: Sun, 9 Oct 2022 19:48:22 +0200 Subject: [PATCH 1/6] Add NullOrEmpty and NullOrWhiteSpace overloads for ReadOnlySpan - #220 Related to https://github.com/ardalis/GuardClauses/issues/220 --- .../GuardAgainstNullExtensions.cs | 47 +++++++++++++++++++ .../GuardAgainstNullOrEmpty.cs | 7 +++ .../GuardAgainstNullOrWhiteSpace.cs | 9 ++++ 3 files changed, 63 insertions(+) diff --git a/src/GuardClauses/GuardAgainstNullExtensions.cs b/src/GuardClauses/GuardAgainstNullExtensions.cs index b21617f1..11f34253 100644 --- a/src/GuardClauses/GuardAgainstNullExtensions.cs +++ b/src/GuardClauses/GuardAgainstNullExtensions.cs @@ -79,6 +79,29 @@ public static string NullOrEmpty(this IGuardClause guardClause, return input; } +#if NET5_0_OR_GREATER + /// + /// Throws an if is an empty string. + /// + /// + /// + /// + /// Optional. Custom error message + /// if the value is not an empty string. + /// + public static ReadOnlySpan NullOrEmpty(this IGuardClause guardClause, + ReadOnlySpan input, + string parameterName, + string? message = null) + { + if (input == string.Empty) + { + throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName); + } + return input; + } +#endif + /// /// Throws an if is null. /// Throws an if is an empty guid. @@ -175,6 +198,30 @@ public static string NullOrWhiteSpace(this IGuardClause guardClause, return input; } +#if NET5_0_OR_GREATER + /// + /// Throws an if is an empty or white space string. + /// + /// + /// + /// + /// Optional. Custom error message + /// if the value is not an empty or whitespace string. + /// + public static ReadOnlySpan NullOrWhiteSpace(this IGuardClause guardClause, + ReadOnlySpan input, + string parameterName, + string? message = null) + { + if (input.IsWhiteSpace()) + { + throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName); + } + + return input; + } +#endif + /// /// Throws an if is default for that type. /// diff --git a/test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs b/test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs index 98297c8c..ba9df60f 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs @@ -12,6 +12,7 @@ public class GuardAgainstNullOrEmpty public void DoesNothingGivenNonEmptyStringValue() { Guard.Against.NullOrEmpty("a", "string"); + Guard.Against.NullOrEmpty("a".AsSpan(), "stringSpan"); Guard.Against.NullOrEmpty("1", "aNumericString"); } @@ -41,6 +42,12 @@ public void ThrowsGivenEmptyString() Assert.Throws(() => Guard.Against.NullOrEmpty("", "emptyString")); } + [Fact] + public void ThrowsGivenEmptyStringSpan() + { + Assert.Throws(() => Guard.Against.NullOrEmpty("".AsSpan(), "emptyStringSpan")); + } + [Fact] public void ThrowsGivenNullGuid() { diff --git a/test/GuardClauses.UnitTests/GuardAgainstNullOrWhiteSpace.cs b/test/GuardClauses.UnitTests/GuardAgainstNullOrWhiteSpace.cs index 609d93f0..99bf4105 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstNullOrWhiteSpace.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstNullOrWhiteSpace.cs @@ -15,6 +15,7 @@ public class GuardAgainstNullOrWhiteSpace public void DoesNothingGivenNonEmptyStringValue(string nonEmptyString) { Guard.Against.NullOrWhiteSpace(nonEmptyString, "string"); + Guard.Against.NullOrWhiteSpace(nonEmptyString.AsSpan(), "stringSpan"); Guard.Against.NullOrWhiteSpace(nonEmptyString, "aNumericString"); } @@ -30,12 +31,19 @@ public void ThrowsGivenEmptyString() Assert.Throws(() => Guard.Against.NullOrWhiteSpace("", "emptystring")); } + [Fact] + public void ThrowsGivenEmptyStringSpan() + { + Assert.Throws(() => Guard.Against.NullOrWhiteSpace("".AsSpan(), "emptyStringSpan")); + } + [Theory] [InlineData(" ")] [InlineData(" ")] public void ThrowsGivenWhiteSpaceString(string whiteSpaceString) { Assert.Throws(() => Guard.Against.NullOrWhiteSpace(whiteSpaceString, "whitespacestring")); + Assert.Throws(() => Guard.Against.NullOrWhiteSpace(whiteSpaceString.AsSpan(), "whiteSpaceStringSpan")); } [Theory] @@ -47,6 +55,7 @@ public void ThrowsGivenWhiteSpaceString(string whiteSpaceString) public void ReturnsExpectedValueGivenNonEmptyStringValue(string nonEmptyString, string expected) { Assert.Equal(expected, Guard.Against.NullOrWhiteSpace(nonEmptyString, "string")); + Assert.Equal(expected, Guard.Against.NullOrWhiteSpace(nonEmptyString.AsSpan(), "stringSpan").ToString()); Assert.Equal(expected, Guard.Against.NullOrWhiteSpace(nonEmptyString, "aNumericString")); } From ba2f72345cfe8d03d3d17aaddcd97d879bc8ff54 Mon Sep 17 00:00:00 2001 From: KonH Date: Mon, 10 Oct 2022 20:00:30 +0200 Subject: [PATCH 2/6] Use MemoryExtensions.IsWhiteSpace explicitly --- src/GuardClauses/GuardAgainstNullExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GuardClauses/GuardAgainstNullExtensions.cs b/src/GuardClauses/GuardAgainstNullExtensions.cs index 11f34253..b17aeb62 100644 --- a/src/GuardClauses/GuardAgainstNullExtensions.cs +++ b/src/GuardClauses/GuardAgainstNullExtensions.cs @@ -213,7 +213,7 @@ public static ReadOnlySpan NullOrWhiteSpace(this IGuardClause guardClause, string parameterName, string? message = null) { - if (input.IsWhiteSpace()) + if (MemoryExtensions.IsWhiteSpace(input)) { throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName); } From b63e0c4d04d3c8986547130b45b7d5d811d333db Mon Sep 17 00:00:00 2001 From: KonH Date: Mon, 10 Oct 2022 20:21:50 +0200 Subject: [PATCH 3/6] Change naming - remove actually unused Null prefix --- src/GuardClauses/GuardAgainstNullExtensions.cs | 4 ++-- test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs | 4 ++-- .../GuardAgainstNullOrWhiteSpace.cs | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/GuardClauses/GuardAgainstNullExtensions.cs b/src/GuardClauses/GuardAgainstNullExtensions.cs index b17aeb62..b2843fde 100644 --- a/src/GuardClauses/GuardAgainstNullExtensions.cs +++ b/src/GuardClauses/GuardAgainstNullExtensions.cs @@ -89,7 +89,7 @@ public static string NullOrEmpty(this IGuardClause guardClause, /// Optional. Custom error message /// if the value is not an empty string. /// - public static ReadOnlySpan NullOrEmpty(this IGuardClause guardClause, + public static ReadOnlySpan Empty(this IGuardClause guardClause, ReadOnlySpan input, string parameterName, string? message = null) @@ -208,7 +208,7 @@ public static string NullOrWhiteSpace(this IGuardClause guardClause, /// Optional. Custom error message /// if the value is not an empty or whitespace string. /// - public static ReadOnlySpan NullOrWhiteSpace(this IGuardClause guardClause, + public static ReadOnlySpan WhiteSpace(this IGuardClause guardClause, ReadOnlySpan input, string parameterName, string? message = null) diff --git a/test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs b/test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs index ba9df60f..88516ea0 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs @@ -12,7 +12,7 @@ public class GuardAgainstNullOrEmpty public void DoesNothingGivenNonEmptyStringValue() { Guard.Against.NullOrEmpty("a", "string"); - Guard.Against.NullOrEmpty("a".AsSpan(), "stringSpan"); + Guard.Against.Empty("a".AsSpan(), "stringSpan"); Guard.Against.NullOrEmpty("1", "aNumericString"); } @@ -45,7 +45,7 @@ public void ThrowsGivenEmptyString() [Fact] public void ThrowsGivenEmptyStringSpan() { - Assert.Throws(() => Guard.Against.NullOrEmpty("".AsSpan(), "emptyStringSpan")); + Assert.Throws(() => Guard.Against.Empty("".AsSpan(), "emptyStringSpan")); } [Fact] diff --git a/test/GuardClauses.UnitTests/GuardAgainstNullOrWhiteSpace.cs b/test/GuardClauses.UnitTests/GuardAgainstNullOrWhiteSpace.cs index 99bf4105..947fb069 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstNullOrWhiteSpace.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstNullOrWhiteSpace.cs @@ -15,7 +15,7 @@ public class GuardAgainstNullOrWhiteSpace public void DoesNothingGivenNonEmptyStringValue(string nonEmptyString) { Guard.Against.NullOrWhiteSpace(nonEmptyString, "string"); - Guard.Against.NullOrWhiteSpace(nonEmptyString.AsSpan(), "stringSpan"); + Guard.Against.WhiteSpace(nonEmptyString.AsSpan(), "stringSpan"); Guard.Against.NullOrWhiteSpace(nonEmptyString, "aNumericString"); } @@ -34,7 +34,7 @@ public void ThrowsGivenEmptyString() [Fact] public void ThrowsGivenEmptyStringSpan() { - Assert.Throws(() => Guard.Against.NullOrWhiteSpace("".AsSpan(), "emptyStringSpan")); + Assert.Throws(() => Guard.Against.WhiteSpace("".AsSpan(), "emptyStringSpan")); } [Theory] @@ -43,7 +43,7 @@ public void ThrowsGivenEmptyStringSpan() public void ThrowsGivenWhiteSpaceString(string whiteSpaceString) { Assert.Throws(() => Guard.Against.NullOrWhiteSpace(whiteSpaceString, "whitespacestring")); - Assert.Throws(() => Guard.Against.NullOrWhiteSpace(whiteSpaceString.AsSpan(), "whiteSpaceStringSpan")); + Assert.Throws(() => Guard.Against.WhiteSpace(whiteSpaceString.AsSpan(), "whiteSpaceStringSpan")); } [Theory] @@ -55,7 +55,7 @@ public void ThrowsGivenWhiteSpaceString(string whiteSpaceString) public void ReturnsExpectedValueGivenNonEmptyStringValue(string nonEmptyString, string expected) { Assert.Equal(expected, Guard.Against.NullOrWhiteSpace(nonEmptyString, "string")); - Assert.Equal(expected, Guard.Against.NullOrWhiteSpace(nonEmptyString.AsSpan(), "stringSpan").ToString()); + Assert.Equal(expected, Guard.Against.WhiteSpace(nonEmptyString.AsSpan(), "stringSpan").ToString()); Assert.Equal(expected, Guard.Against.NullOrWhiteSpace(nonEmptyString, "aNumericString")); } From ed3fcd90c5fd902a65a9f96c6e6b1d41ea297a93 Mon Sep 17 00:00:00 2001 From: KonH Date: Mon, 10 Oct 2022 20:53:38 +0200 Subject: [PATCH 4/6] Check span length before testing it agains string.Empty --- src/GuardClauses/GuardAgainstNullExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GuardClauses/GuardAgainstNullExtensions.cs b/src/GuardClauses/GuardAgainstNullExtensions.cs index b2843fde..9b6c473a 100644 --- a/src/GuardClauses/GuardAgainstNullExtensions.cs +++ b/src/GuardClauses/GuardAgainstNullExtensions.cs @@ -94,7 +94,7 @@ public static ReadOnlySpan Empty(this IGuardClause guardClause, string parameterName, string? message = null) { - if (input == string.Empty) + if (input.Length == 0 || input == string.Empty) { throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName); } From 3f666822c92a41f9624a07addb5a4783be0a13b3 Mon Sep 17 00:00:00 2001 From: KonH Date: Mon, 10 Oct 2022 21:07:17 +0200 Subject: [PATCH 5/6] Move new methods in separated file --- ...GuardAgainstEmptyOrWhiteSpaceExtensions.cs | 56 +++++++++++++++++++ .../GuardAgainstNullExtensions.cs | 47 ---------------- 2 files changed, 56 insertions(+), 47 deletions(-) create mode 100644 src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs diff --git a/src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs b/src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs new file mode 100644 index 00000000..fa1cfb97 --- /dev/null +++ b/src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace Ardalis.GuardClauses +{ + public static partial class GuardClauseExtensions + { +#if NET5_0_OR_GREATER + /// + /// Throws an if is an empty string. + /// + /// + /// + /// + /// Optional. Custom error message + /// if the value is not an empty string. + /// + public static ReadOnlySpan Empty(this IGuardClause guardClause, + ReadOnlySpan input, + string parameterName, + string? message = null) + { + if (input.Length == 0 || input == string.Empty) + { + throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName); + } + return input; + } + + /// + /// Throws an if is an empty or white space string. + /// + /// + /// + /// + /// Optional. Custom error message + /// if the value is not an empty or whitespace string. + /// + public static ReadOnlySpan WhiteSpace(this IGuardClause guardClause, + ReadOnlySpan input, + string parameterName, + string? message = null) + { + if (MemoryExtensions.IsWhiteSpace(input)) + { + throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName); + } + + return input; + } +#endif + } +} diff --git a/src/GuardClauses/GuardAgainstNullExtensions.cs b/src/GuardClauses/GuardAgainstNullExtensions.cs index 9b6c473a..b21617f1 100644 --- a/src/GuardClauses/GuardAgainstNullExtensions.cs +++ b/src/GuardClauses/GuardAgainstNullExtensions.cs @@ -79,29 +79,6 @@ public static string NullOrEmpty(this IGuardClause guardClause, return input; } -#if NET5_0_OR_GREATER - /// - /// Throws an if is an empty string. - /// - /// - /// - /// - /// Optional. Custom error message - /// if the value is not an empty string. - /// - public static ReadOnlySpan Empty(this IGuardClause guardClause, - ReadOnlySpan input, - string parameterName, - string? message = null) - { - if (input.Length == 0 || input == string.Empty) - { - throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName); - } - return input; - } -#endif - /// /// Throws an if is null. /// Throws an if is an empty guid. @@ -198,30 +175,6 @@ public static string NullOrWhiteSpace(this IGuardClause guardClause, return input; } -#if NET5_0_OR_GREATER - /// - /// Throws an if is an empty or white space string. - /// - /// - /// - /// - /// Optional. Custom error message - /// if the value is not an empty or whitespace string. - /// - public static ReadOnlySpan WhiteSpace(this IGuardClause guardClause, - ReadOnlySpan input, - string parameterName, - string? message = null) - { - if (MemoryExtensions.IsWhiteSpace(input)) - { - throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName); - } - - return input; - } -#endif - /// /// Throws an if is default for that type. /// From 52636fedd6b343bfe8063c2c24a3bf974cfc9683 Mon Sep 17 00:00:00 2001 From: KonH Date: Mon, 10 Oct 2022 21:13:27 +0200 Subject: [PATCH 6/6] Remove unused usings in new file --- src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs b/src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs index fa1cfb97..02a46f5e 100644 --- a/src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs +++ b/src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Runtime.CompilerServices; namespace Ardalis.GuardClauses {