File: src\libraries\Common\src\System\Text\Json\PooledByteBufferWriter.cs
Web Access
Project: src\src\libraries\Microsoft.Extensions.Logging.Console\src\Microsoft.Extensions.Logging.Console.csproj (Microsoft.Extensions.Logging.Console)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.IO;
using System.IO.Pipelines;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
 
namespace System.Text.Json
{
    internal sealed class PooledByteBufferWriter : PipeWriter, IDisposable
    {
        private const int MinimumBufferSize = 256;
 
        private ArrayBuffer _buffer;
        private readonly Stream? _stream;
 
        public PooledByteBufferWriter(int initialCapacity)
        {
            _buffer = new ArrayBuffer(initialCapacity, usePool: true);
        }
 
        public PooledByteBufferWriter(int initialCapacity, Stream stream) : this(initialCapacity)
        {
            _stream = stream;
        }
 
        public ReadOnlySpan<byte> WrittenSpan => _buffer.ActiveSpan;
 
        public ReadOnlyMemory<byte> WrittenMemory => _buffer.ActiveMemory;
 
        public int Capacity => _buffer.Capacity;
 
        public void Clear() => _buffer.Discard(_buffer.ActiveLength);
 
        public void ClearAndReturnBuffers() => _buffer.ClearAndReturnBuffer();
 
        public void Dispose() => _buffer.Dispose();
 
        public void InitializeEmptyInstance(int initialCapacity)
        {
            Debug.Assert(initialCapacity > 0);
            Debug.Assert(_buffer.ActiveLength == 0);
 
            _buffer.EnsureAvailableSpace(initialCapacity);
        }
 
        public static PooledByteBufferWriter CreateEmptyInstanceForCaching() => new PooledByteBufferWriter(initialCapacity: 0);
 
        public override void Advance(int count) => _buffer.Commit(count);
 
        public override Memory<byte> GetMemory(int sizeHint = MinimumBufferSize)
        {
            Debug.Assert(sizeHint > 0);
 
            _buffer.EnsureAvailableSpace(sizeHint);
            return _buffer.AvailableMemory;
        }
 
        public override Span<byte> GetSpan(int sizeHint = MinimumBufferSize)
        {
            Debug.Assert(sizeHint > 0);
 
            _buffer.EnsureAvailableSpace(sizeHint);
            return _buffer.AvailableSpan;
        }
 
#if NET
        internal void WriteToStream(Stream destination) => destination.Write(_buffer.ActiveSpan);
#else
        internal void WriteToStream(Stream destination) => destination.Write(_buffer.ActiveMemory);
#endif
 
        public override async ValueTask<FlushResult> FlushAsync(CancellationToken cancellationToken = default)
        {
            Debug.Assert(_stream is not null);
            await _stream.WriteAsync(WrittenMemory, cancellationToken).ConfigureAwait(false);
            Clear();
 
            return new FlushResult(isCanceled: false, isCompleted: false);
        }
 
        public override bool CanGetUnflushedBytes => true;
        public override long UnflushedBytes => _buffer.ActiveLength;
 
        // This type is used internally in JsonSerializer to help buffer and flush bytes to the underlying Stream.
        // It's only pretending to be a PipeWriter and doesn't need Complete or CancelPendingFlush for the internal usage.
        public override void CancelPendingFlush() => throw new NotImplementedException();
        public override void Complete(Exception? exception = null) => throw new NotImplementedException();
    }
}