< Summary

Class:Azure.Core.ArrayBufferWriter`1
Assembly:Azure.Messaging.ServiceBus
File(s):C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Shared\ArrayBufferWriter.cs
Covered lines:0
Uncovered lines:40
Coverable lines:40
Total lines:190
Line coverage:0% (0 of 40)
Covered branches:0
Total branches:14
Branch coverage:0% (0 of 14)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor()-0%100%
.ctor(...)-0%0%
get_WrittenMemory()-0%100%
get_WrittenSpan()-0%100%
get_WrittenCount()-0%100%
get_Capacity()-0%100%
get_FreeCapacity()-0%100%
Clear()-0%100%
Advance(...)-0%0%
GetMemory(...)-0%100%
GetSpan(...)-0%100%
CheckAndResizeBuffer(...)-0%0%
ThrowInvalidOperationException_AdvancedTooFar(...)-0%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Shared\ArrayBufferWriter.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Buffers;
 6using System.Diagnostics;
 7
 8namespace Azure.Core
 9{
 10    /// <summary>
 11    /// Represents a heap-based, array-backed output sink into which <typeparam name="T"/> data can be written.
 12    /// </summary>
 13    internal sealed class ArrayBufferWriter<T> : IBufferWriter<T>
 14    {
 15        private T[] _buffer;
 16        private const int DefaultInitialBufferSize = 256;
 17
 18        /// <summary>
 19        /// Creates an instance of an <see cref="ArrayBufferWriter{T}"/>, in which data can be written to,
 20        /// with the default initial capacity.
 21        /// </summary>
 022        public ArrayBufferWriter()
 23        {
 024            _buffer = Array.Empty<T>();
 025            WrittenCount = 0;
 026        }
 27
 28        /// <summary>
 29        /// Creates an instance of an <see cref="ArrayBufferWriter{T}"/>, in which data can be written to,
 30        /// with an initial capacity specified.
 31        /// </summary>
 32        /// <param name="initialCapacity">The minimum capacity with which to initialize the underlying buffer.</param>
 33        /// <exception cref="ArgumentException">
 34        /// Thrown when <paramref name="initialCapacity"/> is not positive (i.e. less than or equal to 0).
 35        /// </exception>
 036        public ArrayBufferWriter(int initialCapacity)
 37        {
 038            if (initialCapacity <= 0)
 39#pragma warning disable CA2208 // Instantiate argument exceptions correctly
 040                throw new ArgumentException(nameof(initialCapacity));
 41#pragma warning restore CA2208 // Instantiate argument exceptions correctly
 42
 043            _buffer = new T[initialCapacity];
 044            WrittenCount = 0;
 045        }
 46
 47        /// <summary>
 48        /// Returns the data written to the underlying buffer so far, as a <see cref="ReadOnlyMemory{T}"/>.
 49        /// </summary>
 050        public ReadOnlyMemory<T> WrittenMemory => _buffer.AsMemory(0, WrittenCount);
 51
 52        /// <summary>
 53        /// Returns the data written to the underlying buffer so far, as a <see cref="ReadOnlySpan{T}"/>.
 54        /// </summary>
 055        public ReadOnlySpan<T> WrittenSpan => _buffer.AsSpan(0, WrittenCount);
 56
 57        /// <summary>
 58        /// Returns the amount of data written to the underlying buffer so far.
 59        /// </summary>
 060        public int WrittenCount { get; private set; }
 61
 62        /// <summary>
 63        /// Returns the total amount of space within the underlying buffer.
 64        /// </summary>
 065        public int Capacity => _buffer.Length;
 66
 67        /// <summary>
 68        /// Returns the amount of space available that can still be written into without forcing the underlying buffer t
 69        /// </summary>
 070        public int FreeCapacity => _buffer.Length - WrittenCount;
 71
 72        /// <summary>
 73        /// Clears the data written to the underlying buffer.
 74        /// </summary>
 75        /// <remarks>
 76        /// You must clear the <see cref="ArrayBufferWriter{T}"/> before trying to re-use it.
 77        /// </remarks>
 78        public void Clear()
 79        {
 80            Debug.Assert(_buffer.Length >= WrittenCount);
 081            _buffer.AsSpan(0, WrittenCount).Clear();
 082            WrittenCount = 0;
 083        }
 84
 85        /// <summary>
 86        /// Notifies <see cref="IBufferWriter{T}"/> that <paramref name="count"/> amount of data was written to the outp
 87        /// </summary>
 88        /// <exception cref="ArgumentException">
 89        /// Thrown when <paramref name="count"/> is negative.
 90        /// </exception>
 91        /// <exception cref="InvalidOperationException">
 92        /// Thrown when attempting to advance past the end of the underlying buffer.
 93        /// </exception>
 94        /// <remarks>
 95        /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a prev
 96        /// </remarks>
 97        public void Advance(int count)
 98        {
 099            if (count < 0)
 100#pragma warning disable CA2208 // Instantiate argument exceptions correctly
 0101                throw new ArgumentException(nameof(count));
 102#pragma warning restore CA2208 // Instantiate argument exceptions correctly
 103
 0104            if (WrittenCount > _buffer.Length - count)
 0105                ThrowInvalidOperationException_AdvancedTooFar(_buffer.Length);
 106
 0107            WrittenCount += count;
 0108        }
 109
 110        /// <summary>
 111        /// Returns a <see cref="Memory{T}"/> to write to that is at least the requested length (specified by <paramref 
 112        /// If no <paramref name="sizeHint"/> is provided (or it's equal to <code>0</code>), some non-empty buffer is re
 113        /// </summary>
 114        /// <exception cref="ArgumentException">
 115        /// Thrown when <paramref name="sizeHint"/> is negative.
 116        /// </exception>
 117        /// <remarks>
 118        /// This will never return an empty <see cref="Memory{T}"/>.
 119        /// </remarks>
 120        /// <remarks>
 121        /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer.
 122        /// </remarks>
 123        /// <remarks>
 124        /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a prev
 125        /// </remarks>
 126        public Memory<T> GetMemory(int sizeHint = 0)
 127        {
 0128            CheckAndResizeBuffer(sizeHint);
 129            Debug.Assert(_buffer.Length > WrittenCount);
 0130            return _buffer.AsMemory(WrittenCount);
 131        }
 132
 133        /// <summary>
 134        /// Returns a <see cref="Span{T}"/> to write to that is at least the requested length (specified by <paramref na
 135        /// If no <paramref name="sizeHint"/> is provided (or it's equal to <code>0</code>), some non-empty buffer is re
 136        /// </summary>
 137        /// <exception cref="ArgumentException">
 138        /// Thrown when <paramref name="sizeHint"/> is negative.
 139        /// </exception>
 140        /// <remarks>
 141        /// This will never return an empty <see cref="Span{T}"/>.
 142        /// </remarks>
 143        /// <remarks>
 144        /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer.
 145        /// </remarks>
 146        /// <remarks>
 147        /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a prev
 148        /// </remarks>
 149        public Span<T> GetSpan(int sizeHint = 0)
 150        {
 0151            CheckAndResizeBuffer(sizeHint);
 152            Debug.Assert(_buffer.Length > WrittenCount);
 0153            return _buffer.AsSpan(WrittenCount);
 154        }
 155
 156        private void CheckAndResizeBuffer(int sizeHint)
 157        {
 0158            if (sizeHint < 0)
 159#pragma warning disable CA2208 // Instantiate argument exceptions correctly
 0160                throw new ArgumentException(nameof(sizeHint));
 161#pragma warning restore CA2208 // Instantiate argument exceptions correctly
 162
 0163            if (sizeHint == 0)
 164            {
 0165                sizeHint = 1;
 166            }
 167
 0168            if (sizeHint > FreeCapacity)
 169            {
 0170                int growBy = Math.Max(sizeHint, _buffer.Length);
 171
 0172                if (_buffer.Length == 0)
 173                {
 0174                    growBy = Math.Max(growBy, DefaultInitialBufferSize);
 175                }
 176
 0177                int newSize = checked(_buffer.Length + growBy);
 178
 0179                Array.Resize(ref _buffer, newSize);
 180            }
 181
 182            Debug.Assert(FreeCapacity > 0 && FreeCapacity >= sizeHint);
 0183        }
 184
 185        private static void ThrowInvalidOperationException_AdvancedTooFar(int capacity)
 186        {
 0187            throw new InvalidOperationException($"Advanced past capacity of {capacity}");
 188        }
 189    }
 190}