2
2
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3
3
4
4
using System ;
5
+ using System . Buffers ;
5
6
using System . Diagnostics ;
6
7
using System . Runtime . CompilerServices ;
7
8
using System . Runtime . InteropServices ;
@@ -87,6 +88,7 @@ private static unsafe ulong GetMaskAsLong(byte[] bytes)
87
88
}
88
89
89
90
// The same as GetAsciiStringNonNullCharacters but throws BadRequest
91
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
90
92
public static unsafe string GetHeaderName ( this ReadOnlySpan < byte > span )
91
93
{
92
94
if ( span . IsEmpty )
@@ -96,24 +98,29 @@ public static unsafe string GetHeaderName(this ReadOnlySpan<byte> span)
96
98
97
99
fixed ( byte * source = & MemoryMarshal . GetReference ( span ) )
98
100
{
99
- return string . Create ( span . Length , new IntPtr ( source ) , ( buffer , state ) =>
101
+ return string . Create ( span . Length , new IntPtr ( source ) , s_getHeaderName ) ;
102
+ }
103
+ }
104
+
105
+ private static readonly SpanAction < char , IntPtr > s_getHeaderName = GetHeaderName ;
106
+
107
+ private static unsafe void GetHeaderName ( Span < char > buffer , IntPtr state )
108
+ {
109
+ fixed ( char * output = & MemoryMarshal . GetReference ( buffer ) )
110
+ {
111
+ // This version if AsciiUtilities returns null if there are any null (0 byte) characters
112
+ // in the string
113
+ if ( ! StringUtilities . TryGetAsciiString ( ( byte * ) state . ToPointer ( ) , output , buffer . Length ) )
100
114
{
101
- fixed ( char * output = & MemoryMarshal . GetReference ( buffer ) )
102
- {
103
- // This version if AsciiUtilities returns null if there are any null (0 byte) characters
104
- // in the string
105
- if ( ! StringUtilities . TryGetAsciiString ( ( byte * ) state . ToPointer ( ) , output , buffer . Length ) )
106
- {
107
- BadHttpRequestException . Throw ( RequestRejectionReason . InvalidCharactersInHeaderName ) ;
108
- }
109
- }
110
- } ) ;
115
+ BadHttpRequestException . Throw ( RequestRejectionReason . InvalidCharactersInHeaderName ) ;
116
+ }
111
117
}
112
118
}
113
119
114
120
public static string GetAsciiStringNonNullCharacters ( this Span < byte > span )
115
121
=> GetAsciiStringNonNullCharacters ( ( ReadOnlySpan < byte > ) span ) ;
116
122
123
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
117
124
public static unsafe string GetAsciiStringNonNullCharacters ( this ReadOnlySpan < byte > span )
118
125
{
119
126
if ( span . IsEmpty )
@@ -123,18 +130,22 @@ public static unsafe string GetAsciiStringNonNullCharacters(this ReadOnlySpan<by
123
130
124
131
fixed ( byte * source = & MemoryMarshal . GetReference ( span ) )
125
132
{
126
- return string . Create ( span . Length , new IntPtr ( source ) , ( buffer , state ) =>
133
+ return string . Create ( span . Length , new IntPtr ( source ) , s_getAsciiStringNonNullCharacters ) ;
134
+ }
135
+ }
136
+
137
+ private static readonly SpanAction < char , IntPtr > s_getAsciiStringNonNullCharacters = GetAsciiStringNonNullCharacters ;
138
+
139
+ private static unsafe void GetAsciiStringNonNullCharacters ( Span < char > buffer , IntPtr state )
140
+ {
141
+ fixed ( char * output = & MemoryMarshal . GetReference ( buffer ) )
142
+ {
143
+ // This version if AsciiUtilities returns null if there are any null (0 byte) characters
144
+ // in the string
145
+ if ( ! StringUtilities . TryGetAsciiString ( ( byte * ) state . ToPointer ( ) , output , buffer . Length ) )
127
146
{
128
- fixed ( char * output = & MemoryMarshal . GetReference ( buffer ) )
129
- {
130
- // This version if AsciiUtilities returns null if there are any null (0 byte) characters
131
- // in the string
132
- if ( ! StringUtilities . TryGetAsciiString ( ( byte * ) state . ToPointer ( ) , output , buffer . Length ) )
133
- {
134
- throw new InvalidOperationException ( ) ;
135
- }
136
- }
137
- } ) ;
147
+ throw new InvalidOperationException ( ) ;
148
+ }
138
149
}
139
150
}
140
151
@@ -150,23 +161,12 @@ public static unsafe string GetAsciiOrUTF8StringNonNullCharacters(this ReadOnlyS
150
161
151
162
fixed ( byte * source = & MemoryMarshal . GetReference ( span ) )
152
163
{
153
- var resultString = string . Create ( span . Length , new IntPtr ( source ) , ( buffer , state ) =>
154
- {
155
- fixed ( char * output = & MemoryMarshal . GetReference ( buffer ) )
156
- {
157
- // This version if AsciiUtilities returns null if there are any null (0 byte) characters
158
- // in the string
159
- if ( ! StringUtilities . TryGetAsciiString ( ( byte * ) state . ToPointer ( ) , output , buffer . Length ) )
160
- {
161
- // Mark resultString for UTF-8 encoding
162
- output [ 0 ] = '\0 ' ;
163
- }
164
- }
165
- } ) ;
164
+ var resultString = string . Create ( span . Length , new IntPtr ( source ) , s_getAsciiOrUtf8StringNonNullCharacters ) ;
166
165
167
166
// If rersultString is marked, perform UTF-8 encoding
168
167
if ( resultString [ 0 ] == '\0 ' )
169
168
{
169
+ // null characters are considered invalid
170
170
if ( span . IndexOf ( ( byte ) 0 ) != - 1 )
171
171
{
172
172
throw new InvalidOperationException ( ) ;
@@ -186,6 +186,22 @@ public static unsafe string GetAsciiOrUTF8StringNonNullCharacters(this ReadOnlyS
186
186
}
187
187
}
188
188
189
+ private static readonly SpanAction < char , IntPtr > s_getAsciiOrUtf8StringNonNullCharacters = GetAsciiOrUTF8StringNonNullCharacters ;
190
+
191
+ private static unsafe void GetAsciiOrUTF8StringNonNullCharacters ( Span < char > buffer , IntPtr state )
192
+ {
193
+ fixed ( char * output = & MemoryMarshal . GetReference ( buffer ) )
194
+ {
195
+ // This version if AsciiUtilities returns null if there are any null (0 byte) characters
196
+ // in the string
197
+ if ( ! StringUtilities . TryGetAsciiString ( ( byte * ) state . ToPointer ( ) , output , buffer . Length ) )
198
+ {
199
+ // Mark resultString for UTF-8 encoding
200
+ output [ 0 ] = '\0 ' ;
201
+ }
202
+ }
203
+ }
204
+
189
205
public static string GetAsciiStringEscaped ( this Span < byte > span , int maxChars )
190
206
{
191
207
var sb = new StringBuilder ( ) ;
0 commit comments