@@ -112,6 +112,62 @@ public static byte[] ReadFully(this Stream input, byte[] buffer)
112
112
return tempStream . ToArray ( ) ;
113
113
}
114
114
115
+ /// <summary>
116
+ /// Reads the given stream up to the end, returning the data as a byte array.
117
+ /// </summary>
118
+ public static Task < byte [ ] > ReadFullyAsync ( this Stream input , CancellationToken token = default ) =>
119
+ ReadFullyAsync ( input , DefaultBufferSize , token ) ;
120
+
121
+ /// <summary>
122
+ /// Reads the given stream up to the end, returning the data as a byte
123
+ /// array, using the given buffer size.
124
+ /// </summary>
125
+ public static async Task < byte [ ] > ReadFullyAsync ( this Stream input , int bufferSize , CancellationToken token = default )
126
+ {
127
+ if ( bufferSize < 1 )
128
+ throw new ArgumentOutOfRangeException ( nameof ( bufferSize ) ) ;
129
+
130
+ byte [ ] buffer = BufferPool . GetBuffer ( bufferSize ) ;
131
+ try
132
+ {
133
+ return await ReadFullyAsync ( input , buffer , token ) ;
134
+ }
135
+ finally
136
+ {
137
+ BufferPool . ReleaseBufferToPool ( ref buffer ) ;
138
+ }
139
+ }
140
+
141
+ /// <summary>
142
+ /// Reads the given stream up to the end, returning the data as a byte
143
+ /// array, using the given buffer for transferring data. Note that the
144
+ /// current contents of the buffer is ignored, so the buffer needn't
145
+ /// be cleared beforehand.
146
+ /// </summary>
147
+ public static async Task < byte [ ] > ReadFullyAsync ( this Stream input , byte [ ] buffer , CancellationToken token = default )
148
+ {
149
+ if ( buffer == null )
150
+ throw new ArgumentNullException ( nameof ( buffer ) ) ;
151
+
152
+ if ( input == null )
153
+ throw new ArgumentNullException ( nameof ( input ) ) ;
154
+
155
+ if ( buffer . Length == 0 )
156
+ throw new ArgumentException ( "Buffer has length of 0" ) ;
157
+
158
+ // We could do all our own work here, but using MemoryStream is easier
159
+ // and likely to be just as efficient.
160
+ using var tempStream = MemoryStreamFactory . GetStream ( ) ;
161
+ await CopyToAsync ( input , tempStream , buffer , token ) ;
162
+ // No need to copy the buffer if it's the right size
163
+ if ( tempStream . Length == tempStream . GetBuffer ( ) . Length )
164
+ {
165
+ return tempStream . GetBuffer ( ) ;
166
+ }
167
+ // Okay, make a copy that's the right size
168
+ return tempStream . ToArray ( ) ;
169
+ }
170
+
115
171
/// <summary>
116
172
/// Reads the given stream up to the end, returning the MemoryStream Buffer as ReadOnlyMemory<byte>.
117
173
/// </summary>
@@ -150,6 +206,44 @@ public static ReadOnlyMemory<byte> ReadFullyAsMemory(this Stream input, byte[] b
150
206
return ms . GetBufferAsMemory ( ) ;
151
207
}
152
208
209
+ /// <summary>
210
+ /// Reads the given stream up to the end, returning the MemoryStream Buffer as ReadOnlyMemory<byte>.
211
+ /// </summary>
212
+ public static Task < ReadOnlyMemory < byte > > ReadFullyAsMemoryAsync ( this Stream input , CancellationToken token = default ) =>
213
+ ReadFullyAsMemoryAsync ( input , DefaultBufferSize , token ) ;
214
+
215
+ /// <summary>
216
+ /// Reads the given stream up to the end, returning the MemoryStream Buffer as ReadOnlyMemory<byte>.
217
+ /// </summary>
218
+ public static async Task < ReadOnlyMemory < byte > > ReadFullyAsMemoryAsync ( this Stream input , int bufferSize , CancellationToken token = default )
219
+ {
220
+ byte [ ] buffer = BufferPool . GetBuffer ( bufferSize ) ;
221
+ try
222
+ {
223
+ return await ReadFullyAsMemoryAsync ( input , buffer , token ) ;
224
+ }
225
+ finally
226
+ {
227
+ BufferPool . ReleaseBufferToPool ( ref buffer ) ;
228
+ }
229
+ }
230
+
231
+ public static async Task < ReadOnlyMemory < byte > > ReadFullyAsMemoryAsync ( this Stream input , byte [ ] buffer , CancellationToken token = default )
232
+ {
233
+ if ( buffer == null )
234
+ throw new ArgumentNullException ( nameof ( buffer ) ) ;
235
+
236
+ if ( input == null )
237
+ throw new ArgumentNullException ( nameof ( input ) ) ;
238
+
239
+ if ( buffer . Length == 0 )
240
+ throw new ArgumentException ( "Buffer has length of 0" ) ;
241
+
242
+ var ms = new MemoryStream ( ) ;
243
+ await CopyToAsync ( input , ms , buffer , token ) ;
244
+ return ms . GetBufferAsMemory ( ) ;
245
+ }
246
+
153
247
154
248
/// <summary>
155
249
/// Copies all the data from one stream into another.
@@ -200,6 +294,35 @@ public static long CopyTo(this Stream input, Stream output, byte[] buffer)
200
294
return total ;
201
295
}
202
296
297
+ /// <summary>
298
+ /// Copies all the data from one stream into another, using the given
299
+ /// buffer for transferring data. Note that the current contents of
300
+ /// the buffer is ignored, so the buffer needn't be cleared beforehand.
301
+ /// </summary>
302
+ public static async Task < long > CopyToAsync ( this Stream input , Stream output , byte [ ] buffer , CancellationToken token = default )
303
+ {
304
+ if ( buffer == null )
305
+ throw new ArgumentNullException ( nameof ( buffer ) ) ;
306
+
307
+ if ( input == null )
308
+ throw new ArgumentNullException ( nameof ( input ) ) ;
309
+
310
+ if ( output == null )
311
+ throw new ArgumentNullException ( nameof ( output ) ) ;
312
+
313
+ if ( buffer . Length == 0 )
314
+ throw new ArgumentException ( "Buffer has length of 0" ) ;
315
+
316
+ long total = 0 ;
317
+ int read ;
318
+ while ( ( read = await input . ReadAsync ( buffer , 0 , buffer . Length , token ) ) > 0 )
319
+ {
320
+ await output . WriteAsync ( buffer , 0 , read , token ) ;
321
+ total += read ;
322
+ }
323
+ return total ;
324
+ }
325
+
203
326
/// <summary>
204
327
/// Reads exactly the given number of bytes from the specified stream.
205
328
/// If the end of the stream is reached before the specified amount
0 commit comments