private static void PlainText(ref WritableBuffer outputBuffer) { var writer = new WritableBufferWriter(outputBuffer); // HTTP 1.1 OK writer.Write(_http11OK); // Server headers writer.Write(_headerServer); // Date header writer.Write(_dateHeaderValueManager.GetDateHeaderValues().Bytes); writer.Write(_crlf); // Content-Type header writer.Write(_headerContentTypeText); writer.Write(_crlf); // Content-Length header writer.Write(_headerContentLength); PipelineExtensions.WriteNumeric(ref writer, (ulong)_plainTextBody.Length); writer.Write(_crlf); // End of headers writer.Write(_crlf); // Body writer.Write(_plainTextBody); }
private static void Json(ref WritableBuffer outputBuffer) { var writer = new WritableBufferWriter(outputBuffer); // HTTP 1.1 OK writer.Write(_http11OK); // Server headers writer.Write(_headerServer); // Date header writer.Write(_dateHeaderValueManager.GetDateHeaderValues().Bytes); writer.Write(_crlf); // Content-Type header writer.Write(_headerContentTypeJson); writer.Write(_crlf); var jsonPayload = JsonSerializer.SerializeUnsafe(new { message = "Hello, World!" }); // Content-Length header writer.Write(_headerContentLength); PipelineExtensions.WriteNumeric(ref writer, (ulong)jsonPayload.Count); writer.Write(_crlf); // End of headers writer.Write(_crlf); // Body writer.Write(jsonPayload.Array, jsonPayload.Offset, jsonPayload.Count); }
public Task WriteAsync( ArraySegment <byte> buffer, CancellationToken cancellationToken) { var writableBuffer = default(WritableBuffer); lock (_contextLock) { if (_completed) { throw new ObjectDisposedException("Response is already completed"); } writableBuffer = _pipe.Writer.Alloc(1); // TODO obsolete #pragma warning disable CS0618 // Type or member is obsolete var writer = new WritableBufferWriter(writableBuffer); #pragma warning restore CS0618 // Type or member is obsolete if (buffer.Count > 0) { writer.Write(buffer.Array, buffer.Offset, buffer.Count); } writableBuffer.Commit(); } return(FlushAsync(writableBuffer, cancellationToken)); }
public static int WriteBeginChunkBytes(ref WritableBufferWriter start, int dataCount) { var chunkSegment = BeginChunkBytes(dataCount); start.Write(chunkSegment.Array, chunkSegment.Offset, chunkSegment.Count); return(chunkSegment.Count); }
private unsafe static void WriteAsciiMultiWrite(ref WritableBufferWriter buffer, string data) { var remaining = data.Length; fixed(char *input = data) { var inputSlice = input; while (remaining > 0) { var writable = Math.Min(remaining, buffer.Span.Length); if (writable == 0) { buffer.Ensure(); continue; } fixed(byte *output = &buffer.Span.DangerousGetPinnableReference()) { EncodeAsciiCharsToBytes(inputSlice, output, writable); } inputSlice += writable; remaining -= writable; buffer.Advance(writable); } } }
private Task WriteAsync( ArraySegment <byte> buffer, CancellationToken cancellationToken) { var writableBuffer = default(WritableBuffer); long bytesWritten = 0; lock (_contextLock) { if (_completed) { return(Task.CompletedTask); } writableBuffer = _pipeWriter.Alloc(1); var writer = new WritableBufferWriter(writableBuffer); if (buffer.Count > 0) { writer.Write(buffer.Array, buffer.Offset, buffer.Count); bytesWritten += buffer.Count; } writableBuffer.Commit(); } return(FlushAsync(writableBuffer, bytesWritten, cancellationToken)); }
public void ThrowsForInvalidParameters(int arrayLength, int offset, int length) { _buffer = _pipe.Writer.Alloc(1); var initialLength = _buffer.Buffer.Length; var writer = new WritableBufferWriter(_buffer); var array = new byte[arrayLength]; for (int i = 0; i < array.Length; i++) { array[i] = (byte)(i + 1); } writer.Write(array, 0, 0); writer.Write(array, array.Length, 0); try { writer.Write(array, offset, length); Assert.True(false); } catch (Exception ex) { Assert.True(ex is ArgumentOutOfRangeException); } writer.Write(array, 0, array.Length); Assert.Equal(array, Read()); }
public unsafe static void WriteAsciiNoValidation(ref WritableBufferWriter buffer, string data) { if (string.IsNullOrEmpty(data)) { return; } var dest = buffer.Span; var destLength = dest.Length; var sourceLength = data.Length; // Fast path, try copying to the available memory directly if (sourceLength <= destLength) { fixed(char *input = data) fixed(byte *output = &dest.DangerousGetPinnableReference()) { EncodeAsciiCharsToBytes(input, output, sourceLength); } buffer.Advance(sourceLength); } else { WriteAsciiMultiWrite(ref buffer, data); } }
private void Json(ref WritableBuffer outputBuffer) { var writer = new WritableBufferWriter(outputBuffer); // HTTP 1.1 OK writer.Write(_bytesHttpVersion11); writer.Write(ReasonPhrases.ToStatusBytes(200, reasonPhrase: null)); // Headers var values = _dateHeaderValueManager.GetDateHeaderValues(); ResponseHeaders.SetRawDate(values.String, values.Bytes); ResponseHeaders.SetRawServer("Custom", _headerServer); ResponseHeaders.HeaderContentType = "application/json"; var jsonPayload = JsonSerializer.SerializeUnsafe(new { message = "Hello, World!" }); ResponseHeaders.ContentLength = jsonPayload.Count; // Write headers ResponseHeaders.CopyTo(ref writer); writer.Write(_bytesEndHeaders); // Body writer.Write(jsonPayload.Array, jsonPayload.Offset, jsonPayload.Count); }
public void WriteHeader(AsciiString name, ulong value) { Output.Write(name); var output = new WritableBufferWriter(Output); PipelineExtensions.WriteNumeric(ref output, value); Output.Write(_crlf); }
public void ExposesSpan() { _buffer = _pipe.Writer.Alloc(1); var writer = new WritableBufferWriter(_buffer); Assert.Equal(_buffer.Buffer.Length, writer.Span.Length); Assert.Equal(new byte[] { }, Read()); }
public void CanWriteIntoHeadlessBuffer() { _buffer = _pipe.Writer.Alloc(); var writer = new WritableBufferWriter(_buffer); writer.Write(new byte[] { 1, 2, 3 }); Assert.Equal(new byte[] { 1, 2, 3 }, Read()); }
public void EnsureAllocatesSpan() { _buffer = _pipe.Writer.Alloc(); var writer = new WritableBufferWriter(_buffer); writer.Ensure(10); Assert.True(writer.Span.Length > 10); Assert.Equal(new byte[] {}, Read()); }
public void CanWriteEmpty() { _buffer = _pipe.Writer.Alloc(); var writer = new WritableBufferWriter(_buffer); var array = new byte[] { }; writer.Write(array); writer.Write(array, 0, array.Length); Assert.Equal(array, Read()); }
public void CanWriteMultipleTimes() { _buffer = _pipe.Writer.Alloc(); var writer = new WritableBufferWriter(_buffer); writer.Write(new byte[] { 1 }); writer.Write(new byte[] { 2 }); writer.Write(new byte[] { 3 }); Assert.Equal(new byte[] { 1, 2, 3 }, Read()); }
public void CanWriteWithOffsetAndLenght(int alloc, int offset, int length) { _buffer = _pipe.Writer.Alloc(alloc); var writer = new WritableBufferWriter(_buffer); var array = new byte[] { 1, 2, 3 }; writer.Write(array, offset, length); Assert.Equal(array.Skip(offset).Take(length).ToArray(), Read()); }
public void CanWriteOverTheBlockLength() { _buffer = _pipe.Writer.Alloc(1); var writer = new WritableBufferWriter(_buffer); var source = Enumerable.Range(0, _buffer.Buffer.Length).Select(i => (byte)i); var expectedBytes = source.Concat(source).Concat(source).ToArray(); writer.Write(expectedBytes); Assert.Equal(expectedBytes, Read()); }
public void SlicesSpanAndAdvancesAfterWrite() { _buffer = _pipe.Writer.Alloc(1); var initialLength = _buffer.Buffer.Length; var writer = new WritableBufferWriter(_buffer); writer.Write(new byte[] { 1, 2, 3 }); Assert.Equal(initialLength - 3, writer.Span.Length); Assert.Equal(_buffer.Buffer.Length, writer.Span.Length); Assert.Equal(new byte[] { 1, 2, 3 }, Read()); }
public void WriteAsciiNoValidationWritesOnlyOneBytePerChar(string input) { // WriteAscii doesn't validate if characters are in the ASCII range // but it shouldn't produce more than one byte per character var writerBuffer = _pipe.Writer.Alloc(); var writer = new WritableBufferWriter(writerBuffer); PipelineExtensions.WriteAsciiNoValidation(ref writer, input); writerBuffer.FlushAsync().GetAwaiter().GetResult(); var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult(); Assert.Equal(input.Length, reader.Buffer.Length); }
public unsafe static void WriteNumeric(ref WritableBufferWriter buffer, ulong number) { const byte AsciiDigitStart = (byte)'0'; var span = buffer.Span; var bytesLeftInBlock = span.Length; // Fast path, try copying to the available memory directly var simpleWrite = true; fixed(byte *output = &span.DangerousGetPinnableReference()) { var start = output; if (number < 10 && bytesLeftInBlock >= 1) { *(start) = (byte)(((uint)number) + AsciiDigitStart); buffer.Advance(1); } else if (number < 100 && bytesLeftInBlock >= 2) { var val = (uint)number; var tens = (byte)((val * 205u) >> 11); // div10, valid to 1028 *(start) = (byte)(tens + AsciiDigitStart); *(start + 1) = (byte)(val - (tens * 10) + AsciiDigitStart); buffer.Advance(2); } else if (number < 1000 && bytesLeftInBlock >= 3) { var val = (uint)number; var digit0 = (byte)((val * 41u) >> 12); // div100, valid to 1098 var digits01 = (byte)((val * 205u) >> 11); // div10, valid to 1028 *(start) = (byte)(digit0 + AsciiDigitStart); *(start + 1) = (byte)(digits01 - (digit0 * 10) + AsciiDigitStart); *(start + 2) = (byte)(val - (digits01 * 10) + AsciiDigitStart); buffer.Advance(3); } else { simpleWrite = false; } } if (!simpleWrite) { WriteNumericMultiWrite(ref buffer, number); } }
public void WritesNumericToAscii(ulong number) { var writerBuffer = _pipe.Writer.Alloc(); var writer = new WritableBufferWriter(writerBuffer); PipelineExtensions.WriteNumeric(ref writer, number); writerBuffer.FlushAsync().GetAwaiter().GetResult(); var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult(); var numAsStr = number.ToString(); var expected = Encoding.ASCII.GetBytes(numAsStr); AssertExtensions.Equal(expected, reader.Buffer.Slice(0, numAsStr.Length).ToArray()); }
private void Default(ref WritableBuffer outputBuffer) { var writer = new WritableBufferWriter(outputBuffer); // HTTP 1.1 OK writer.Write(_bytesHttpVersion11); writer.Write(ReasonPhrases.ToStatusBytes(200, reasonPhrase: null)); // Headers var values = _dateHeaderValueManager.GetDateHeaderValues(); ResponseHeaders.SetRawDate(values.String, values.Bytes); ResponseHeaders.SetRawServer("Custom", _headerServer); ResponseHeaders.ContentLength = 0; // Write headers ResponseHeaders.CopyTo(ref writer); writer.Write(_bytesEndHeaders); }
private static void WriteNumericMultiWrite(ref WritableBufferWriter buffer, ulong number) { const byte AsciiDigitStart = (byte)'0'; var value = number; var position = _maxULongByteLength; var byteBuffer = NumericBytesScratch; do { // Consider using Math.DivRem() if available var quotient = value / 10; byteBuffer[--position] = (byte)(AsciiDigitStart + (value - quotient * 10)); // 0x30 = '0' value = quotient; }while (value != 0); var length = _maxULongByteLength - position; buffer.Write(byteBuffer, position, length); }
public void WriteResponseHeaders(int statusCode, string reasonPhrase, HttpResponseHeaders responseHeaders) { lock (_contextLock) { if (_completed) { return; } var buffer = _pipeWriter.Alloc(1); var writer = new WritableBufferWriter(buffer); writer.Write(_bytesHttpVersion11); var statusBytes = ReasonPhrases.ToStatusBytes(statusCode, reasonPhrase); writer.Write(statusBytes); responseHeaders.CopyTo(ref writer); writer.Write(_bytesEndHeaders); buffer.Commit(); } }
public void WriteAsciiNoValidation() { const byte maxAscii = 0x7f; var writerBuffer = _pipe.Writer.Alloc(); var writer = new WritableBufferWriter(writerBuffer); for (var i = 0; i < maxAscii; i++) { PipelineExtensions.WriteAsciiNoValidation(ref writer, new string((char)i, 1)); } writerBuffer.FlushAsync().GetAwaiter().GetResult(); var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult(); var data = reader.Buffer.Slice(0, maxAscii).ToArray(); for (var i = 0; i < maxAscii; i++) { Assert.Equal(i, data[i]); } }
public void CopyTo(ref WritableBufferWriter output) { CopyToFast(ref output); if (MaybeUnknown != null) { foreach (var kv in MaybeUnknown) { foreach (var value in kv.Value) { if (value != null) { output.Write(_CrLf); PipelineExtensions.WriteAsciiNoValidation(ref output, kv.Key); output.Write(_colonSpace); PipelineExtensions.WriteAsciiNoValidation(ref output, value); } } } } }
public void EncodesAsAscii(string input, byte[] expected) { var writerBuffer = _pipe.Writer.Alloc(); var writer = new WritableBufferWriter(writerBuffer); PipelineExtensions.WriteAsciiNoValidation(ref writer, input); writerBuffer.FlushAsync().GetAwaiter().GetResult(); var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult(); if (expected.Length > 0) { AssertExtensions.Equal( expected, reader.Buffer.ToArray()); } else { Assert.Equal(0, reader.Buffer.Length); } }
private static void Default(ref WritableBuffer outputBuffer) { var writer = new WritableBufferWriter(outputBuffer); // HTTP 1.1 OK writer.Write(_http11OK); // Server headers writer.Write(_headerServer); // Date header writer.Write(_dateHeaderValueManager.GetDateHeaderValues().Bytes); writer.Write(_crlf); // Content-Length 0 writer.Write(_headerContentLengthZero); writer.Write(_crlf); // End of headers writer.Write(_crlf); }
public void WritesNumericAcrossSpanBoundaries(int gapSize) { var writerBuffer = _pipe.Writer.Alloc(100); var writer = new WritableBufferWriter(writerBuffer); // almost fill up the first block var spacer = new byte[writer.Span.Length - gapSize]; writer.Write(spacer); var bufferLength = writer.Span.Length; PipelineExtensions.WriteNumeric(ref writer, ulong.MaxValue); Assert.NotEqual(bufferLength, writer.Span.Length); writerBuffer.FlushAsync().GetAwaiter().GetResult(); var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult(); var numAsString = ulong.MaxValue.ToString(); var written = reader.Buffer.Slice(spacer.Length, numAsString.Length); Assert.False(written.IsSingleSpan, "The buffer should cross spans"); AssertExtensions.Equal(Encoding.ASCII.GetBytes(numAsString), written.ToArray()); }
private Task WriteAsync( ArraySegment <byte> buffer, CancellationToken cancellationToken, bool chunk = false) { var writableBuffer = default(WritableBuffer); lock (_contextLock) { if (_completed) { return(Task.CompletedTask); } writableBuffer = _pipe.Writer.Alloc(1); var writer = new WritableBufferWriter(writableBuffer); if (buffer.Count > 0) { if (chunk) { ChunkWriter.WriteBeginChunkBytes(ref writer, buffer.Count); } writer.Write(buffer.Array, buffer.Offset, buffer.Count); if (chunk) { ChunkWriter.WriteEndChunkBytes(ref writer); } } writableBuffer.Commit(); } return(FlushAsync(writableBuffer, cancellationToken)); }