Skip to content

Commit 8528092

Browse files
authored
Merge pull request #266 from OronDF343/add-memorystream-copytoasync
Asynchronous implementation of `MemorySource<TSource>.CopyToAsync`
2 parents 43bafc5 + 76e1900 commit 8528092

File tree

5 files changed

+85
-2
lines changed

5 files changed

+85
-2
lines changed

CommunityToolkit.HighPerformance/Streams/MemoryStream{TSource}.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,13 @@ public sealed override Task CopyToAsync(Stream destination, int bufferSize, Canc
119119

120120
try
121121
{
122-
CopyTo(destination, bufferSize);
122+
MemoryStream.ValidateDisposed(this.disposed);
123123

124-
return Task.CompletedTask;
124+
Memory<byte> source = this.source.Memory.Slice(this.position);
125+
126+
this.position += source.Length;
127+
128+
return destination.WriteAsync(source, cancellationToken).AsTask();
125129
}
126130
catch (OperationCanceledException e)
127131
{

CommunityToolkit.HighPerformance/Streams/Sources/ArrayOwner.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,11 @@ public Span<byte> Span
7474
#endif
7575
}
7676
}
77+
78+
/// <inheritdoc/>
79+
public Memory<byte> Memory
80+
{
81+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
82+
get => this.array.AsMemory(this.offset, this.length);
83+
}
7784
}

CommunityToolkit.HighPerformance/Streams/Sources/Interfaces/ISpanOwner.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ internal interface ISpanOwner
2020
/// Gets a <see cref="Span{T}"/> instance wrapping the underlying memory area.
2121
/// </summary>
2222
Span<byte> Span { get; }
23+
24+
/// <summary>
25+
/// Gets a <see cref="Memory{T}"/> instance wrapping the underlying memory area.
26+
/// </summary>
27+
Memory<byte> Memory { get; }
2328
}

CommunityToolkit.HighPerformance/Streams/Sources/MemoryManagerOwner.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,11 @@ public Span<byte> Span
6161
return this.memoryManager.GetSpan().Slice(this.offset, this.length);
6262
}
6363
}
64+
65+
/// <inheritdoc/>
66+
public Memory<byte> Memory
67+
{
68+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
69+
get => this.memoryManager.Memory.Slice(this.offset, this.length);
70+
}
6471
}

tests/CommunityToolkit.HighPerformance.UnitTests/Streams/Test_MemoryStream.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,66 @@ public async Task Test_MemoryStream_ReadWriteAsync_Memory()
252252
Assert.IsTrue(data.Span.SequenceEqual(result.Span));
253253
}
254254

255+
[TestMethod]
256+
public void Test_MemoryStream_CopyTo()
257+
{
258+
Stream source = new byte[100].AsMemory().AsStream();
259+
260+
Memory<byte> data = CreateRandomData(64);
261+
262+
source.Write(data.Span);
263+
264+
Assert.AreEqual(source.Position, data.Length);
265+
266+
source.Position = 0;
267+
268+
Stream destination = new byte[100].AsMemory().AsStream();
269+
270+
source.CopyTo(destination);
271+
272+
Assert.AreEqual(source.Position, destination.Position);
273+
274+
destination.Position = 0;
275+
276+
Memory<byte> result = new byte[data.Length];
277+
278+
int bytesRead = destination.Read(result.Span);
279+
280+
Assert.AreEqual(bytesRead, result.Length);
281+
Assert.AreEqual(destination.Position, data.Length);
282+
Assert.IsTrue(data.Span.SequenceEqual(result.Span));
283+
}
284+
285+
[TestMethod]
286+
public async Task Test_MemoryStream_CopyToAsync()
287+
{
288+
Stream source = new byte[100].AsMemory().AsStream();
289+
290+
Memory<byte> data = CreateRandomData(64);
291+
292+
await source.WriteAsync(data);
293+
294+
Assert.AreEqual(source.Position, data.Length);
295+
296+
source.Position = 0;
297+
298+
Stream destination = new byte[100].AsMemory().AsStream();
299+
300+
await source.CopyToAsync(destination);
301+
302+
Assert.AreEqual(source.Position, destination.Position);
303+
304+
destination.Position = 0;
305+
306+
Memory<byte> result = new byte[data.Length];
307+
308+
int bytesRead = await destination.ReadAsync(result);
309+
310+
Assert.AreEqual(bytesRead, result.Length);
311+
Assert.AreEqual(destination.Position, data.Length);
312+
Assert.IsTrue(data.Span.SequenceEqual(result.Span));
313+
}
314+
255315
/// <summary>
256316
/// Creates a random <see cref="byte"/> array filled with random data.
257317
/// </summary>

0 commit comments

Comments
 (0)