22// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33// See the LICENSE file in the project root for more information.
44
5+ using System ;
6+
57#if ELASTICSEARCH_SERVERLESS
68namespace Elastic . Clients . Elasticsearch . Serverless ;
79#else
@@ -10,18 +12,53 @@ namespace Elastic.Clients.Elasticsearch;
1012
1113internal static class StringExtensions
1214{
13- internal static string ToCamelCase ( this string s )
15+ // Taken from:
16+ // https://github.com/dotnet/runtime/blob/main/src/libraries/System.Text.Json/Common/JsonCamelCaseNamingPolicy.cs
17+
18+ internal static string ToCamelCase ( this string name )
1419 {
15- if ( string . IsNullOrEmpty ( s ) )
16- return s ;
20+ if ( string . IsNullOrEmpty ( name ) || ! char . IsUpper ( name [ 0 ] ) )
21+ {
22+ return name ;
23+ }
24+
25+ #if NET
26+ return string . Create ( name . Length , name , ( chars , name ) =>
27+ {
28+ name . CopyTo ( chars ) ;
29+ FixCasing ( chars ) ;
30+ } ) ;
31+ #else
32+ var chars = name . ToCharArray ( ) ;
33+ FixCasing ( chars ) ;
34+ return new string ( chars ) ;
35+ #endif
36+ }
37+
38+ private static void FixCasing ( Span < char > chars )
39+ {
40+ for ( var i = 0 ; i < chars . Length ; i ++ )
41+ {
42+ if ( i == 1 && ! char . IsUpper ( chars [ i ] ) )
43+ {
44+ break ;
45+ }
46+
47+ var hasNext = ( i + 1 < chars . Length ) ;
1748
18- if ( ! char . IsUpper ( s [ 0 ] ) )
19- return s ;
49+ // Stop when next char is already lowercase.
50+ if ( i > 0 && hasNext && ! char . IsUpper ( chars [ i + 1 ] ) )
51+ {
52+ // If the next char is a space, lowercase current char before exiting.
53+ if ( chars [ i + 1 ] == ' ' )
54+ {
55+ chars [ i ] = char . ToLowerInvariant ( chars [ i ] ) ;
56+ }
2057
21- var camelCase = char . ToLowerInvariant ( s [ 0 ] ) . ToString ( ) ;
22- if ( s . Length > 1 )
23- camelCase += s . Substring ( 1 ) ;
58+ break ;
59+ }
2460
25- return camelCase ;
61+ chars [ i ] = char . ToLowerInvariant ( chars [ i ] ) ;
62+ }
2663 }
2764}
0 commit comments