diff --git a/src/IbanNet/IIbanSpanParser.cs b/src/IbanNet/IIbanSpanParser.cs new file mode 100644 index 00000000..f3cffb57 --- /dev/null +++ b/src/IbanNet/IIbanSpanParser.cs @@ -0,0 +1,27 @@ +#if USE_SPANS +using System.Diagnostics.CodeAnalysis; + +namespace IbanNet; + +/// +/// Provides parsing of international bank account numbers into an . +/// +internal interface IIbanSpanParser +{ + /// + /// Parses the specified into an . + /// + /// The IBAN value to parse. + /// an if the is parsed successfully + /// Thrown when the specified is not a valid IBAN. + Iban Parse(ReadOnlySpan value); + + /// + /// Attempts to parse the specified into an . + /// + /// The IBAN value to parse. + /// The if the is parsed successfully. + /// if the is parsed successfully, or otherwise + bool TryParse(ReadOnlySpan value, [NotNullWhen(true)] out Iban? iban); +} +#endif diff --git a/src/IbanNet/Iban.cs b/src/IbanNet/Iban.cs index 05ba544b..7eee6d81 100644 --- a/src/IbanNet/Iban.cs +++ b/src/IbanNet/Iban.cs @@ -19,7 +19,7 @@ namespace IbanNet; public sealed class Iban : IEquatable, #if NET8_0_OR_GREATER - IParsable, + ISpanParsable, #endif IFormattable { @@ -295,6 +295,20 @@ internal static Iban Parse(string s) return parser.Parse(s); } +#if USE_SPANS + /// + /// Converts the specified into an . + /// + /// The IBAN value to parse. + /// An if the is converted successfully. + /// Thrown when the specified is not a valid IBAN. + internal static Iban Parse(ReadOnlySpan s) + { + IIbanSpanParser parser = new IbanParser(IbanRegistry.Default); + return parser.Parse(s); + } +#endif + #if NET8_0_OR_GREATER /// /// Converts the specified into an . @@ -306,6 +320,9 @@ internal static Iban Parse(string s) /// Thrown when the specified is not a valid IBAN. static Iban IParsable.Parse(string s, IFormatProvider? provider) => Parse(s); + + static Iban ISpanParsable.Parse(ReadOnlySpan s, IFormatProvider? provider) + => Parse(s); #endif /// @@ -320,6 +337,20 @@ internal static bool TryParse(string? s, [NotNullWhen(true)] out Iban? result) return parser.TryParse(s, out result); } +#if USE_SPANS + /// + /// Tries to convert the specified into an . + /// + /// The IBAN value to parse. + /// The if the is converted successfully. + /// if the is converted successfully, or otherwise + internal static bool TryParse(ReadOnlySpan s, [NotNullWhen(true)] out Iban? result) + { + IIbanSpanParser parser = new IbanParser(IbanRegistry.Default); + return parser.TryParse(s, out result); + } +#endif + #if NET8_0_OR_GREATER /// /// Tries to convert the specified into an . @@ -330,5 +361,8 @@ internal static bool TryParse(string? s, [NotNullWhen(true)] out Iban? result) /// if the is converted successfully, or otherwise static bool IParsable.TryParse(string? s, IFormatProvider? provider, [NotNullWhen(true)] out Iban? result) => TryParse(s, out result); + + static bool ISpanParsable.TryParse(ReadOnlySpan s, IFormatProvider? provider, [NotNullWhen(true)] out Iban? result) + => TryParse(s, out result); #endif } diff --git a/src/IbanNet/IbanParser.cs b/src/IbanNet/IbanParser.cs index 6cdcdd1a..d053833f 100644 --- a/src/IbanNet/IbanParser.cs +++ b/src/IbanNet/IbanParser.cs @@ -1,5 +1,4 @@ using System.Diagnostics.CodeAnalysis; -using System.Globalization; using IbanNet.Internal; using IbanNet.Registry; @@ -8,7 +7,11 @@ namespace IbanNet; /// /// Provides parsing of international bank account numbers into an . /// -public sealed class IbanParser : IIbanParser +public sealed class IbanParser + : IIbanParser +#if USE_SPANS + , IIbanSpanParser +#endif { private readonly IIbanValidator _ibanValidator; @@ -23,10 +26,7 @@ public IbanParser(IIbanRegistry registry) throw new ArgumentNullException(nameof(registry)); } - _ibanValidator = new IbanValidator(new IbanValidatorOptions - { - Registry = registry - }); + _ibanValidator = new IbanValidator(new IbanValidatorOptions { Registry = registry }); } /// @@ -39,12 +39,24 @@ public IbanParser(IIbanValidator ibanValidator) } /// +#if USE_SPANS + public Iban Parse(string value) + { + return value is null + ? throw new ArgumentNullException(nameof(value)) + : ((IIbanSpanParser)this).Parse(value); + } + + Iban IIbanSpanParser.Parse(ReadOnlySpan value) + { +#else public Iban Parse(string value) { if (value is null) { throw new ArgumentNullException(nameof(value)); } +#endif if (TryParse(value, out Iban? iban, out ValidationResult validationResult, out Exception? exceptionThrown)) { @@ -52,7 +64,7 @@ public Iban Parse(string value) } string errorMessage = validationResult.Error is null || string.IsNullOrEmpty(validationResult.Error.ErrorMessage) - ? string.Format(CultureInfo.CurrentCulture, Resources.IbanFormatException_The_value_0_is_not_a_valid_IBAN, value) + ? Resources.IbanFormatException_The_value_is_not_a_valid_IBAN : validationResult.Error.ErrorMessage; if (exceptionThrown is not null) @@ -69,7 +81,16 @@ public bool TryParse(string? value, [NotNullWhen(true)] out Iban? iban) return TryParse(value, out iban, out _, out _); } - private bool TryParse( + +#if USE_SPANS + bool IIbanSpanParser.TryParse(ReadOnlySpan value, [NotNullWhen(true)] out Iban? iban) + { + return TryParse(value, out iban, out _, out _); + } +#endif + + private bool TryParse + ( #if USE_SPANS ReadOnlySpan value, #else @@ -77,6 +98,7 @@ private bool TryParse( #endif [NotNullWhen(true)] out Iban? iban, out ValidationResult validationResult, + // ReSharper disable once RedundantNullableFlowAttribute [MaybeNullWhen(false)] out Exception? exceptionThrown) { iban = null; diff --git a/src/IbanNet/Resources.Designer.cs b/src/IbanNet/Resources.Designer.cs index f94e78ea..bbf3b37f 100644 --- a/src/IbanNet/Resources.Designer.cs +++ b/src/IbanNet/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace IbanNet { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -178,11 +178,11 @@ internal static string Exception_The_country_0_does_not_define_a_IBAN_pattern { } /// - /// Looks up a localized string similar to The value '{0}' is not a valid IBAN.. + /// Looks up a localized string similar to The value is not a valid IBAN.. /// - internal static string IbanFormatException_The_value_0_is_not_a_valid_IBAN { + internal static string IbanFormatException_The_value_is_not_a_valid_IBAN { get { - return ResourceManager.GetString("IbanFormatException_The_value_0_is_not_a_valid_IBAN", resourceCulture); + return ResourceManager.GetString("IbanFormatException_The_value_is_not_a_valid_IBAN", resourceCulture); } } diff --git a/src/IbanNet/Resources.ca.resx b/src/IbanNet/Resources.ca.resx index 79cddcfa..eedaee0b 100644 --- a/src/IbanNet/Resources.ca.resx +++ b/src/IbanNet/Resources.ca.resx @@ -98,8 +98,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - El valor '{0}' no és un IBAN vàlid. + + El valor no és un IBAN vàlid. El format '{0}' no és vàlid. diff --git a/src/IbanNet/Resources.de.resx b/src/IbanNet/Resources.de.resx index 4858c4b6..eb291613 100644 --- a/src/IbanNet/Resources.de.resx +++ b/src/IbanNet/Resources.de.resx @@ -98,8 +98,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Der Wert '{0}' ist keine gültige IBAN. + + Der Wert ist keine gültige IBAN. Das Format '{0}' ist ungültig. diff --git a/src/IbanNet/Resources.nl.resx b/src/IbanNet/Resources.nl.resx index 59ac98ae..6e66a80c 100644 --- a/src/IbanNet/Resources.nl.resx +++ b/src/IbanNet/Resources.nl.resx @@ -117,8 +117,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - De waarde '{0}' is geen geldige IBAN. + + De waarde bevat geen geldige IBAN. Het formaat '{0}' is niet valide. diff --git a/src/IbanNet/Resources.resx b/src/IbanNet/Resources.resx index d36de621..2bd0568c 100644 --- a/src/IbanNet/Resources.resx +++ b/src/IbanNet/Resources.resx @@ -98,8 +98,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - The value '{0}' is not a valid IBAN. + + The value is not a valid IBAN. The format '{0}' is invalid. diff --git a/test/IbanNet.Tests/PublicApi/.NET_10.0.verified.txt b/test/IbanNet.Tests/PublicApi/.NET_10.0.verified.txt index 75cc6c9e..848bf382 100644 --- a/test/IbanNet.Tests/PublicApi/.NET_10.0.verified.txt +++ b/test/IbanNet.Tests/PublicApi/.NET_10.0.verified.txt @@ -101,7 +101,7 @@ namespace IbanNet } [System.ComponentModel.TypeConverter(typeof(IbanNet.TypeConverters.IbanTypeConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(IbanNet.Json.IbanJsonConverter))] - public sealed class Iban : System.IEquatable, System.IFormattable, System.IParsable + public sealed class Iban : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanParsable { [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] public const int MaxLength = 34; diff --git a/test/IbanNet.Tests/PublicApi/.NET_8.0.verified.txt b/test/IbanNet.Tests/PublicApi/.NET_8.0.verified.txt index 0b2a6b69..46b24f96 100644 --- a/test/IbanNet.Tests/PublicApi/.NET_8.0.verified.txt +++ b/test/IbanNet.Tests/PublicApi/.NET_8.0.verified.txt @@ -101,7 +101,7 @@ namespace IbanNet } [System.ComponentModel.TypeConverter(typeof(IbanNet.TypeConverters.IbanTypeConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(IbanNet.Json.IbanJsonConverter))] - public sealed class Iban : System.IEquatable, System.IFormattable, System.IParsable + public sealed class Iban : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanParsable { [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] public const int MaxLength = 34;