@@ -207,27 +207,45 @@ public static unsafe T Read<T>(this Stream stream)
207
207
{
208
208
#if NETSTANDARD2_1_OR_GREATER
209
209
T result = default ;
210
- int length = sizeof ( T ) ;
210
+ int bytesOffset = 0 ;
211
211
212
- unsafe
212
+ // As per Stream.Read's documentation:
213
+ // "The total number of bytes read into the buffer. This can be less than the number of bytes allocated in the
214
+ // buffer if that many bytes are not currently available, or zero (0) if the end of the stream has been reached."
215
+ // Because of this, we have to loop until all requires bytes have been read, and only throw if the return is 0.
216
+ do
213
217
{
214
- if ( stream . Read ( new Span < byte > ( & result , length ) ) != length )
218
+ int bytesRead = stream . Read ( new Span < byte > ( ( byte * ) & result + bytesOffset , sizeof ( T ) - bytesOffset ) ) ;
219
+
220
+ // A return value of 0 indicates that the end of the stream has been reached
221
+ if ( bytesRead == 0 )
215
222
{
216
223
ThrowInvalidOperationExceptionForEndOfStream ( ) ;
217
224
}
225
+
226
+ bytesOffset += bytesRead ;
218
227
}
228
+ while ( bytesOffset < sizeof ( T ) ) ;
219
229
220
230
return result ;
221
231
#else
222
- int length = sizeof ( T ) ;
223
- byte [ ] buffer = ArrayPool < byte > . Shared . Rent ( length ) ;
232
+ int bytesOffset = 0 ;
233
+ byte [ ] buffer = ArrayPool < byte > . Shared . Rent ( sizeof ( T ) ) ;
224
234
225
235
try
226
236
{
227
- if ( stream . Read ( buffer , 0 , length ) != length )
237
+ do
228
238
{
229
- ThrowInvalidOperationExceptionForEndOfStream ( ) ;
239
+ int bytesRead = stream . Read ( buffer . AsSpan ( bytesOffset , sizeof ( T ) - bytesOffset ) ) ;
240
+
241
+ if ( bytesRead == 0 )
242
+ {
243
+ ThrowInvalidOperationExceptionForEndOfStream ( ) ;
244
+ }
245
+
246
+ bytesOffset += bytesRead ;
230
247
}
248
+ while ( bytesOffset < sizeof ( T ) ) ;
231
249
232
250
return Unsafe . ReadUnaligned < T > ( ref buffer [ 0 ] ) ;
233
251
}
0 commit comments