@@ -22,15 +22,24 @@ namespace Microsoft.AspNetCore.Internal
2222#else
2323 internal
2424#endif
25- readonly ref struct QueryStringEnumerable
25+ readonly struct QueryStringEnumerable
2626 {
27- private readonly ReadOnlySpan < char > _queryString ;
27+ private readonly ReadOnlyMemory < char > _queryString ;
2828
2929 /// <summary>
3030 /// Constructs an instance of <see cref="QueryStringEnumerable"/>.
3131 /// </summary>
3232 /// <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 )
3443 {
3544 _queryString = queryString ;
3645 }
@@ -45,21 +54,21 @@ public Enumerator GetEnumerator()
4554 /// <summary>
4655 /// Represents a single name/value pair extracted from a query string during enumeration.
4756 /// </summary>
48- public readonly ref struct EncodedNameValuePair
57+ public readonly struct EncodedNameValuePair
4958 {
5059 /// <summary>
5160 /// Gets the name from this name/value pair in its original encoded form.
5261 /// To get the decoded string, call <see cref="DecodeName"/>.
5362 /// </summary>
54- public readonly ReadOnlySpan < char > EncodedName { get ; }
63+ public readonly ReadOnlyMemory < char > EncodedName { get ; }
5564
5665 /// <summary>
5766 /// Gets the value from this name/value pair in its original encoded form.
5867 /// To get the decoded string, call <see cref="DecodeValue"/>.
5968 /// </summary>
60- public readonly ReadOnlySpan < char > EncodedValue { get ; }
69+ public readonly ReadOnlyMemory < char > EncodedValue { get ; }
6170
62- internal EncodedNameValuePair ( ReadOnlySpan < char > encodedName , ReadOnlySpan < char > encodedValue )
71+ internal EncodedNameValuePair ( ReadOnlyMemory < char > encodedName , ReadOnlyMemory < char > encodedValue )
6372 {
6473 EncodedName = encodedName ;
6574 EncodedValue = encodedValue ;
@@ -69,37 +78,37 @@ internal EncodedNameValuePair(ReadOnlySpan<char> encodedName, ReadOnlySpan<char>
6978 /// Decodes the name from this name/value pair.
7079 /// </summary>
7180 /// <returns>Characters representing the decoded name.</returns>
72- public ReadOnlySpan < char > DecodeName ( )
81+ public ReadOnlyMemory < char > DecodeName ( )
7382 => Decode ( EncodedName ) ;
7483
7584 /// <summary>
7685 /// Decodes the value from this name/value pair.
7786 /// </summary>
7887 /// <returns>Characters representing the decoded value.</returns>
79- public ReadOnlySpan < char > DecodeValue ( )
88+ public ReadOnlyMemory < char > DecodeValue ( )
8089 => Decode ( EncodedValue ) ;
8190
82- private static ReadOnlySpan < char > Decode ( ReadOnlySpan < char > chars )
91+ private static ReadOnlyMemory < char > Decode ( ReadOnlyMemory < char > chars )
8392 {
8493 // If the value is short, it's cheap to check up front if it really needs decoding. If it doesn't,
8594 // then we can save some allocations.
86- return chars . Length < 16 && chars . IndexOfAny ( '%' , '+' ) < 0
95+ return chars . Length < 16 && chars . Span . IndexOfAny ( '%' , '+' ) < 0
8796 ? chars
88- : Uri . UnescapeDataString ( SpanHelper . ReplacePlusWithSpace ( chars ) ) ;
97+ : Uri . UnescapeDataString ( SpanHelper . ReplacePlusWithSpace ( chars . Span ) ) . AsMemory ( ) ;
8998 }
9099 }
91100
92101 /// <summary>
93102 /// An enumerator that supplies the name/value pairs from a URI query string.
94103 /// </summary>
95- public ref struct Enumerator
104+ public struct Enumerator
96105 {
97- private ReadOnlySpan < char > _query ;
106+ private ReadOnlyMemory < char > _query ;
98107
99- internal Enumerator ( ReadOnlySpan < char > query )
108+ internal Enumerator ( ReadOnlyMemory < char > query )
100109 {
101110 Current = default ;
102- _query = query . IsEmpty || query [ 0 ] != '?'
111+ _query = query . IsEmpty || query . Span [ 0 ] != '?'
103112 ? query
104113 : query . Slice ( 1 ) ;
105114 }
@@ -118,8 +127,8 @@ public bool MoveNext()
118127 while ( ! _query . IsEmpty )
119128 {
120129 // Chomp off the next segment
121- ReadOnlySpan < char > segment ;
122- var delimiterIndex = _query . IndexOf ( '&' ) ;
130+ ReadOnlyMemory < char > segment ;
131+ var delimiterIndex = _query . Span . IndexOf ( '&' ) ;
123132 if ( delimiterIndex >= 0 )
124133 {
125134 segment = _query . Slice ( 0 , delimiterIndex ) ;
@@ -132,7 +141,7 @@ public bool MoveNext()
132141 }
133142
134143 // If it's nonempty, emit it
135- var equalIndex = segment . IndexOf ( '=' ) ;
144+ var equalIndex = segment . Span . IndexOf ( '=' ) ;
136145 if ( equalIndex >= 0 )
137146 {
138147 Current = new EncodedNameValuePair (
0 commit comments