@@ -11,9 +11,12 @@ namespace PolylineAlgorithm.Abstraction;
1111using PolylineAlgorithm . Internal . Logging ;
1212using PolylineAlgorithm . Properties ;
1313using System ;
14+ using System . Buffers ;
1415using System . Collections . Generic ;
1516using System . Diagnostics ;
17+ using System . Diagnostics . CodeAnalysis ;
1618using System . Runtime . CompilerServices ;
19+ using static PolylineAlgorithm . Internal . Defaults . Polyline . Block ;
1720
1821/// <summary>
1922/// Provides functionality to encode a collection of geographic coordinates into an encoded polyline string.
@@ -57,7 +60,6 @@ protected AbstractPolylineEncoder(PolylineEncodingOptions options) {
5760 /// </param>
5861 /// <returns>
5962 /// An instance of <typeparamref name="TPolyline"/> representing the encoded coordinates.
60- /// Returns <see langword="default"/> if the input collection is empty or null.
6163 /// </returns>
6264 /// <exception cref="ArgumentNullException">
6365 /// Thrown when <paramref name="coordinates"/> is <see langword="null"/>.
@@ -81,38 +83,48 @@ public TPolyline Encode(ReadOnlySpan<TCoordinate> coordinates) {
8183 int consumed = 0 ;
8284 int length = GetMaxBufferLength ( coordinates . Length , _logger ) ;
8385
84- Span < char > buffer = stackalloc char [ length ] ;
86+ char [ ] ? temp = length <= Options . StackAllocLimit
87+ ? null
88+ : ArrayPool < char > . Shared . Rent ( length ) ;
8589
86- for ( var i = 0 ; i < coordinates . Length ; i ++ ) {
87- variance
88- . Next (
89- PolylineEncoding . Normalize ( GetLatitude ( coordinates [ i ] ) , CoordinateValueType . Latitude ) ,
90- PolylineEncoding . Normalize ( GetLongitude ( coordinates [ i ] ) , CoordinateValueType . Longitude )
91- ) ;
90+ Span < char > buffer = temp is null ? stackalloc char [ length ] : temp . AsSpan ( 0 , length ) ;
9291
93- ValidateBuffer ( ref variance , ref position , ref buffer , _logger ) ;
92+ try {
93+ for ( var i = 0 ; i < coordinates . Length ; i ++ ) {
94+ variance
95+ . Next (
96+ PolylineEncoding . Normalize ( GetLatitude ( coordinates [ i ] ) , CoordinateValueType . Latitude ) ,
97+ PolylineEncoding . Normalize ( GetLongitude ( coordinates [ i ] ) , CoordinateValueType . Longitude )
98+ ) ;
9499
95- if ( ! PolylineEncoding . TryWriteValue ( variance . Latitude , ref buffer , ref position )
96- || ! PolylineEncoding . TryWriteValue ( variance . Longitude , ref buffer , ref position )
97- ) {
98- // This shouldn't happen, but if it does, log the error and throw an exception.
99- _logger
100- . LogOperationFailedDebug ( OperationName ) ;
101- _logger
102- . LogCannotWriteValueToBufferWarning ( position , consumed ) ;
100+ ValidateBuffer ( variance , position , buffer , _logger ) ;
103101
104- throw new InvalidOperationException ( ExceptionMessageResource . CouldNotWriteEncodedValueToTheBuffer ) ;
105- }
102+ if ( ! PolylineEncoding . TryWriteValue ( variance . Latitude , buffer , ref position )
103+ || ! PolylineEncoding . TryWriteValue ( variance . Longitude , buffer , ref position )
104+ ) {
105+ // This shouldn't happen, but if it does, log the error and throw an exception.
106+ _logger
107+ . LogOperationFailedDebug ( OperationName ) ;
108+ _logger
109+ . LogCannotWriteValueToBufferWarning ( position , consumed ) ;
110+
111+ throw new InvalidOperationException ( ExceptionMessageResource . CouldNotWriteEncodedValueToTheBuffer ) ;
112+ }
106113
107- consumed ++ ;
114+ consumed ++ ;
115+ }
116+ } finally {
117+ if ( temp is not null ) {
118+ ArrayPool < char > . Shared . Return ( temp ) ;
119+ }
108120 }
109121
122+
123+
110124 _logger
111125 . LogOperationFinishedDebug ( OperationName ) ;
112126
113- var result = buffer [ ..position ] . ToString ( ) . AsMemory ( ) ;
114-
115- return CreatePolyline ( ref result ) ;
127+ return CreatePolyline ( buffer [ ..position ] . ToString ( ) . AsMemory ( ) ) ;
116128
117129 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
118130 static int GetRequiredLength ( CoordinateVariance variance ) =>
@@ -134,16 +146,8 @@ int GetMaxBufferLength(int count, ILogger logger) {
134146
135147 int requestedBufferLength = count * Defaults . Polyline . Block . Length . Max ;
136148
137- Debug . Assert ( Options . MaxBufferLength > 0 , "Max buffer length must be greater than zero." ) ;
138149 Debug . Assert ( requestedBufferLength > 0 , "Requested buffer length must be greater than zero." ) ;
139150
140- if ( requestedBufferLength > Options . MaxBufferLength ) {
141- logger
142- . LogRequestedBufferSizeExceedsMaxBufferLengthWarning ( requestedBufferLength , Options . MaxBufferLength ) ;
143-
144- return Options . MaxBufferLength ;
145- }
146-
147151 return requestedBufferLength ;
148152 }
149153
@@ -160,7 +164,7 @@ static void ValidateEmptyCoordinates(ref ReadOnlySpan<TCoordinate> coordinates,
160164 }
161165
162166 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
163- static void ValidateBuffer ( ref CoordinateVariance variance , ref int position , ref Span < char > buffer , ILogger logger ) {
167+ static void ValidateBuffer ( CoordinateVariance variance , int position , Span < char > buffer , ILogger logger ) {
164168 if ( GetRemainingBufferSize ( position , buffer . Length ) < GetRequiredLength ( variance ) ) {
165169 logger
166170 . LogOperationFailedDebug ( OperationName ) ;
@@ -180,7 +184,7 @@ static void ValidateBuffer(ref CoordinateVariance variance, ref int position, re
180184 /// An instance of <typeparamref name="TPolyline"/> representing the encoded polyline.
181185 /// </returns>
182186 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
183- protected abstract TPolyline CreatePolyline ( ref ReadOnlyMemory < char > polyline ) ;
187+ protected abstract TPolyline CreatePolyline ( ReadOnlyMemory < char > polyline ) ;
184188
185189 /// <summary>
186190 /// Extracts the longitude value from the specified coordinate.
0 commit comments