// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.IO.Pipelines; using System.Text; using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure; namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http { public static class ChunkWriter { private static readonly ArraySegment _endChunkBytes = CreateAsciiByteArraySegment("\r\n"); private static readonly byte[] _hex = Encoding.ASCII.GetBytes("0123456789abcdef"); private static ArraySegment CreateAsciiByteArraySegment(string text) { var bytes = Encoding.ASCII.GetBytes(text); return new ArraySegment(bytes); } public static ArraySegment BeginChunkBytes(int dataCount) { var bytes = new byte[10] { _hex[((dataCount >> 0x1c) & 0x0f)], _hex[((dataCount >> 0x18) & 0x0f)], _hex[((dataCount >> 0x14) & 0x0f)], _hex[((dataCount >> 0x10) & 0x0f)], _hex[((dataCount >> 0x0c) & 0x0f)], _hex[((dataCount >> 0x08) & 0x0f)], _hex[((dataCount >> 0x04) & 0x0f)], _hex[((dataCount >> 0x00) & 0x0f)], (byte)'\r', (byte)'\n', }; // Determine the most-significant non-zero nibble int total, shift; total = (dataCount > 0xffff) ? 0x10 : 0x00; dataCount >>= total; shift = (dataCount > 0x00ff) ? 0x08 : 0x00; dataCount >>= shift; total |= shift; total |= (dataCount > 0x000f) ? 0x04 : 0x00; var offset = 7 - (total >> 2); return new ArraySegment(bytes, offset, 10 - offset); } public static int WriteBeginChunkBytes(ref WritableBuffer start, int dataCount) { var chunkSegment = BeginChunkBytes(dataCount); start.Write(chunkSegment); return chunkSegment.Count; } public static void WriteEndChunkBytes(ref WritableBuffer start) { start.Write(_endChunkBytes); } } }