@@ -94,6 +94,7 @@ public override int WriteTimeout
9494 }
9595
9696 /// <inheritdoc/>
97+ [ DebuggerBrowsable ( DebuggerBrowsableState . Never ) ]
9798 public override long Length
9899 {
99100 get
@@ -156,6 +157,7 @@ private void EnsureReadBufferIsEmpty()
156157 }
157158
158159 /// <inheritdoc/>
160+ [ DebuggerBrowsable ( DebuggerBrowsableState . Never ) ]
159161 Memory < byte > IBufferedWriter . Buffer
160162 {
161163 get
@@ -302,23 +304,29 @@ private void WriteCore(ReadOnlySpan<byte> data)
302304
303305 if ( writePosition is 0 )
304306 ClearReadBufferBeforeWrite ( ) ;
305-
307+
306308 var freeBuf = EnsureBufferAllocated ( ) . Span . Slice ( writePosition ) ;
307309
308- // drain buffered data if needed
309- if ( freeBuf . Length < data . Length )
310- WriteCore ( ) ;
311-
312- // if internal buffer has not enough space then just write through
313- if ( data . Length > freeBuf . Length )
310+ if ( data . Length <= freeBuf . Length )
314311 {
315- stream . Write ( data ) ;
316- Reset ( ) ;
312+ data . CopyTo ( freeBuf ) ;
313+ writePosition += data . Length ;
317314 }
318- else
315+ else if ( data . Length < maxBufferSize )
319316 {
317+ data . CopyTo ( freeBuf , out var bytesWritten ) ;
318+ stream . Write ( freeBuf = buffer . Span ) ;
319+ data = data . Slice ( bytesWritten ) ;
320320 data . CopyTo ( freeBuf ) ;
321- writePosition += data . Length ;
321+ writePosition = data . Length ;
322+
323+ Debug . Assert ( writePosition > 0 ) ;
324+ }
325+ else
326+ {
327+ WriteCore ( ) ;
328+ stream . Write ( data ) ;
329+ Reset ( ) ;
322330 }
323331 }
324332
@@ -360,35 +368,64 @@ public override ValueTask WriteAsync(ReadOnlyMemory<byte> data, CancellationToke
360368 return task ;
361369 }
362370
363- private async ValueTask WriteCoreAsync ( ReadOnlyMemory < byte > data , CancellationToken token )
371+ private ValueTask WriteCoreAsync ( ReadOnlyMemory < byte > data , CancellationToken token )
364372 {
365373 Debug . Assert ( stream is not null ) ;
366374
367375 if ( writePosition is 0 )
368376 ClearReadBufferBeforeWrite ( ) ;
369377
370- var freeBuf = EnsureBufferAllocated ( ) . Memory . Slice ( writePosition ) ;
371-
372- // drain buffered data if needed
373- if ( freeBuf . Length < data . Length )
378+ var freeCapacity = maxBufferSize - writePosition ;
379+
380+ ValueTask task ;
381+ if ( data . Length <= freeCapacity )
374382 {
375- await WriteCoreAsync ( out _ , token ) . ConfigureAwait ( false ) ;
376- freeBuf = buffer . Memory . Slice ( writePosition ) ;
383+ data . CopyTo ( EnsureBufferAllocated ( ) . Memory . Slice ( writePosition ) ) ;
384+ writePosition += data . Length ;
385+ task = ValueTask . CompletedTask ;
377386 }
378-
379- // if internal buffer has not enough space then just write through
380- if ( data . Length > freeBuf . Length )
387+ else if ( data . Length < maxBufferSize )
381388 {
382- await stream . WriteAsync ( data , token ) . ConfigureAwait ( false ) ;
383- Reset ( ) ;
389+ task = CopyAndWriteAsync ( data , token ) ;
390+ }
391+ else if ( writePosition is 0 )
392+ {
393+ task = stream . WriteAsync ( data , token ) ;
384394 }
385395 else
386396 {
387- data . CopyTo ( freeBuf ) ;
388- writePosition += data . Length ;
397+ task = WriteWithBufferAsync ( data , token ) ;
389398 }
399+
400+ return task ;
390401 }
391-
402+
403+ private async ValueTask CopyAndWriteAsync ( ReadOnlyMemory < byte > data , CancellationToken token )
404+ {
405+ Debug . Assert ( stream is not null ) ;
406+ Debug . Assert ( data . Length < maxBufferSize ) ;
407+
408+ var writeBuffer = buffer . Memory ;
409+ data . Span . CopyTo ( writeBuffer . Span . Slice ( writePosition ) , out var bytesWritten ) ;
410+ await stream . WriteAsync ( writeBuffer , token ) . ConfigureAwait ( false ) ;
411+ data = data . Slice ( bytesWritten ) ;
412+ data . CopyTo ( writeBuffer ) ;
413+ writePosition = data . Length ;
414+
415+ Debug . Assert ( writePosition > 0 ) ;
416+ }
417+
418+ private async ValueTask WriteWithBufferAsync ( ReadOnlyMemory < byte > data , CancellationToken token )
419+ {
420+ Debug . Assert ( stream is not null ) ;
421+ Debug . Assert ( data . Length >= maxBufferSize ) ;
422+ Debug . Assert ( writePosition > 0 ) ;
423+
424+ await stream . WriteAsync ( WrittenMemory , token ) . ConfigureAwait ( false ) ;
425+ await stream . WriteAsync ( data , token ) . ConfigureAwait ( false ) ;
426+ Reset ( ) ;
427+ }
428+
392429 /// <inheritdoc/>
393430 public override Task WriteAsync ( byte [ ] data , int offset , int count , CancellationToken token )
394431 => WriteAsync ( new ReadOnlyMemory < byte > ( data , offset , count ) , token ) . AsTask ( ) ;
@@ -454,12 +491,13 @@ private int ReadCore(Span<byte> data)
454491 {
455492 // nothing to do
456493 }
457- else if ( data . Length > MaxBufferSize )
494+ else if ( data . Length > maxBufferSize )
458495 {
459496 bytesRead += stream . Read ( data ) ;
460497 }
461498 else
462499 {
500+ readPosition = 0 ;
463501 readLength = stream . Read ( EnsureBufferAllocated ( ) . Span ) ;
464502 bytesRead += ReadFromBuffer ( data ) ;
465503 }
@@ -536,6 +574,7 @@ private async ValueTask<int> ReadCoreAsync(Memory<byte> data, CancellationToken
536574 else
537575 {
538576 Debug . Assert ( readPosition == readLength ) ;
577+ readPosition = 0 ;
539578 readLength = await stream . ReadAsync ( EnsureBufferAllocated ( ) . Memory , token ) . ConfigureAwait ( false ) ;
540579 bytesRead += ReadFromBuffer ( data . Span ) ;
541580 }
@@ -740,6 +779,7 @@ private void EnsureWriteBufferIsEmpty()
740779 }
741780
742781 /// <inheritdoc/>
782+ [ DebuggerBrowsable ( DebuggerBrowsableState . Never ) ]
743783 ReadOnlyMemory < byte > IBufferedReader . Buffer
744784 {
745785 get
0 commit comments