diff --git a/sdk/core/Azure.Core/src/RequestContent.cs b/sdk/core/Azure.Core/src/RequestContent.cs index eaa669022d4c..5433bc0ba84d 100644 --- a/sdk/core/Azure.Core/src/RequestContent.cs +++ b/sdk/core/Azure.Core/src/RequestContent.cs @@ -67,7 +67,7 @@ public abstract class RequestContent : IDisposable /// The to use. /// An instance of that wraps a . /// The returned content represents the UTF-8 Encoding of the given string. - public static RequestContent Create(string content) => Create(s_UTF8NoBomEncoding.GetBytes(content)); + public static RequestContent Create(string content) => new CustomStringContent(content, s_UTF8NoBomEncoding); /// /// Creates an instance of that wraps a . @@ -221,13 +221,8 @@ public override void WriteTo(Stream stream, CancellationToken cancellationToken) public override bool TryComputeLength(out long length) { - if (_stream.CanSeek) - { - length = _stream.Length - _origin; - return true; - } - length = 0; - return false; + length = _stream.Length - _origin; + return true; } public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) @@ -261,7 +256,11 @@ public override void Dispose() { } public override void WriteTo(Stream stream, CancellationToken cancellation) { +#if NET6_0_OR_GREATER + stream.Write(_bytes.AsSpan(_contentStart, _contentLength)); +#else stream.Write(_bytes, _contentStart, _contentLength); +#endif } public override bool TryComputeLength(out long length) @@ -272,9 +271,11 @@ public override bool TryComputeLength(out long length) public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) { -#pragma warning disable CA1835 // WriteAsync(Memory<>) overload is not available in all targets +#if NET6_0_OR_GREATER + await stream.WriteAsync(_bytes.AsMemory(_contentStart, _contentLength), cancellation).ConfigureAwait(false); +#else await stream.WriteAsync(_bytes, _contentStart, _contentLength, cancellation).ConfigureAwait(false); -#pragma warning restore // WriteAsync(Memory<>) overload is not available in all targets +#endif } } @@ -289,8 +290,13 @@ public override void Dispose() { } public override void WriteTo(Stream stream, CancellationToken cancellation) { +#if NET6_0_OR_GREATER + stream.Write(_bytes.Span); +#else + byte[] buffer = _bytes.ToArray(); stream.Write(buffer, 0, buffer.Length); +#endif } public override bool TryComputeLength(out long length) @@ -316,8 +322,15 @@ public override void Dispose() { } public override void WriteTo(Stream stream, CancellationToken cancellation) { +#if NET6_0_OR_GREATER + foreach (var memory in _bytes) + { + stream.Write(memory.Span); + } +#else byte[] buffer = _bytes.ToArray(); stream.Write(buffer, 0, buffer.Length); +#endif } public override bool TryComputeLength(out long length) @@ -332,6 +345,56 @@ public override async Task WriteToAsync(Stream stream, CancellationToken cancell } } + private sealed class CustomStringContent : RequestContent + { + private readonly byte[] _buffer; + private readonly int _actualByteCount; + + public CustomStringContent(string value, Encoding? encoding = null) + { + encoding ??= Encoding.UTF8; +#if NET6_0_OR_GREATER + var byteCount = encoding.GetMaxByteCount(value.Length); + _buffer = ArrayPool.Shared.Rent(byteCount); + _actualByteCount = encoding.GetBytes(value, _buffer); +#else + _buffer = encoding.GetBytes(value); + _actualByteCount = _buffer.Length; +#endif + } + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) + { +#if NET6_0_OR_GREATER + await stream.WriteAsync(_buffer.AsMemory(0, _actualByteCount), cancellation).ConfigureAwait(false); +#else + await stream.WriteAsync(_buffer, 0, _actualByteCount, cancellation).ConfigureAwait(false); +#endif + } + + public override void WriteTo(Stream stream, CancellationToken cancellation) + { +#if NET6_0_OR_GREATER + stream.Write(_buffer.AsSpan(0, _actualByteCount)); +#else + stream.Write(_buffer, 0, _actualByteCount); +#endif + } + + public override bool TryComputeLength(out long length) + { + length = _actualByteCount; + return true; + } + + public override void Dispose() + { +#if NET6_0_OR_GREATER + ArrayPool.Shared.Return(_buffer, clearArray: true); +#endif + } + } + private sealed class DynamicDataContent : RequestContent { private readonly DynamicData _data; @@ -350,7 +413,7 @@ public override void WriteTo(Stream stream, CancellationToken cancellation) public override bool TryComputeLength(out long length) { - length = default; + length = 0; return false; } diff --git a/sdk/core/Azure.Core/src/Shared/StringRequestContent.cs b/sdk/core/Azure.Core/src/Shared/StringRequestContent.cs index 58a40c466612..aa95208d5038 100644 --- a/sdk/core/Azure.Core/src/Shared/StringRequestContent.cs +++ b/sdk/core/Azure.Core/src/Shared/StringRequestContent.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Buffers; using System.IO; using System.Text; using System.Threading; @@ -11,39 +12,50 @@ namespace Azure.Core { internal class StringRequestContent : RequestContent { - private readonly byte[] _bytes; + private readonly byte[] _buffer; + private readonly int _actualByteCount; public StringRequestContent(string value) { - _bytes = Encoding.UTF8.GetBytes(value); +#if NET6_0_OR_GREATER + var byteCount = Encoding.UTF8.GetMaxByteCount(value.Length); + _buffer = ArrayPool.Shared.Rent(byteCount); + _actualByteCount = Encoding.UTF8.GetBytes(value, _buffer); +#else + _buffer = Encoding.UTF8.GetBytes(value); + _actualByteCount = _buffer.Length; +#endif } public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) { #if NET6_0_OR_GREATER - await stream.WriteAsync(_bytes.AsMemory(), cancellation).ConfigureAwait(false); + await stream.WriteAsync(_buffer.AsMemory(0, _actualByteCount), cancellation).ConfigureAwait(false); #else - await stream.WriteAsync(_bytes, 0, _bytes.Length, cancellation).ConfigureAwait(false); + await stream.WriteAsync(_buffer, 0, _actualByteCount, cancellation).ConfigureAwait(false); #endif } public override void WriteTo(Stream stream, CancellationToken cancellation) { #if NET6_0_OR_GREATER - stream.Write(_bytes.AsSpan()); + stream.Write(_buffer.AsSpan(0, _actualByteCount)); #else - stream.Write(_bytes, 0, _bytes.Length); + stream.Write(_buffer, 0, _actualByteCount); #endif } public override bool TryComputeLength(out long length) { - length = _bytes.Length; + length = _actualByteCount; return true; } public override void Dispose() { +#if NET6_0_OR_GREATER + ArrayPool.Shared.Return(_buffer, clearArray: true); +#endif } } }