@@ -69,10 +69,10 @@ public override PropagationContext Extract<T>(PropagationContext context, T carr
6969 }
7070
7171 string ? tracestate = null ;
72- var tracestateCollection = getter ( carrier , TraceState ) ;
73- if ( tracestateCollection != null && HasAnyValues ( tracestateCollection ) )
72+ TryExtractTracestate ( getter ( carrier , TraceState ) , out var extractedTracestate , out var hasTraceState ) ;
73+ if ( hasTraceState )
7474 {
75- TryExtractTracestate ( tracestateCollection , out tracestate ) ;
75+ tracestate = extractedTracestate ;
7676 }
7777
7878 return new PropagationContext (
@@ -216,23 +216,83 @@ internal static bool TryExtractTraceparent(string traceparent, out ActivityTrace
216216 return true ;
217217 }
218218
219- internal static bool TryExtractTracestate ( string [ ] tracestateCollection , out string tracestateResult )
220- => TryExtractTracestate ( ( IEnumerable < string > ) tracestateCollection , out tracestateResult ) ;
219+ internal static bool TryExtractTracestate ( string [ ] ? tracestateCollection , out string tracestateResult )
220+ => TryExtractTracestate ( ( IEnumerable < string > ? ) tracestateCollection , out tracestateResult ) ;
221221
222- internal static bool TryExtractTracestate ( IEnumerable < string > tracestateCollection , out string tracestateResult )
222+ internal static bool TryExtractTracestate ( IEnumerable < string > ? tracestateCollection , out string tracestateResult )
223+ => TryExtractTracestate ( tracestateCollection , out tracestateResult , out _ ) ;
224+
225+ private static bool TryExtractTracestate ( IEnumerable < string > ? tracestateCollection , out string tracestateResult , out bool hasTraceState )
223226 {
224227 tracestateResult = string . Empty ;
228+ hasTraceState = false ;
225229
226230 if ( tracestateCollection == null )
227231 {
228232 return true ;
229233 }
230234
231- if ( TryGetSingleValue ( tracestateCollection , out var singleTraceState ) )
235+ if ( tracestateCollection is IList < string > list )
236+ {
237+ if ( list . Count == 0 )
238+ {
239+ return true ;
240+ }
241+
242+ hasTraceState = true ;
243+ if ( list . Count == 1 )
244+ {
245+ return TryExtractSingleTracestate ( list [ 0 ] , out tracestateResult ) ;
246+ }
247+
248+ return TryExtractMultipleTracestate ( list , out tracestateResult ) ;
249+ }
250+
251+ if ( tracestateCollection is IReadOnlyList < string > readOnlyList )
252+ {
253+ if ( readOnlyList . Count == 0 )
254+ {
255+ return true ;
256+ }
257+
258+ hasTraceState = true ;
259+ if ( readOnlyList . Count == 1 )
260+ {
261+ return TryExtractSingleTracestate ( readOnlyList [ 0 ] , out tracestateResult ) ;
262+ }
263+
264+ return TryExtractMultipleTracestate ( readOnlyList , out tracestateResult ) ;
265+ }
266+
267+ using var enumerator = tracestateCollection . GetEnumerator ( ) ;
268+ if ( ! enumerator . MoveNext ( ) )
269+ {
270+ return true ;
271+ }
272+
273+ hasTraceState = true ;
274+ var singleTraceState = enumerator . Current ;
275+ if ( ! enumerator . MoveNext ( ) )
232276 {
233277 return TryExtractSingleTracestate ( singleTraceState , out tracestateResult ) ;
234278 }
235279
280+ return TryExtractMultipleTracestate ( EnumerateFrom ( singleTraceState , enumerator ) , out tracestateResult ) ;
281+ }
282+
283+ private static IEnumerable < string > EnumerateFrom ( string first , IEnumerator < string > enumerator )
284+ {
285+ yield return first ;
286+
287+ do
288+ {
289+ yield return enumerator . Current ;
290+ }
291+ while ( enumerator . MoveNext ( ) ) ;
292+ }
293+
294+ private static bool TryExtractMultipleTracestate ( IEnumerable < string > tracestateCollection , out string tracestateResult )
295+ {
236296 var keySet = new HashSet < string > ( ) ;
237297 var result = new StringBuilder ( ) ;
238298
@@ -268,13 +328,15 @@ internal static bool TryExtractTracestate(IEnumerable<string> tracestateCollecti
268328 {
269329 // https://github.com/w3c/trace-context/blob/master/spec/20-http_request_header_format.md#list
270330 // test_tracestate_member_count_limit
331+ tracestateResult = string . Empty ;
271332 return false ;
272333 }
273334
274335 var keyLength = listMember . IndexOf ( '=' ) ;
275336 if ( keyLength == listMember . Length || keyLength == - 1 )
276337 {
277338 // Missing key or value in tracestate
339+ tracestateResult = string . Empty ;
278340 return false ;
279341 }
280342
@@ -284,20 +346,23 @@ internal static bool TryExtractTracestate(IEnumerable<string> tracestateCollecti
284346 // test_tracestate_key_illegal_characters in https://github.com/w3c/trace-context/blob/master/test/test.py
285347 // test_tracestate_key_length_limit
286348 // test_tracestate_key_illegal_vendor_format
349+ tracestateResult = string . Empty ;
287350 return false ;
288351 }
289352
290353 var value = listMember . Slice ( keyLength + 1 ) ;
291354 if ( ! ValidateValue ( value ) )
292355 {
293356 // test_tracestate_value_illegal_characters
357+ tracestateResult = string . Empty ;
294358 return false ;
295359 }
296360
297361 // ValidateKey() call above has ensured the key does not contain upper case letters.
298362 if ( ! keySet . Add ( key . ToString ( ) ) )
299363 {
300364 // test_tracestate_duplicated_keys
365+ tracestateResult = string . Empty ;
301366 return false ;
302367 }
303368
@@ -502,29 +567,6 @@ private static int GetKeyHashCode(ReadOnlySpan<char> key)
502567#endif
503568 }
504569
505- private static bool HasAnyValues ( IEnumerable < string > values )
506- {
507- #if NET
508- if ( values . TryGetNonEnumeratedCount ( out var count ) )
509- {
510- return count > 0 ;
511- }
512- #endif
513-
514- if ( values is ICollection < string > collection )
515- {
516- return collection . Count > 0 ;
517- }
518-
519- if ( values is IReadOnlyCollection < string > readOnlyCollection )
520- {
521- return readOnlyCollection . Count > 0 ;
522- }
523-
524- using var enumerator = values . GetEnumerator ( ) ;
525- return enumerator . MoveNext ( ) ;
526- }
527-
528570 private static bool TryGetSingleValue ( IEnumerable < string > ? values , out string value )
529571 {
530572 value = string . Empty ;
0 commit comments