Skip to content

Commit 7895451

Browse files
committed
override Stream.WriteAsync(byte[], int, int, CancellationToken) and Stream.WriteAsync(ReadOnlyMemory, CancellationToken)
1 parent 8f8d417 commit 7895451

File tree

2 files changed

+114
-18
lines changed

2 files changed

+114
-18
lines changed

src/Smdn.Fundamental.Stream/Smdn.IO.Streams/PartialStream.cs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,21 +266,46 @@ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken
266266
}
267267
#endif
268268

269+
private void CheckWriteRemainder(int count, string nameOfCountParameter)
270+
{
271+
if (count < 0)
272+
throw ExceptionUtils.CreateArgumentMustBeZeroOrPositive(nameOfCountParameter, count);
273+
274+
if (GetRemainderLength() - count < 0L)
275+
throw new IOException("attempted to write after end of stream");
276+
}
277+
269278
public override void Write(byte[] buffer, int offset, int count)
270279
{
271280
CheckDisposed();
272281
CheckWritable();
282+
CheckWriteRemainder(count, nameof(count));
273283

274-
if (count < 0)
275-
throw ExceptionUtils.CreateArgumentMustBeZeroOrPositive(nameof(count), count);
284+
stream.Write(buffer, offset, count);
285+
}
276286

277-
var remainder = GetRemainderLength() - count;
287+
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default)
288+
{
289+
CheckDisposed();
290+
CheckWritable();
291+
CheckWriteRemainder(count, nameof(count));
278292

279-
if (remainder < 0L)
280-
throw new IOException("attempted to write after end of stream");
281-
else
282-
stream.Write(buffer, offset, count);
293+
return stream.WriteAsync(buffer, offset, count, cancellationToken);
294+
}
295+
296+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
297+
public override ValueTask WriteAsync(
298+
ReadOnlyMemory<byte> buffer,
299+
CancellationToken cancellationToken = default
300+
)
301+
{
302+
CheckDisposed();
303+
CheckWritable();
304+
CheckWriteRemainder(buffer.Length, nameof(buffer));
305+
306+
return stream.WriteAsync(buffer, cancellationToken);
283307
}
308+
#endif
284309

285310
private void CheckDisposed()
286311
{

tests/Smdn/Smdn.IO.Streams/PartialStream.cs

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ public void TestConstructReadOnlyWithWritableStream()
5555
Assert.IsFalse(stream.CanWrite);
5656

5757
Assert.Throws<NotSupportedException>(() => stream.Write(new byte[] {0x00, 0x01, 0x02, 0x03}, 0, 4));
58+
Assert.Throws<NotSupportedException>(() => stream.WriteAsync(new byte[] {0x00, 0x01, 0x02, 0x03}, 0, 4));
5859
Assert.Throws<NotSupportedException>(() => stream.WriteByte(0x00));
60+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
61+
Assert.Throws<NotSupportedException>(() => stream.WriteAsync(ReadOnlyMemory<byte>.Empty));
62+
#endif
5963

6064
var len = stream.Length;
6165
var pos = stream.Position;
@@ -164,7 +168,10 @@ private void TestClose(PartialStream stream)
164168
#endif
165169
Assert.Throws<ObjectDisposedException>(() =>stream.WriteByte(0x00));
166170
Assert.Throws<ObjectDisposedException>(() => stream.Write(_Array.Empty<byte>(), 0, 0));
167-
//Assert.Throws<ObjectDisposedException>(() => stream.WriteAsync(_Array.Empty<byte>(), 0, 0));
171+
Assert.Throws<ObjectDisposedException>(() => stream.WriteAsync(_Array.Empty<byte>(), 0, 0));
172+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
173+
Assert.Throws<ObjectDisposedException>(() => stream.WriteAsync(ReadOnlyMemory<byte>.Empty));
174+
#endif
168175

169176
stream.Dispose();
170177
}
@@ -379,8 +386,21 @@ public void TestReadByte_LengthNotSpecified()
379386
Assert.AreEqual(8, stream.InnerStream.Position);
380387
}
381388

382-
[Test]
383-
public void TestWriteLengthSpecified()
389+
enum WriteMethod {
390+
Write,
391+
WriteAsync,
392+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
393+
WriteAsyncFromReadOnlyMemory,
394+
#endif
395+
}
396+
397+
[Test] public Task TestWrite_LengthSpecified() => TestWrite_LengthSpecified(WriteMethod.Write);
398+
[Test] public Task TestWriteAsync_LengthSpecified() => TestWrite_LengthSpecified(WriteMethod.WriteAsync);
399+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
400+
[Test] public Task TestWriteAsync_FromReadOnlyMemory_LengthSpecified() => TestWrite_LengthSpecified(WriteMethod.WriteAsyncFromReadOnlyMemory);
401+
#endif
402+
403+
private async Task TestWrite_LengthSpecified(WriteMethod writeMethod)
384404
{
385405
var inner = new MemoryStream(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
386406

@@ -391,16 +411,39 @@ public void TestWriteLengthSpecified()
391411
Assert.AreEqual(4, stream.Length);
392412
Assert.AreEqual(0, stream.Position);
393413

394-
stream.Write(new byte[] {0x02, 0x03}, 0, 2);
414+
switch (writeMethod) {
415+
case WriteMethod.WriteAsync: await stream.WriteAsync(new byte[] {0x02, 0x03}, 0, 2); break;
416+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
417+
case WriteMethod.WriteAsyncFromReadOnlyMemory: await stream.WriteAsync(new ReadOnlyMemory<byte>(new byte[] {0x02, 0x03})); break;
418+
#endif
419+
default: stream.Write(new byte[] {0x02, 0x03}, 0, 2); break;
420+
};
421+
422+
Assert.AreEqual(2, stream.Position);
423+
395424
stream.WriteByte(0x04);
396425

397426
Assert.AreEqual(3, stream.Position);
398427

399-
Assert.Throws<IOException>(() => stream.Write(new byte[] {0x05, 0x06}, 0, 2));
428+
Assert.ThrowsAsync<IOException>(async () => {
429+
switch (writeMethod) {
430+
case WriteMethod.WriteAsync: await stream.WriteAsync(new byte[] {0x05, 0x06}, 0, 2); break;
431+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
432+
case WriteMethod.WriteAsyncFromReadOnlyMemory: await stream.WriteAsync(new ReadOnlyMemory<byte>(new byte[] {0x05, 0x06})); break;
433+
#endif
434+
default: stream.Write(new byte[] {0x05, 0x06}, 0, 2); break;
435+
}
436+
});
400437

401438
Assert.AreEqual(3, stream.Position);
402439

403-
stream.Write(new byte[] {0x05}, 0, 1);
440+
switch (writeMethod) {
441+
case WriteMethod.WriteAsync: await stream.WriteAsync(new byte[] {0x05}, 0, 1); break;
442+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
443+
case WriteMethod.WriteAsyncFromReadOnlyMemory: await stream.WriteAsync(new ReadOnlyMemory<byte>(new byte[] {0x05})); break;
444+
#endif
445+
default: stream.Write(new byte[] {0x05}, 0, 1); break;
446+
};
404447

405448
Assert.AreEqual(4, stream.Position);
406449

@@ -412,8 +455,13 @@ public void TestWriteLengthSpecified()
412455
Assert.AreEqual(new byte[] {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00}, inner.ToArray());
413456
}
414457

415-
[Test]
416-
public void TestWriteLengthNotSpecified()
458+
[Test] public Task TestWrite_LengthNotSpecified() => TestWrite_LengthNotSpecified(WriteMethod.Write);
459+
[Test] public Task TestWriteAsync_LengthNotSpecified() => TestWrite_LengthNotSpecified(WriteMethod.WriteAsync);
460+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
461+
[Test] public Task TestWriteAsync_FromReadOnlyMemory_LengthNotSpecified() => TestWrite_LengthNotSpecified(WriteMethod.WriteAsyncFromReadOnlyMemory);
462+
#endif
463+
464+
private async Task TestWrite_LengthNotSpecified(WriteMethod writeMethod)
417465
{
418466
var inner = new MemoryStream(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
419467

@@ -424,17 +472,40 @@ public void TestWriteLengthNotSpecified()
424472
Assert.AreEqual(6, stream.Length);
425473
Assert.AreEqual(0, stream.Position);
426474

427-
stream.Write(new byte[] {0x02, 0x03, 0x04}, 0, 3);
475+
switch (writeMethod) {
476+
case WriteMethod.WriteAsync: await stream.WriteAsync(new byte[] {0x02, 0x03, 0x04}, 0, 3); break;
477+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
478+
case WriteMethod.WriteAsyncFromReadOnlyMemory: await stream.WriteAsync(new ReadOnlyMemory<byte>(new byte[] {0x02, 0x03, 0x04})); break;
479+
#endif
480+
default: stream.Write(new byte[] {0x02, 0x03, 0x04}, 0, 3); break;
481+
};
482+
483+
Assert.AreEqual(3, stream.Position);
484+
428485
stream.WriteByte(0x05);
429486

430487
Assert.AreEqual(4, stream.Position);
431488

432489
// cannot expand MemoryStream
433-
Assert.Throws<NotSupportedException>(() => stream.Write(new byte[] {0x06, 0x07, 0x08}, 0, 3));
490+
Assert.ThrowsAsync<NotSupportedException>(async () => {
491+
switch (writeMethod) {
492+
case WriteMethod.WriteAsync: await stream.WriteAsync(new byte[] {0x06, 0x07, 0x08}, 0, 3); break;
493+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
494+
case WriteMethod.WriteAsyncFromReadOnlyMemory: await stream.WriteAsync(new ReadOnlyMemory<byte>(new byte[] {0x06, 0x07, 0x08})); break;
495+
#endif
496+
default: stream.Write(new byte[] {0x06, 0x07, 0x08}, 0, 3); break;
497+
}
498+
});
434499

435500
Assert.AreEqual(4, stream.Position);
436501

437-
stream.Write(new byte[] {0x06, 0x07}, 0, 2);
502+
switch (writeMethod) {
503+
case WriteMethod.WriteAsync: await stream.WriteAsync(new byte[] {0x06, 0x07}, 0, 2); break;
504+
#if SYSTEM_IO_STREAM_WRITEASYNC_READONLYMEMORY_OF_BYTE
505+
case WriteMethod.WriteAsyncFromReadOnlyMemory: await stream.WriteAsync(new ReadOnlyMemory<byte>(new byte[] {0x06, 0x07})); break;
506+
#endif
507+
default: stream.Write(new byte[] {0x06, 0x07}, 0, 2); break;
508+
};
438509

439510
Assert.AreEqual(6, stream.Position);
440511

0 commit comments

Comments
 (0)