Use spans for complex segments (#9817)
This commit is contained in:
parent
f08da14f1b
commit
8af14399b6
|
|
@ -228,13 +228,14 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
{
|
{
|
||||||
for (var i = 0; i < captures.Length; i++)
|
for (var i = 0; i < captures.Length; i++)
|
||||||
{
|
{
|
||||||
var parameterName = captures[i].parameterName;
|
(var parameterName, var segmentIndex, var slotIndex) = captures[i];
|
||||||
if (segments.Length > captures[i].segmentIndex)
|
|
||||||
|
if ((uint)segmentIndex < (uint)segments.Length)
|
||||||
{
|
{
|
||||||
var segment = segments[captures[i].segmentIndex];
|
var segment = segments[segmentIndex];
|
||||||
if (parameterName != null && segment.Length > 0)
|
if (parameterName != null && segment.Length > 0)
|
||||||
{
|
{
|
||||||
slots[captures[i].slotIndex] = new KeyValuePair<string, object>(
|
slots[slotIndex] = new KeyValuePair<string, object>(
|
||||||
parameterName,
|
parameterName,
|
||||||
path.Substring(segment.Start, segment.Length));
|
path.Substring(segment.Start, segment.Length));
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +250,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
ReadOnlySpan<PathSegment> segments)
|
ReadOnlySpan<PathSegment> segments)
|
||||||
{
|
{
|
||||||
// Read segmentIndex to local both to skip double read from stack value
|
// 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;
|
var segmentIndex = catchAll.segmentIndex;
|
||||||
if ((uint)segmentIndex < (uint)segments.Length)
|
if ((uint)segmentIndex < (uint)segments.Length)
|
||||||
{
|
{
|
||||||
|
|
@ -271,7 +272,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
||||||
{
|
{
|
||||||
(var complexSegment, var segmentIndex) = complexSegments[i];
|
(var complexSegment, var segmentIndex) = complexSegments[i];
|
||||||
var segment = segments[segmentIndex];
|
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))
|
if (!RoutePatternMatcher.MatchComplexSegment(complexSegment, text, values))
|
||||||
{
|
{
|
||||||
Logger.CandidateRejectedByComplexSegment(_logger, path, endpoint, complexSegment);
|
Logger.CandidateRejectedByComplexSegment(_logger, path, endpoint, complexSegment);
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
if (!pathSegment.IsSimple)
|
if (!pathSegment.IsSimple)
|
||||||
{
|
{
|
||||||
if (!MatchComplexSegment(pathSegment, requestSegment.ToString(), values))
|
if (!MatchComplexSegment(pathSegment, requestSegment.AsSpan(), values))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -292,7 +292,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
internal static bool MatchComplexSegment(
|
internal static bool MatchComplexSegment(
|
||||||
RoutePatternPathSegment routeSegment,
|
RoutePatternPathSegment routeSegment,
|
||||||
string requestSegment,
|
ReadOnlySpan<char> requestSegment,
|
||||||
RouteValueDictionary values)
|
RouteValueDictionary values)
|
||||||
{
|
{
|
||||||
var indexOfLastSegment = routeSegment.Parts.Count - 1;
|
var indexOfLastSegment = routeSegment.Parts.Count - 1;
|
||||||
|
|
@ -336,7 +336,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
private static bool MatchComplexSegmentCore(
|
private static bool MatchComplexSegmentCore(
|
||||||
RoutePatternPathSegment routeSegment,
|
RoutePatternPathSegment routeSegment,
|
||||||
string requestSegment,
|
ReadOnlySpan<char> requestSegment,
|
||||||
RouteValueDictionary values,
|
RouteValueDictionary values,
|
||||||
int indexOfLastSegmentUsed)
|
int indexOfLastSegmentUsed)
|
||||||
{
|
{
|
||||||
|
|
@ -366,14 +366,14 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
Debug.Assert(part.IsLiteral || part.IsSeparator);
|
Debug.Assert(part.IsLiteral || part.IsSeparator);
|
||||||
lastLiteral = part;
|
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 we have a pending parameter subsegment, we must leave at least one character for that
|
||||||
if (parameterNeedsValue != null)
|
if (parameterNeedsValue != null)
|
||||||
{
|
{
|
||||||
startIndex--;
|
startIndex--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startIndex < 0)
|
if (startIndex == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -382,17 +382,15 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
if (part.IsLiteral)
|
if (part.IsLiteral)
|
||||||
{
|
{
|
||||||
var literal = (RoutePatternLiteralPart)part;
|
var literal = (RoutePatternLiteralPart)part;
|
||||||
indexOfLiteral = requestSegment.LastIndexOf(
|
indexOfLiteral = requestSegment.Slice(0, startIndex).LastIndexOf(
|
||||||
literal.Content,
|
literal.Content,
|
||||||
startIndex,
|
|
||||||
StringComparison.OrdinalIgnoreCase);
|
StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var literal = (RoutePatternSeparatorPart)part;
|
var literal = (RoutePatternSeparatorPart)part;
|
||||||
indexOfLiteral = requestSegment.LastIndexOf(
|
indexOfLiteral = requestSegment.Slice(0, startIndex).LastIndexOf(
|
||||||
literal.Content,
|
literal.Content,
|
||||||
startIndex,
|
|
||||||
StringComparison.OrdinalIgnoreCase);
|
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.
|
// 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
|
// For these segments all parameters must have non-empty values. If the parameter
|
||||||
|
|
@ -478,7 +476,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If there's a value in the segment for this parameter, use the subsegment value
|
// 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;
|
parameterNeedsValue = null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue