internal static async Task <string> ReadLineAsync(this IAsyncEnumerator <byte> enumerator, CancellationToken cancellationToken) { // Validate parameters. if (enumerator == null) { throw new ArgumentNullException(nameof(enumerator)); } // The buffer. ArraySegment <byte> buffer = await enumerator.ReadLineBytesAsync(cancellationToken).ConfigureAwait(false); // Decode. return(Encoding.ASCII.GetString(buffer.Array, buffer.Offset, buffer.Count)); }
internal static async Task <HttpContent> ReadHttpContentFromChunkedTransferEncoding(this IAsyncEnumerator <byte> enumerator, HttpResponseMessage response, CancellationToken cancellationToken) { // Validate parameters. if (enumerator == null) { throw new ArgumentNullException(nameof(enumerator)); } if (response == null) { throw new ArgumentNullException(nameof(response)); } // The memory stream. var ms = new MemoryStream(); // Continue forever. while (true) { // Read the array buffer as a string. string chunkSize = await enumerator.ReadLineAsync(cancellationToken).ConfigureAwait(false); // Match. Match match = ChunkSizeRegex.Match(chunkSize); // Convert to a length. int length = int.Parse(match.GetGroupValue("chunkSize"), NumberStyles.HexNumber); // If 0, get out. if (length == 0 && !match.Groups["chunkExtension"].Success) { // Get out. break; } // While there are bytes to read. while (length-- > 0 && await enumerator.MoveNext(cancellationToken).ConfigureAwait(false)) { ms.WriteByte(enumerator.Current); } // Read the bytes. var line = await enumerator.ReadLineBytesAsync(cancellationToken).ConfigureAwait(false); // If not empty, throw. if (line.Count > 0) { throw new InvalidOperationException("An unexpected byte sequence was encountered after processing chunked encoding data."); } } // Set the header fields again. This is for extra headers that // may be passed down. await response.SetHeaderFieldsAsync(enumerator, cancellationToken).ConfigureAwait(false); // Reset the memory stream. ms.Seek(0, SeekOrigin.Begin); // Return the content. return(new StreamContent(ms)); }