@@ -31,6 +31,8 @@ public static partial class MimeHelper
3131
3232 private static readonly Regex ScriptPattern = new ( @"^(?:application|text)/(?:javascript|ecmascript|x-php|x-sh|x-shellscript|x-python|x-ruby|x-perl)$" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
3333
34+ private static readonly SearchValues < char > QueryFragmentSeparators = SearchValues . Create ( "?#" ) ;
35+
3436 private static readonly HashSet < string > ScriptMimeSet = new ( StringComparer . OrdinalIgnoreCase )
3537 {
3638 "application/javascript" ,
@@ -403,7 +405,7 @@ private static IEnumerable<string> EnumerateExtensionCandidates(string value)
403405 yield break ;
404406 }
405407
406- var separatorIndex = trimmed . IndexOfAny ( new [ ] { '?' , '#' } ) ;
408+ var separatorIndex = trimmed . AsSpan ( ) . IndexOfAny ( QueryFragmentSeparators ) ;
407409 if ( separatorIndex >= 0 )
408410 {
409411 trimmed = trimmed [ ..separatorIndex ] ;
@@ -441,10 +443,12 @@ private static IEnumerable<string> EnumerateExtensionCandidates(string value)
441443 }
442444
443445 var yielded = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
446+ var sanitized = fileName . Trim ( '.' ) ;
444447 var index = fileName . IndexOf ( '.' ) ;
445448 while ( index >= 0 && index < fileName . Length - 1 )
446449 {
447- var candidate = fileName [ ( index + 1 ) ..] . Trim ( '.' ) ;
450+ var remainder = fileName [ ( index + 1 ) ..] ;
451+ var candidate = remainder . Trim ( '.' ) ;
448452 if ( candidate . Length > 0 && yielded . Add ( candidate ) )
449453 {
450454 yield return candidate ;
@@ -453,7 +457,6 @@ private static IEnumerable<string> EnumerateExtensionCandidates(string value)
453457 index = fileName . IndexOf ( '.' , index + 1 ) ;
454458 }
455459
456- var sanitized = fileName . Trim ( '.' ) ;
457460 if ( sanitized . Length > 0 && yielded . Add ( sanitized ) )
458461 {
459462 yield return sanitized ;
@@ -467,8 +470,41 @@ private static string NormalizeExtensionKey(string extension)
467470 return string . Empty ;
468471 }
469472
470- var normalized = extension . Trim ( ) . TrimStart ( '.' ) ;
471- return normalized . ToLowerInvariant ( ) ;
473+ var span = extension . AsSpan ( ) ;
474+
475+ var start = 0 ;
476+ var end = span . Length - 1 ;
477+
478+ while ( start <= end && char . IsWhiteSpace ( span [ start ] ) )
479+ {
480+ start ++ ;
481+ }
482+
483+ while ( end >= start && char . IsWhiteSpace ( span [ end ] ) )
484+ {
485+ end -- ;
486+ }
487+
488+ while ( start <= end && span [ start ] == '.' )
489+ {
490+ start ++ ;
491+ }
492+
493+ if ( start > end )
494+ {
495+ return string . Empty ;
496+ }
497+
498+ var length = end - start + 1 ;
499+
500+ return string . Create ( length , ( extension , start , length ) , static ( destination , state ) =>
501+ {
502+ var ( source , offset , count ) = state ;
503+ for ( var i = 0 ; i < count ; i ++ )
504+ {
505+ destination [ i ] = char . ToLowerInvariant ( source [ offset + i ] ) ;
506+ }
507+ } ) ;
472508 }
473509
474510 private static void RegisterMimeTypeInternal ( string extension , string mime )
0 commit comments