|
1 | 1 | using System;
|
2 | 2 | using System.IO;
|
3 | 3 | using System.Threading;
|
| 4 | +using System.Threading.Tasks; |
4 | 5 |
|
5 | 6 | namespace ICSharpCode.SharpZipLib.Tests.TestSupport
|
6 | 7 | {
|
@@ -188,6 +189,77 @@ public override long Position
|
188 | 189 |
|
189 | 190 | }
|
190 | 191 |
|
| 192 | +#if NETSTANDARD2_1 || NETCOREAPP3_0_OR_GREATER |
| 193 | + /// <summary> |
| 194 | + /// A <see cref="Stream"/> that does not support non-async operations. |
| 195 | + /// </summary> |
| 196 | + /// <remarks> |
| 197 | + /// This could not be done by extending MemoryStream itself, since other instances of MemoryStream tries to us a faster (non-async) method of copying |
| 198 | + /// if it detects that it's a (subclass of) MemoryStream. |
| 199 | + /// </remarks> |
| 200 | + public class MemoryStreamWithoutSync : Stream |
| 201 | + { |
| 202 | + MemoryStream _inner = new MemoryStream(); |
| 203 | + |
| 204 | + public override bool CanRead => _inner.CanRead; |
| 205 | + public override bool CanSeek => _inner.CanSeek; |
| 206 | + public override bool CanWrite => _inner.CanWrite; |
| 207 | + public override long Length => _inner.Length; |
| 208 | + public override long Position { get => _inner.Position; set => _inner.Position = value; } |
| 209 | + |
| 210 | + public byte[] ToArray() => _inner.ToArray(); |
| 211 | + |
| 212 | + public override void Flush() => throw new NotSupportedException($"Non-async call to {nameof(Flush)}"); |
| 213 | + |
| 214 | + |
| 215 | + public override void CopyTo(Stream destination, int bufferSize) => throw new NotSupportedException($"Non-async call to {nameof(CopyTo)}"); |
| 216 | + public override void Write(ReadOnlySpan<byte> buffer) => throw new NotSupportedException($"Non-async call to {nameof(Write)}"); |
| 217 | + public override int Read(Span<byte> buffer) => throw new NotSupportedException($"Non-async call to {nameof(Read)}"); |
| 218 | + |
| 219 | + public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException($"Non-async call to {nameof(Write)}"); |
| 220 | + public override void WriteByte(byte value) => throw new NotSupportedException($"Non-async call to {nameof(Write)}"); |
| 221 | + |
| 222 | + public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException($"Non-async call to {nameof(Read)}"); |
| 223 | + public override int ReadByte() => throw new NotSupportedException($"Non-async call to {nameof(ReadByte)}"); |
| 224 | + |
| 225 | + // Even though our mock stream is writing synchronously, this should not fail the tests |
| 226 | + public override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) |
| 227 | + { |
| 228 | + var buf = new byte[bufferSize]; |
| 229 | + while(_inner.Read(buf, 0, bufferSize) > 0) { |
| 230 | + await destination.WriteAsync(buf, cancellationToken); |
| 231 | + } |
| 232 | + } |
| 233 | + public override Task FlushAsync(CancellationToken cancellationToken) => TaskFromBlocking(() => _inner.Flush()); |
| 234 | + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => TaskFromBlocking(() => _inner.Write(buffer, offset, count)); |
| 235 | + public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => Task.FromResult(_inner.Read(buffer, offset, count)); |
| 236 | + public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default) => ValueTaskFromBlocking(() => _inner.Write(buffer.Span)); |
| 237 | + public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default) => ValueTask.FromResult(_inner.Read(buffer.Span)); |
| 238 | + |
| 239 | + static Task TaskFromBlocking(Action action) |
| 240 | + { |
| 241 | + action(); |
| 242 | + return Task.CompletedTask; |
| 243 | + } |
| 244 | + |
| 245 | + static ValueTask ValueTaskFromBlocking(Action action) |
| 246 | + { |
| 247 | + action(); |
| 248 | + return ValueTask.CompletedTask; |
| 249 | + } |
| 250 | + |
| 251 | + public override long Seek(long offset, SeekOrigin origin) |
| 252 | + { |
| 253 | + return _inner.Seek(offset, origin); |
| 254 | + } |
| 255 | + |
| 256 | + public override void SetLength(long value) |
| 257 | + { |
| 258 | + _inner.SetLength(value); |
| 259 | + } |
| 260 | + } |
| 261 | +#endif |
| 262 | + |
191 | 263 | /// <summary>
|
192 | 264 | /// A <see cref="Stream"/> that cannot be read but supports infinite writes.
|
193 | 265 | /// </summary>
|
|
0 commit comments