Use spans for complex segments (#9817)

This commit is contained in:
David Fowler 2019-04-30 22:56:53 -07:00 committed by GitHub
parent f08da14f1b
commit 8af14399b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 18 deletions

View File

@ -228,13 +228,14 @@ namespace Microsoft.AspNetCore.Routing.Matching
{
for (var i = 0; i < captures.Length; i++)
{
var parameterName = captures[i].parameterName;
if (segments.Length > captures[i].segmentIndex)
(var parameterName, var segmentIndex, var slotIndex) = captures[i];
if ((uint)segmentIndex < (uint)segments.Length)
{
var segment = segments[captures[i].segmentIndex];
var segment = segments[segmentIndex];
if (parameterName != null && segment.Length > 0)
{
slots[captures[i].slotIndex] = new KeyValuePair<string, object>(
slots[slotIndex] = new KeyValuePair<string, object>(
parameterName,
path.Substring(segment.Start, segment.Length));
}
@ -249,7 +250,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
ReadOnlySpan<PathSegment> segments)
{
// Read segmentIndex to local both to skip double read from stack value
// and to use the same in-bounds validated varaible to access the array.
// and to use the same in-bounds validated variable to access the array.
var segmentIndex = catchAll.segmentIndex;
if ((uint)segmentIndex < (uint)segments.Length)
{
@ -271,7 +272,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
{
(var complexSegment, var segmentIndex) = complexSegments[i];
var segment = segments[segmentIndex];
var text = path.Substring(segment.Start, segment.Length);
var text = path.AsSpan(segment.Start, segment.Length);
if (!RoutePatternMatcher.MatchComplexSegment(complexSegment, text, values))
{
Logger.CandidateRejectedByComplexSegment(_logger, path, endpoint, complexSegment);

View File

@ -160,7 +160,7 @@ namespace Microsoft.AspNetCore.Routing
}
if (!pathSegment.IsSimple)
{
if (!MatchComplexSegment(pathSegment, requestSegment.ToString(), values))
if (!MatchComplexSegment(pathSegment, requestSegment.AsSpan(), values))
{
return false;
}
@ -292,7 +292,7 @@ namespace Microsoft.AspNetCore.Routing
internal static bool MatchComplexSegment(
RoutePatternPathSegment routeSegment,
string requestSegment,
ReadOnlySpan<char> requestSegment,
RouteValueDictionary values)
{
var indexOfLastSegment = routeSegment.Parts.Count - 1;
@ -336,7 +336,7 @@ namespace Microsoft.AspNetCore.Routing
private static bool MatchComplexSegmentCore(
RoutePatternPathSegment routeSegment,
string requestSegment,
ReadOnlySpan<char> requestSegment,
RouteValueDictionary values,
int indexOfLastSegmentUsed)
{
@ -366,14 +366,14 @@ namespace Microsoft.AspNetCore.Routing
Debug.Assert(part.IsLiteral || part.IsSeparator);
lastLiteral = part;
var startIndex = lastIndex - 1;
var startIndex = lastIndex;
// If we have a pending parameter subsegment, we must leave at least one character for that
if (parameterNeedsValue != null)
{
startIndex--;
}
if (startIndex < 0)
if (startIndex == 0)
{
return false;
}
@ -382,17 +382,15 @@ namespace Microsoft.AspNetCore.Routing
if (part.IsLiteral)
{
var literal = (RoutePatternLiteralPart)part;
indexOfLiteral = requestSegment.LastIndexOf(
indexOfLiteral = requestSegment.Slice(0, startIndex).LastIndexOf(
literal.Content,
startIndex,
StringComparison.OrdinalIgnoreCase);
}
else
{
var literal = (RoutePatternSeparatorPart)part;
indexOfLiteral = requestSegment.LastIndexOf(
indexOfLiteral = requestSegment.Slice(0, startIndex).LastIndexOf(
literal.Content,
startIndex,
StringComparison.OrdinalIgnoreCase);
}
@ -465,9 +463,9 @@ namespace Microsoft.AspNetCore.Routing
}
}
var parameterValueString = requestSegment.Substring(parameterStartIndex, parameterTextLength);
var parameterValueSpan = requestSegment.Slice(parameterStartIndex, parameterTextLength);
if (string.IsNullOrEmpty(parameterValueString))
if (parameterValueSpan.Length == 0)
{
// If we're here that means we have a segment that contains multiple sub-segments.
// For these segments all parameters must have non-empty values. If the parameter
@ -478,7 +476,7 @@ namespace Microsoft.AspNetCore.Routing
else
{
// If there's a value in the segment for this parameter, use the subsegment value
outValues.Add(parameterNeedsValue.Name, parameterValueString);
outValues.Add(parameterNeedsValue.Name, new string(parameterValueSpan));
}
parameterNeedsValue = null;