| File: Utility\StreamExtensions.cs | Web Access |
| Project: src\nuget-client\src\NuGet.Core\NuGet.Protocol\NuGet.Protocol.csproj (NuGet.Protocol) |
// 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.IO; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json.Linq; namespace NuGet.Protocol { public static class StreamExtensions { public static readonly int BufferSize = 8192; public static async Task CopyToAsync(this Stream stream, Stream destination, CancellationToken token) { await stream.CopyToAsync(destination, BufferSize, token); } internal static async Task<JObject?> AsJObjectAsync(this Stream? stream, CancellationToken token) { if (stream == null) { return null; } using (var reader = new StreamReader((await stream.AsSeekableStreamAsync(token))!)) { return JsonUtility.LoadJson(reader); } } /// <summary> /// Read a stream into a memory stream if CanSeek is false. /// This method is used to ensure that network streams /// can be read by non-async reads without blocking. /// /// Closes the original stream by default. /// </summary> internal static Task<Stream?> AsSeekableStreamAsync(this Stream? stream, CancellationToken token) { return AsSeekableStreamAsync(stream, leaveStreamOpen: false, token: token); } /// <summary> /// Read a stream into a memory stream if CanSeek is false. /// This method is used to ensure that network streams /// can be read by non-async reads without blocking. /// </summary> internal static async Task<Stream?> AsSeekableStreamAsync(this Stream? stream, bool leaveStreamOpen, CancellationToken token) { if (stream == null) { return null; } if (stream.CanSeek) { // Return the same stream if it can seek. // Network streams are not seekable. stream.Position = 0; return stream; } var memStream = new MemoryStream(); try { // Copy the the current stream to a memory stream. // This avoids the sync .Read call. await stream.CopyToAsync(memStream, token); memStream.Position = 0; } finally { if (!leaveStreamOpen) { stream.Dispose(); } } return memStream; } } }