Incorporate StringSegment from primitives
This commit is contained in:
parent
e5f4aa03d2
commit
a5727dc932
|
|
@ -1,136 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Routing.Internal
|
|
||||||
{
|
|
||||||
public struct PathSegment : IEquatable<PathSegment>, IEquatable<string>
|
|
||||||
{
|
|
||||||
private readonly string _path;
|
|
||||||
private readonly int _start;
|
|
||||||
private readonly int _length;
|
|
||||||
|
|
||||||
private string _segment;
|
|
||||||
|
|
||||||
public PathSegment(string path, int start, int length)
|
|
||||||
{
|
|
||||||
if (path == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start < 1 || start >= path.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(start));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length < 0 || start + length > path.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(length));
|
|
||||||
}
|
|
||||||
|
|
||||||
_path = path;
|
|
||||||
_start = start;
|
|
||||||
_length = length;
|
|
||||||
|
|
||||||
_segment = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Length => _length;
|
|
||||||
|
|
||||||
public string GetRemainingPath()
|
|
||||||
{
|
|
||||||
if (_path == null)
|
|
||||||
{
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _path.Substring(_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
var other = obj as PathSegment?;
|
|
||||||
if (other == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Equals(other.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
if (_path == null)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return StringComparer.OrdinalIgnoreCase.GetHashCode(ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (_path == null)
|
|
||||||
{
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_segment == null)
|
|
||||||
{
|
|
||||||
_segment = _path.Substring(_start, _length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _segment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(PathSegment other)
|
|
||||||
{
|
|
||||||
if (_path == null)
|
|
||||||
{
|
|
||||||
return other._path == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (other._length != _length)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Compare(
|
|
||||||
_path,
|
|
||||||
_start,
|
|
||||||
other._path,
|
|
||||||
other._start,
|
|
||||||
_length,
|
|
||||||
StringComparison.OrdinalIgnoreCase) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(string other)
|
|
||||||
{
|
|
||||||
if (_path == null)
|
|
||||||
{
|
|
||||||
return other == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (other.Length != _length)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Compare(_path, _start, other, 0, _length, StringComparison.OrdinalIgnoreCase) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(PathSegment x, PathSegment y)
|
|
||||||
{
|
|
||||||
return x.Equals(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(PathSegment x, PathSegment y)
|
|
||||||
{
|
|
||||||
return !x.Equals(y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,10 +6,11 @@ using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Routing.Internal
|
namespace Microsoft.AspNet.Routing.Internal
|
||||||
{
|
{
|
||||||
public struct PathTokenizer : IReadOnlyList<PathSegment>
|
public struct PathTokenizer : IReadOnlyList<StringSegment>
|
||||||
{
|
{
|
||||||
private readonly string _path;
|
private readonly string _path;
|
||||||
private int _count;
|
private int _count;
|
||||||
|
|
@ -63,7 +64,7 @@ namespace Microsoft.AspNet.Routing.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathSegment this[int index]
|
public StringSegment this[int index]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -82,7 +83,7 @@ namespace Microsoft.AspNet.Routing.Internal
|
||||||
{
|
{
|
||||||
if (currentSegmentIndex++ == index)
|
if (currentSegmentIndex++ == index)
|
||||||
{
|
{
|
||||||
return new PathSegment(_path, currentSegmentStart, delimiterIndex - currentSegmentStart);
|
return new StringSegment(_path, currentSegmentStart, delimiterIndex - currentSegmentStart);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -96,7 +97,7 @@ namespace Microsoft.AspNet.Routing.Internal
|
||||||
Debug.Assert(_path[_path.Length - 1] != '/');
|
Debug.Assert(_path[_path.Length - 1] != '/');
|
||||||
Debug.Assert(currentSegmentIndex == index);
|
Debug.Assert(currentSegmentIndex == index);
|
||||||
|
|
||||||
return new PathSegment(_path, currentSegmentStart, _path.Length - currentSegmentStart);
|
return new StringSegment(_path, currentSegmentStart, _path.Length - currentSegmentStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +106,7 @@ namespace Microsoft.AspNet.Routing.Internal
|
||||||
return new Enumerator(this);
|
return new Enumerator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator<PathSegment> IEnumerable<PathSegment>.GetEnumerator()
|
IEnumerator<StringSegment> IEnumerable<StringSegment>.GetEnumerator()
|
||||||
{
|
{
|
||||||
return GetEnumerator();
|
return GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +116,7 @@ namespace Microsoft.AspNet.Routing.Internal
|
||||||
return GetEnumerator();
|
return GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Enumerator : IEnumerator<PathSegment>
|
public struct Enumerator : IEnumerator<StringSegment>
|
||||||
{
|
{
|
||||||
private readonly string _path;
|
private readonly string _path;
|
||||||
|
|
||||||
|
|
@ -130,11 +131,11 @@ namespace Microsoft.AspNet.Routing.Internal
|
||||||
_length = -1;
|
_length = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathSegment Current
|
public StringSegment Current
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return new PathSegment(_path, _index, _length);
|
return new StringSegment(_path, _index, _length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
{
|
{
|
||||||
// This is a literal segment, so we need to match the text, or the route isn't a match.
|
// This is a literal segment, so we need to match the text, or the route isn't a match.
|
||||||
var part = routeSegment.Parts[0];
|
var part = routeSegment.Parts[0];
|
||||||
if (!requestSegment.Equals(part.Text))
|
if (!requestSegment.Equals(part.Text, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +149,7 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
{
|
{
|
||||||
// A catch-all captures til the end of the string.
|
// A catch-all captures til the end of the string.
|
||||||
var part = routeSegment.Parts[0];
|
var part = routeSegment.Parts[0];
|
||||||
var captured = requestSegment.GetRemainingPath();
|
var captured = requestSegment.Buffer.Substring(requestSegment.Offset);
|
||||||
if (captured.Length > 0)
|
if (captured.Length > 0)
|
||||||
{
|
{
|
||||||
values.Add(part.Name, captured);
|
values.Add(part.Name, captured);
|
||||||
|
|
|
||||||
|
|
@ -2,72 +2,73 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Routing.Internal
|
namespace Microsoft.AspNet.Routing.Internal
|
||||||
{
|
{
|
||||||
public class PathTokenizerTest
|
public class PathTokenizerTest
|
||||||
{
|
{
|
||||||
public static TheoryData<string, PathSegment[]> TokenizationData
|
public static TheoryData<string, StringSegment[]> TokenizationData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return new TheoryData<string, PathSegment[]>
|
return new TheoryData<string, StringSegment[]>
|
||||||
{
|
{
|
||||||
{ string.Empty, new PathSegment[] { } },
|
{ string.Empty, new StringSegment[] { } },
|
||||||
{ "/", new PathSegment[] { } },
|
{ "/", new StringSegment[] { } },
|
||||||
{ "//", new PathSegment[] { new PathSegment("//", 1, 0) } },
|
{ "//", new StringSegment[] { new StringSegment("//", 1, 0) } },
|
||||||
{
|
{
|
||||||
"///",
|
"///",
|
||||||
new PathSegment[]
|
new StringSegment[]
|
||||||
{
|
{
|
||||||
new PathSegment("///", 1, 0),
|
new StringSegment("///", 1, 0),
|
||||||
new PathSegment("///", 2, 0),
|
new StringSegment("///", 2, 0),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"////",
|
"////",
|
||||||
new PathSegment[]
|
new StringSegment[]
|
||||||
{
|
{
|
||||||
new PathSegment("////", 1, 0),
|
new StringSegment("////", 1, 0),
|
||||||
new PathSegment("////", 2, 0),
|
new StringSegment("////", 2, 0),
|
||||||
new PathSegment("////", 3, 0),
|
new StringSegment("////", 3, 0),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ "/zero", new PathSegment[] { new PathSegment("/zero", 1, 4) } },
|
{ "/zero", new StringSegment[] { new StringSegment("/zero", 1, 4) } },
|
||||||
{ "/zero/", new PathSegment[] { new PathSegment("/zero/", 1, 4) } },
|
{ "/zero/", new StringSegment[] { new StringSegment("/zero/", 1, 4) } },
|
||||||
{
|
{
|
||||||
"/zero/one",
|
"/zero/one",
|
||||||
new PathSegment[]
|
new StringSegment[]
|
||||||
{
|
{
|
||||||
new PathSegment("/zero/one", 1, 4),
|
new StringSegment("/zero/one", 1, 4),
|
||||||
new PathSegment("/zero/one", 6, 3),
|
new StringSegment("/zero/one", 6, 3),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/zero/one/",
|
"/zero/one/",
|
||||||
new PathSegment[]
|
new StringSegment[]
|
||||||
{
|
{
|
||||||
new PathSegment("/zero/one/", 1, 4),
|
new StringSegment("/zero/one/", 1, 4),
|
||||||
new PathSegment("/zero/one/", 6, 3),
|
new StringSegment("/zero/one/", 6, 3),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/zero/one/two",
|
"/zero/one/two",
|
||||||
new PathSegment[]
|
new StringSegment[]
|
||||||
{
|
{
|
||||||
new PathSegment("/zero/one/two", 1, 4),
|
new StringSegment("/zero/one/two", 1, 4),
|
||||||
new PathSegment("/zero/one/two", 6, 3),
|
new StringSegment("/zero/one/two", 6, 3),
|
||||||
new PathSegment("/zero/one/two", 10, 3),
|
new StringSegment("/zero/one/two", 10, 3),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"/zero/one/two/",
|
"/zero/one/two/",
|
||||||
new PathSegment[]
|
new StringSegment[]
|
||||||
{
|
{
|
||||||
new PathSegment("/zero/one/two/", 1, 4),
|
new StringSegment("/zero/one/two/", 1, 4),
|
||||||
new PathSegment("/zero/one/two/", 6, 3),
|
new StringSegment("/zero/one/two/", 6, 3),
|
||||||
new PathSegment("/zero/one/two/", 10, 3),
|
new StringSegment("/zero/one/two/", 10, 3),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -76,7 +77,7 @@ namespace Microsoft.AspNet.Routing.Internal
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(TokenizationData))]
|
[MemberData(nameof(TokenizationData))]
|
||||||
public void PathTokenizer_Count(string path, PathSegment[] expectedSegments)
|
public void PathTokenizer_Count(string path, StringSegment[] expectedSegments)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var tokenizer = new PathTokenizer(new PathString(path));
|
var tokenizer = new PathTokenizer(new PathString(path));
|
||||||
|
|
@ -90,7 +91,7 @@ namespace Microsoft.AspNet.Routing.Internal
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(TokenizationData))]
|
[MemberData(nameof(TokenizationData))]
|
||||||
public void PathTokenizer_Indexer(string path, PathSegment[] expectedSegments)
|
public void PathTokenizer_Indexer(string path, StringSegment[] expectedSegments)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var tokenizer = new PathTokenizer(new PathString(path));
|
var tokenizer = new PathTokenizer(new PathString(path));
|
||||||
|
|
@ -104,13 +105,13 @@ namespace Microsoft.AspNet.Routing.Internal
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(TokenizationData))]
|
[MemberData(nameof(TokenizationData))]
|
||||||
public void PathTokenizer_Enumerator(string path, PathSegment[] expectedSegments)
|
public void PathTokenizer_Enumerator(string path, StringSegment[] expectedSegments)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var tokenizer = new PathTokenizer(new PathString(path));
|
var tokenizer = new PathTokenizer(new PathString(path));
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
Assert.Equal<PathSegment>(expectedSegments, tokenizer);
|
Assert.Equal<StringSegment>(expectedSegments, tokenizer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue