diff --git a/src/projects/EnsureThat/Enforcers/StringArg.cs b/src/projects/EnsureThat/Enforcers/StringArg.cs index bab34ce..e507c6c 100644 --- a/src/projects/EnsureThat/Enforcers/StringArg.cs +++ b/src/projects/EnsureThat/Enforcers/StringArg.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Text.RegularExpressions; using EnsureThat.Annotations; using JetBrains.Annotations; @@ -270,6 +271,22 @@ public string IsInRange(string value, string min, string max, StringComparison c return value; } + [NotNull] + [ContractAnnotation("value:null => halt")] + public string IsAllLettersOrDigits([ValidatedNotNull] string value, [InvokerParameterName] string paramName = null, OptsFn optsFn = null) + { + Ensure.Any.IsNotNull(value, paramName, optsFn); + + for (var i = 0; i < value.Length; i++) + if (!char.IsLetterOrDigit(value[i])) + throw Ensure.ExceptionFactory.ArgumentException( + string.Format(ExceptionMessages.Strings_IsAllLettersOrDigits_Failed, value), + paramName, + optsFn); + + return value; + } + private static bool StringEquals(string x, string y) => string.Equals(x, y); diff --git a/src/projects/EnsureThat/EnsureArg.Strings.cs b/src/projects/EnsureThat/EnsureArg.Strings.cs index 2e7202e..9cfcc91 100644 --- a/src/projects/EnsureThat/EnsureArg.Strings.cs +++ b/src/projects/EnsureThat/EnsureArg.Strings.cs @@ -84,5 +84,10 @@ public static string StartsWith([ValidatedNotNull] string value, [NotNull] strin [ContractAnnotation("value:null => halt")] public static string StartsWith([ValidatedNotNull] string value, [NotNull] string expectedStartsWith, StringComparison comparisonType, [InvokerParameterName] string paramName = null, OptsFn optsFn = null) => Ensure.String.StartsWith(value, expectedStartsWith, comparisonType, paramName, optsFn); + + [NotNull] + [ContractAnnotation("value:null => halt")] + public static string IsAllLettersOrDigits([ValidatedNotNull] string value, [InvokerParameterName] string paramName = null, OptsFn optsFn = null) + => Ensure.String.IsAllLettersOrDigits(value, paramName, optsFn); } } \ No newline at end of file diff --git a/src/projects/EnsureThat/EnsureThatStringExtensions.cs b/src/projects/EnsureThat/EnsureThatStringExtensions.cs index 16491c8..2debfdd 100644 --- a/src/projects/EnsureThat/EnsureThatStringExtensions.cs +++ b/src/projects/EnsureThat/EnsureThatStringExtensions.cs @@ -80,5 +80,8 @@ public static void IsGte(this in StringParam param, string limit, StringComparis public static void IsInRange(this in StringParam param, string min, string max, StringComparison comparison) => Ensure.String.IsInRange(param.Value, min, max, comparison, param.Name, param.OptsFn); + + public static void IsAllLettersOrDigits(this in StringParam param) + => Ensure.String.IsAllLettersOrDigits(param.Value, param.Name, param.OptsFn); } } \ No newline at end of file diff --git a/src/projects/EnsureThat/ExceptionMessages.cs b/src/projects/EnsureThat/ExceptionMessages.cs index 254034b..7caf80c 100644 --- a/src/projects/EnsureThat/ExceptionMessages.cs +++ b/src/projects/EnsureThat/ExceptionMessages.cs @@ -37,7 +37,7 @@ public static class ExceptionMessages public static string Strings_IsNotEmpty_Failed { get; } = "Empty String is not allowed."; public static string Strings_IsGuid_Failed { get; } = "Value '{0}' is not a valid GUID."; public static string Strings_StartsWith_Failed { get; } = "Value '{0}' is expected to start with '{1}' but does not."; - + public static string Strings_IsAllLettersOrDigits_Failed { get; } = "Expected '{0} to contain only letters or digits but does not."; public static string Types_IsOfType_Failed { get; } = "The param is not of expected type. Expected: '{0}'. Got: '{1}'."; public static string Types_IsNotOfType_Failed { get; } = "The param was expected to not be of the type: '{0}'. But it was."; public static string Types_IsAssignableToType_Failed { get; } = "The param is not assignable to the expected type. Expected: '{0}'. Got: '{1}'."; diff --git a/src/tests/UnitTests/EnsureStringParamTests.cs b/src/tests/UnitTests/EnsureStringParamTests.cs index 0800f8b..ce0fa21 100644 --- a/src/tests/UnitTests/EnsureStringParamTests.cs +++ b/src/tests/UnitTests/EnsureStringParamTests.cs @@ -499,5 +499,50 @@ public void StartsWith_When_DoesNotStartWith_It_should_throw() () => EnsureArg.StartsWith(value, startPart, ParamName), () => Ensure.That(value, ParamName).StartsWith(startPart)); } + + [Fact] + public void IsAllLettersOrDigits_WhenStringIsAllLettersAndDigits_It_should_not_throw() + { + const string value = "aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789"; + + ShouldNotThrow( + () => Ensure.String.IsAllLettersOrDigits(value, ParamName), + () => EnsureArg.IsAllLettersOrDigits(value, ParamName), + () => Ensure.That(value, ParamName).IsAllLettersOrDigits()); + } + + [Fact] + public void IsAllLettersOrDigits_WhenStringIsAllDigits_It_should_not_throw() + { + const string value = "0123456789"; + + ShouldNotThrow( + () => Ensure.String.IsAllLettersOrDigits(value, ParamName), + () => EnsureArg.IsAllLettersOrDigits(value, ParamName), + () => Ensure.That(value, ParamName).IsAllLettersOrDigits()); + } + + [Fact] + public void IsAllLettersOrDigits_WhenStringIsAllLetters_It_should_not_throw() + { + const string value = "aBcDeFgHiJkLmNoPqRsTuVwXyZ"; + + ShouldNotThrow( + () => Ensure.String.IsAllLettersOrDigits(value, ParamName), + () => EnsureArg.IsAllLettersOrDigits(value, ParamName), + () => Ensure.That(value, ParamName).IsAllLettersOrDigits()); + } + + [Fact] + public void IsAllLettersOrDigits_WhenStringDoesNotHaveLettersOrDigits_It_should_throw() + { + const string value = "<:)-+-<"; + + ShouldThrow( + string.Format(ExceptionMessages.Strings_IsAllLettersOrDigits_Failed, value), + () => Ensure.String.IsAllLettersOrDigits(value, ParamName), + () => EnsureArg.IsAllLettersOrDigits(value, ParamName), + () => Ensure.That(value, ParamName).IsAllLettersOrDigits()); + } } } \ No newline at end of file