Skip to content

Commit 19e4674

Browse files
authored
Vectorized HttpCharacters (and used IndexOfAnyValues in other places found) (#45300)
1 parent dd50702 commit 19e4674

File tree

6 files changed

+51
-226
lines changed

6 files changed

+51
-226
lines changed

src/Components/Components/src/Routing/TemplateParser.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Buffers;
5+
46
namespace Microsoft.AspNetCore.Components.Routing;
57

68
// This implementation is temporary, in the future we'll want to have
@@ -18,8 +20,7 @@ namespace Microsoft.AspNetCore.Components.Routing;
1820
// * Catch-all parameters (Like /blog/{*slug})
1921
internal sealed class TemplateParser
2022
{
21-
public static readonly char[] InvalidParameterNameCharacters =
22-
new char[] { '{', '}', '=', '.' };
23+
private static readonly IndexOfAnyValues<char> _invalidParameterNameCharacters = IndexOfAnyValues.Create("{}=.");
2324

2425
internal static RouteTemplate ParseTemplate(string template)
2526
{
@@ -70,9 +71,10 @@ internal static RouteTemplate ParseTemplate(string template)
7071
$"Invalid template '{template}'. Empty parameter name in segment '{segment}' is not allowed.");
7172
}
7273

73-
var invalidCharacter = segment.IndexOfAny(InvalidParameterNameCharacters, 1, segment.Length - 2);
74-
if (invalidCharacter != -1)
74+
var invalidCharacter = segment.AsSpan(1, segment.Length - 2).IndexOfAny(_invalidParameterNameCharacters);
75+
if (invalidCharacter >= 0)
7576
{
77+
invalidCharacter++; // accommodate the slice above
7678
throw new InvalidOperationException(
7779
$"Invalid template '{template}'. The character '{segment[invalidCharacter]}' in parameter segment '{segment}' is not allowed.");
7880
}

src/Http/Routing/src/Patterns/RoutePatternFactory.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ public static RoutePatternParameterPart ParameterPart(string parameterName)
807807
throw new ArgumentException(Resources.Argument_NullOrEmpty, nameof(parameterName));
808808
}
809809

810-
if (parameterName.IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
810+
if (parameterName.AsSpan().IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
811811
{
812812
throw new ArgumentException(Resources.FormatTemplateRoute_InvalidParameterName(parameterName));
813813
}
@@ -833,7 +833,7 @@ public static RoutePatternParameterPart ParameterPart(string parameterName, obje
833833
throw new ArgumentException(Resources.Argument_NullOrEmpty, nameof(parameterName));
834834
}
835835

836-
if (parameterName.IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
836+
if (parameterName.AsSpan().IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
837837
{
838838
throw new ArgumentException(Resources.FormatTemplateRoute_InvalidParameterName(parameterName));
839839
}
@@ -863,7 +863,7 @@ public static RoutePatternParameterPart ParameterPart(
863863
throw new ArgumentException(Resources.Argument_NullOrEmpty, nameof(parameterName));
864864
}
865865

866-
if (parameterName.IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
866+
if (parameterName.AsSpan().IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
867867
{
868868
throw new ArgumentException(Resources.FormatTemplateRoute_InvalidParameterName(parameterName));
869869
}
@@ -900,7 +900,7 @@ public static RoutePatternParameterPart ParameterPart(
900900
throw new ArgumentException(Resources.Argument_NullOrEmpty, nameof(parameterName));
901901
}
902902

903-
if (parameterName.IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
903+
if (parameterName.AsSpan().IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
904904
{
905905
throw new ArgumentException(Resources.FormatTemplateRoute_InvalidParameterName(parameterName));
906906
}
@@ -942,7 +942,7 @@ public static RoutePatternParameterPart ParameterPart(
942942
throw new ArgumentException(Resources.Argument_NullOrEmpty, nameof(parameterName));
943943
}
944944

945-
if (parameterName.IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
945+
if (parameterName.AsSpan().IndexOfAny(RoutePatternParser.InvalidParameterNameChars) >= 0)
946946
{
947947
throw new ArgumentException(Resources.FormatTemplateRoute_InvalidParameterName(parameterName));
948948
}

src/Http/Routing/src/Patterns/RoutePatternParser.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#nullable disable
55

6+
using System.Buffers;
67
using System.Diagnostics;
78

89
namespace Microsoft.AspNetCore.Routing.Patterns;
@@ -13,17 +14,9 @@ internal static class RoutePatternParser
1314
private const char OpenBrace = '{';
1415
private const char CloseBrace = '}';
1516
private const char QuestionMark = '?';
16-
private const char Asterisk = '*';
1717
private const string PeriodString = ".";
1818

19-
internal static readonly char[] InvalidParameterNameChars = new char[]
20-
{
21-
Separator,
22-
OpenBrace,
23-
CloseBrace,
24-
QuestionMark,
25-
Asterisk
26-
};
19+
internal static readonly IndexOfAnyValues<char> InvalidParameterNameChars = IndexOfAnyValues.Create("/{}?*");
2720

2821
public static RoutePattern Parse(string pattern)
2922
{
@@ -431,7 +424,7 @@ private static bool IsSegmentValid(Context context, List<RoutePatternPart> parts
431424

432425
private static bool IsValidParameterName(Context context, string parameterName)
433426
{
434-
if (parameterName.Length == 0 || parameterName.IndexOfAny(InvalidParameterNameChars) >= 0)
427+
if (parameterName.Length == 0 || parameterName.AsSpan().IndexOfAny(InvalidParameterNameChars) >= 0)
435428
{
436429
context.Error = Resources.FormatTemplateRoute_InvalidParameterName(parameterName);
437430
return false;

src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using Microsoft.AspNetCore.Connections;
88
using Microsoft.AspNetCore.Hosting.Server;
99
using Microsoft.AspNetCore.Hosting.Server.Features;
10-
using Microsoft.AspNetCore.Http;
1110
using Microsoft.AspNetCore.Http.Features;
1211
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
1312
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
@@ -89,8 +88,6 @@ internal KestrelServerImpl(
8988
Features.Set<IServerAddressesFeature>(_serverAddresses);
9089

9190
_transportManager = new TransportManager(_transportFactories, _multiplexedTransportFactories, ServiceContext);
92-
93-
HttpCharacters.Initialize();
9491
}
9592

9693
private static ServiceContext CreateServiceContext(IOptions<KestrelServerOptions> options, ILoggerFactory loggerFactory, DiagnosticSource? diagnosticSource)

src/Shared/HttpSys/RequestProcessing/HeaderCollection.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,12 @@ public static void ValidateHeaderCharacters(string headerCharacters)
272272
{
273273
if (headerCharacters != null)
274274
{
275-
var invalid = HttpCharacters.IndexOfInvalidFieldValueCharExtended(headerCharacters);
276-
if (invalid >= 0)
275+
var invalidIndex = HttpCharacters.IndexOfInvalidFieldValueCharExtended(headerCharacters);
276+
if (invalidIndex >= 0)
277277
{
278-
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Invalid control character in header: 0x{0:X2}", headerCharacters[invalid]));
278+
Throw(headerCharacters, invalidIndex);
279+
static void Throw(string headerCharacters, int invalidIndex)
280+
=> throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Invalid control character in header: 0x{0:X2}", headerCharacters[invalidIndex]));
279281
}
280282
}
281283
}

0 commit comments

Comments
 (0)