@@ -44,7 +44,47 @@ public class BytesStringToArrayJsonConverter<TStruct> : JsonConverter<TStruct[]?
4444 Unsafe . SkipInit ( out byte [ ] ? utf8DataBuffer ) ;
4545 try
4646 {
47- // Try decode in Base64Url first.
47+ // Try decode in Hex first.
48+ if ( utf8DataLength % 2 == 0 )
49+ {
50+ // If the sample data length is odd, then trim the length (to make it even).
51+ if ( utf8SampleData . Length % 2 != 0 )
52+ {
53+ // Cut to up-to 16 bytes for sample data
54+ utf8SampleData = utf8SampleData [ ..Math . Min ( utf8SampleData . Length - 1 , 16 ) ] ;
55+ }
56+
57+ // Try to decode the sample data.
58+ Span < byte > hexTestDecodeBuffer = stackalloc byte [ utf8SampleData . Length / 2 ] ;
59+ OperationStatus hexTestDecodeStatus = Convert . FromHexString ( utf8SampleData , hexTestDecodeBuffer , out _ , out _ ) ;
60+ if ( hexTestDecodeStatus != OperationStatus . Done )
61+ {
62+ goto ResumeToBase64 ;
63+ }
64+
65+ // Alloc buffer
66+ utf8DataBuffer = utf8DataLength > 2048 ? ArrayPool < byte > . Shared . Rent ( utf8DataLength ) : null ;
67+ Span < byte > utf8DataSpan = utf8DataBuffer ?? stackalloc byte [ utf8DataLength ] ;
68+
69+ GetUtf8Data ( ref reader , utf8DataSpan ) ;
70+ utf8DataSpan = utf8DataSpan [ ..utf8DataLength ] ;
71+
72+ // Decode the hex string
73+ int hexBytesToDecodeLength = utf8DataLength / 2 ;
74+ TStruct [ ] hexDecodedStructBuffer = GC . AllocateUninitializedArray < TStruct > ( hexBytesToDecodeLength / sizeof ( TStruct ) ) ;
75+ Span < byte > hexDecodedStructSpan = MemoryMarshal . AsBytes ( hexDecodedStructBuffer . AsSpan ( ) ) ;
76+
77+ hexTestDecodeStatus = Convert . FromHexString ( utf8DataSpan , hexDecodedStructSpan , out _ , out _ ) ;
78+ if ( hexTestDecodeStatus != OperationStatus . Done )
79+ {
80+ ThrowFullHexDecodeFailedException ( hexTestDecodeStatus ) ;
81+ }
82+
83+ return hexDecodedStructBuffer ;
84+ }
85+
86+ ResumeToBase64 :
87+ // Then try Base64Url.
4888 if ( Base64Url . IsValid ( utf8SampleData ) )
4989 {
5090 // Alloc buffer
@@ -70,7 +110,7 @@ public class BytesStringToArrayJsonConverter<TStruct> : JsonConverter<TStruct[]?
70110 return base64DecodedStructBuffer ;
71111 }
72112
73- // Try decode in Base64 first .
113+ // Lastly, try Base64Url .
74114 if ( Base64 . IsValid ( utf8SampleData ) )
75115 {
76116 // Alloc buffer
@@ -100,45 +140,6 @@ public class BytesStringToArrayJsonConverter<TStruct> : JsonConverter<TStruct[]?
100140 utf8DataSpan . CopyTo ( base64DecodedStructSpan ) ;
101141 return base64DecodedStructBuffer ;
102142 }
103-
104- // Try decode in Hex.
105- if ( utf8DataLength % 2 == 0 )
106- {
107- // If the sample data length is odd, then trim the length (to make it even).
108- if ( utf8SampleData . Length % 2 != 0 )
109- {
110- // Cut to up-to 16 bytes for sample data
111- utf8SampleData = utf8SampleData [ ..Math . Min ( utf8SampleData . Length - 1 , 16 ) ] ;
112- }
113-
114- // Try to decode the sample data.
115- Span < byte > hexTestDecodeBuffer = stackalloc byte [ utf8SampleData . Length / 2 ] ;
116- OperationStatus hexTestDecodeStatus = Convert . FromHexString ( utf8SampleData , hexTestDecodeBuffer , out _ , out _ ) ;
117- if ( hexTestDecodeStatus != OperationStatus . Done )
118- {
119- ThrowTestingHexDecodeFailedException ( hexTestDecodeStatus ) ;
120- }
121-
122- // Alloc buffer
123- utf8DataBuffer = utf8DataLength > 2048 ? ArrayPool < byte > . Shared . Rent ( utf8DataLength ) : null ;
124- Span < byte > utf8DataSpan = utf8DataBuffer ?? stackalloc byte [ utf8DataLength ] ;
125-
126- GetUtf8Data ( ref reader , utf8DataSpan ) ;
127- utf8DataSpan = utf8DataSpan [ ..utf8DataLength ] ;
128-
129- // Decode the hex string
130- int hexBytesToDecodeLength = utf8DataLength / 2 ;
131- TStruct [ ] hexDecodedStructBuffer = GC . AllocateUninitializedArray < TStruct > ( hexBytesToDecodeLength / sizeof ( TStruct ) ) ;
132- Span < byte > hexDecodedStructSpan = MemoryMarshal . AsBytes ( hexDecodedStructBuffer . AsSpan ( ) ) ;
133-
134- hexTestDecodeStatus = Convert . FromHexString ( utf8DataSpan , hexDecodedStructSpan , out _ , out _ ) ;
135- if ( hexTestDecodeStatus != OperationStatus . Done )
136- {
137- ThrowFullHexDecodeFailedException ( hexTestDecodeStatus ) ;
138- }
139-
140- return hexDecodedStructBuffer ;
141- }
142143 }
143144 finally
144145 {
@@ -148,14 +149,12 @@ public class BytesStringToArrayJsonConverter<TStruct> : JsonConverter<TStruct[]?
148149 }
149150 }
150151
151- throw new InvalidOperationException ( $ "Value must be in Base64 or Hex string format!") ;
152+ // Gave up :(
153+ throw new InvalidOperationException ( "Value must be in Base64 or Hex string format!" ) ;
152154
153155 static void ThrowInvalidStructSizeToBufferException ( int sizeOfUtf8Data , int sizeOfStruct ) =>
154156 throw new InvalidOperationException ( $ "The decoded data length is not a multiple of the struct size ({ sizeOfUtf8Data } % { sizeOfStruct } = { sizeOfUtf8Data % sizeOfStruct } ).") ;
155157
156- static void ThrowTestingHexDecodeFailedException ( OperationStatus status ) =>
157- throw new InvalidOperationException ( $ "Failed while testing to decode Hex value with status: { status } .") ;
158-
159158 static void ThrowFullHexDecodeFailedException ( OperationStatus status ) =>
160159 throw new InvalidOperationException ( $ "Failed while trying to fully decode the Hex value with status: { status } .") ;
161160
0 commit comments