-
-
Notifications
You must be signed in to change notification settings - Fork 200
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
aspnetcore response output using Streams again
pipelines needs to be done properly so it works from outside VS fixes #1070
- Loading branch information
1 parent
bcdc643
commit e599f28
Showing
3 changed files
with
116 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
src/Peachpie.AspNetCore.Web/ResponseOutput/DefaultTextWriter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
using System; | ||
using System.Buffers; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.IO.Pipelines; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Http; | ||
|
||
namespace Peachpie.AspNetCore.Web.ResponseOutput | ||
{ | ||
/// <summary> | ||
/// <see cref="TextWriter"/> implementation passing text to underlying response stream in given encoding. | ||
/// </summary> | ||
sealed class DefaultTextWriter : TextWriter | ||
{ | ||
HttpResponse HttpResponse { get; } | ||
|
||
public override Encoding Encoding { get; } | ||
|
||
/// <summary> | ||
/// Invariant number format provider. | ||
/// </summary> | ||
public override IFormatProvider FormatProvider => Pchp.Core.Context.InvariantNumberFormatInfo; | ||
|
||
public DefaultTextWriter(HttpResponse response, Encoding encoding) | ||
{ | ||
HttpResponse = response ?? throw new ArgumentNullException(nameof(response)); | ||
Encoding = encoding ?? throw new ArgumentNullException(nameof(encoding)); | ||
} | ||
|
||
const int UTF8MaxByteLength = 6; | ||
|
||
static int GetEncodingMaxByteSize(Encoding encoding) | ||
{ | ||
if (encoding == Encoding.UTF8) | ||
{ | ||
return UTF8MaxByteLength; | ||
} | ||
|
||
return encoding.GetMaxByteCount(1); | ||
} | ||
|
||
/// <summary> | ||
/// Writes a sequence of bytes into the underlying stream. | ||
/// </summary> | ||
public void Write(byte[] buffer, int count) | ||
{ | ||
Debug.Assert(buffer != null); | ||
Debug.Assert(count <= buffer.Length); | ||
|
||
HttpResponse.Body.WriteAsync(new ReadOnlyMemory<byte>(buffer, 0, count)).GetAwaiter().GetResult(); | ||
} | ||
|
||
public void Write(ReadOnlySpan<byte> buffer) | ||
{ | ||
var array = ArrayPool<byte>.Shared.Rent(buffer.Length); | ||
|
||
buffer.CopyTo(array); | ||
Write(array, buffer.Length); | ||
|
||
ArrayPool<byte>.Shared.Return(array); | ||
} | ||
|
||
public override void Write(string value) | ||
{ | ||
HttpResponse.WriteAsync(value, Encoding).GetAwaiter().GetResult(); | ||
} | ||
|
||
public override void Write(char[] chars, int index, int count) | ||
{ | ||
Debug.Assert(chars != null); | ||
Debug.Assert(index <= chars.Length && index >= 0); | ||
Debug.Assert(count >= 0 && count <= chars.Length - index); | ||
|
||
var encodedLength = Encoding.GetByteCount(chars, index, count); | ||
var bytes = ArrayPool<byte>.Shared.Rent(encodedLength); | ||
var nbytes = Encoding.GetBytes(chars, index, count, bytes, 0); // == encodedLength | ||
|
||
Write(bytes, nbytes); | ||
|
||
ArrayPool<byte>.Shared.Return(bytes); | ||
} | ||
|
||
|
||
public override void Write(char value) | ||
{ | ||
// encode the char on stack | ||
Span<byte> encodedCharBuffer = stackalloc byte[GetEncodingMaxByteSize(Encoding)]; | ||
Span<char> chars = stackalloc char[1] { value }; | ||
var nbytes = Encoding.GetBytes(chars, encodedCharBuffer); | ||
|
||
Write(encodedCharBuffer.Slice(0, nbytes)); // NOTE: _tmp is copied by the underlying pipe | ||
} | ||
|
||
public override void Flush() => FlushAsync().GetAwaiter().GetResult(); | ||
|
||
public override Task FlushAsync() => HttpResponse.Body.FlushAsync(CancellationToken.None); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters