22// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33
44using System ;
5+ using System . Buffers ;
56using System . Diagnostics ;
67using System . Runtime . CompilerServices ;
78using System . Runtime . InteropServices ;
@@ -87,6 +88,7 @@ private static unsafe ulong GetMaskAsLong(byte[] bytes)
8788 }
8889
8990 // The same as GetAsciiStringNonNullCharacters but throws BadRequest
91+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
9092 public static unsafe string GetHeaderName ( this ReadOnlySpan < byte > span )
9193 {
9294 if ( span . IsEmpty )
@@ -96,24 +98,29 @@ public static unsafe string GetHeaderName(this ReadOnlySpan<byte> span)
9698
9799 fixed ( byte * source = & MemoryMarshal . GetReference ( span ) )
98100 {
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 ) )
100114 {
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+ }
111117 }
112118 }
113119
114120 public static string GetAsciiStringNonNullCharacters ( this Span < byte > span )
115121 => GetAsciiStringNonNullCharacters ( ( ReadOnlySpan < byte > ) span ) ;
116122
123+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
117124 public static unsafe string GetAsciiStringNonNullCharacters ( this ReadOnlySpan < byte > span )
118125 {
119126 if ( span . IsEmpty )
@@ -123,18 +130,22 @@ public static unsafe string GetAsciiStringNonNullCharacters(this ReadOnlySpan<by
123130
124131 fixed ( byte * source = & MemoryMarshal . GetReference ( span ) )
125132 {
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 ) )
127146 {
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+ }
138149 }
139150 }
140151
@@ -150,23 +161,12 @@ public static unsafe string GetAsciiOrUTF8StringNonNullCharacters(this ReadOnlyS
150161
151162 fixed ( byte * source = & MemoryMarshal . GetReference ( span ) )
152163 {
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 ) ;
166165
167166 // If rersultString is marked, perform UTF-8 encoding
168167 if ( resultString [ 0 ] == '\0 ' )
169168 {
169+ // null characters are considered invalid
170170 if ( span . IndexOf ( ( byte ) 0 ) != - 1 )
171171 {
172172 throw new InvalidOperationException ( ) ;
@@ -186,6 +186,22 @@ public static unsafe string GetAsciiOrUTF8StringNonNullCharacters(this ReadOnlyS
186186 }
187187 }
188188
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+
189205 public static string GetAsciiStringEscaped ( this Span < byte > span , int maxChars )
190206 {
191207 var sb = new StringBuilder ( ) ;
0 commit comments