@@ -22,15 +22,24 @@ namespace Microsoft.AspNetCore.Internal
22
22
#else
23
23
internal
24
24
#endif
25
- readonly ref struct QueryStringEnumerable
25
+ readonly struct QueryStringEnumerable
26
26
{
27
- private readonly ReadOnlySpan < char > _queryString ;
27
+ private readonly ReadOnlyMemory < char > _queryString ;
28
28
29
29
/// <summary>
30
30
/// Constructs an instance of <see cref="QueryStringEnumerable"/>.
31
31
/// </summary>
32
32
/// <param name="queryString">The query string.</param>
33
- public QueryStringEnumerable ( ReadOnlySpan < char > queryString )
33
+ public QueryStringEnumerable ( string ? queryString )
34
+ : this ( queryString . AsMemory ( ) )
35
+ {
36
+ }
37
+
38
+ /// <summary>
39
+ /// Constructs an instance of <see cref="QueryStringEnumerable"/>.
40
+ /// </summary>
41
+ /// <param name="queryString">The query string.</param>
42
+ public QueryStringEnumerable ( ReadOnlyMemory < char > queryString )
34
43
{
35
44
_queryString = queryString ;
36
45
}
@@ -45,21 +54,21 @@ public Enumerator GetEnumerator()
45
54
/// <summary>
46
55
/// Represents a single name/value pair extracted from a query string during enumeration.
47
56
/// </summary>
48
- public readonly ref struct EncodedNameValuePair
57
+ public readonly struct EncodedNameValuePair
49
58
{
50
59
/// <summary>
51
60
/// Gets the name from this name/value pair in its original encoded form.
52
61
/// To get the decoded string, call <see cref="DecodeName"/>.
53
62
/// </summary>
54
- public readonly ReadOnlySpan < char > EncodedName { get ; }
63
+ public readonly ReadOnlyMemory < char > EncodedName { get ; }
55
64
56
65
/// <summary>
57
66
/// Gets the value from this name/value pair in its original encoded form.
58
67
/// To get the decoded string, call <see cref="DecodeValue"/>.
59
68
/// </summary>
60
- public readonly ReadOnlySpan < char > EncodedValue { get ; }
69
+ public readonly ReadOnlyMemory < char > EncodedValue { get ; }
61
70
62
- internal EncodedNameValuePair ( ReadOnlySpan < char > encodedName , ReadOnlySpan < char > encodedValue )
71
+ internal EncodedNameValuePair ( ReadOnlyMemory < char > encodedName , ReadOnlyMemory < char > encodedValue )
63
72
{
64
73
EncodedName = encodedName ;
65
74
EncodedValue = encodedValue ;
@@ -69,37 +78,37 @@ internal EncodedNameValuePair(ReadOnlySpan<char> encodedName, ReadOnlySpan<char>
69
78
/// Decodes the name from this name/value pair.
70
79
/// </summary>
71
80
/// <returns>Characters representing the decoded name.</returns>
72
- public ReadOnlySpan < char > DecodeName ( )
81
+ public ReadOnlyMemory < char > DecodeName ( )
73
82
=> Decode ( EncodedName ) ;
74
83
75
84
/// <summary>
76
85
/// Decodes the value from this name/value pair.
77
86
/// </summary>
78
87
/// <returns>Characters representing the decoded value.</returns>
79
- public ReadOnlySpan < char > DecodeValue ( )
88
+ public ReadOnlyMemory < char > DecodeValue ( )
80
89
=> Decode ( EncodedValue ) ;
81
90
82
- private static ReadOnlySpan < char > Decode ( ReadOnlySpan < char > chars )
91
+ private static ReadOnlyMemory < char > Decode ( ReadOnlyMemory < char > chars )
83
92
{
84
93
// If the value is short, it's cheap to check up front if it really needs decoding. If it doesn't,
85
94
// then we can save some allocations.
86
- return chars . Length < 16 && chars . IndexOfAny ( '%' , '+' ) < 0
95
+ return chars . Length < 16 && chars . Span . IndexOfAny ( '%' , '+' ) < 0
87
96
? chars
88
- : Uri . UnescapeDataString ( SpanHelper . ReplacePlusWithSpace ( chars ) ) ;
97
+ : Uri . UnescapeDataString ( SpanHelper . ReplacePlusWithSpace ( chars . Span ) ) . AsMemory ( ) ;
89
98
}
90
99
}
91
100
92
101
/// <summary>
93
102
/// An enumerator that supplies the name/value pairs from a URI query string.
94
103
/// </summary>
95
- public ref struct Enumerator
104
+ public struct Enumerator
96
105
{
97
- private ReadOnlySpan < char > _query ;
106
+ private ReadOnlyMemory < char > _query ;
98
107
99
- internal Enumerator ( ReadOnlySpan < char > query )
108
+ internal Enumerator ( ReadOnlyMemory < char > query )
100
109
{
101
110
Current = default ;
102
- _query = query . IsEmpty || query [ 0 ] != '?'
111
+ _query = query . IsEmpty || query . Span [ 0 ] != '?'
103
112
? query
104
113
: query . Slice ( 1 ) ;
105
114
}
@@ -118,8 +127,8 @@ public bool MoveNext()
118
127
while ( ! _query . IsEmpty )
119
128
{
120
129
// Chomp off the next segment
121
- ReadOnlySpan < char > segment ;
122
- var delimiterIndex = _query . IndexOf ( '&' ) ;
130
+ ReadOnlyMemory < char > segment ;
131
+ var delimiterIndex = _query . Span . IndexOf ( '&' ) ;
123
132
if ( delimiterIndex >= 0 )
124
133
{
125
134
segment = _query . Slice ( 0 , delimiterIndex ) ;
@@ -132,7 +141,7 @@ public bool MoveNext()
132
141
}
133
142
134
143
// If it's nonempty, emit it
135
- var equalIndex = segment . IndexOf ( '=' ) ;
144
+ var equalIndex = segment . Span . IndexOf ( '=' ) ;
136
145
if ( equalIndex >= 0 )
137
146
{
138
147
Current = new EncodedNameValuePair (
0 commit comments