private IProtonBuffer DoEnsureWritable()

in src/Proton/Buffer/ProtonCompositeBuffer.cs [473:557]


      private IProtonBuffer DoEnsureWritable(long amount, bool allowCompaction = true, long minimumGrowth = 1)
      {
         if (amount < 0)
         {
            throw new ArgumentOutOfRangeException(nameof(amount), "Growth amount must be greater than zero");
         }

         if (WritableBytes >= amount)
         {
            return this;
         }

         if (minimumGrowth < 0)
         {
            throw new ArgumentOutOfRangeException(nameof(minimumGrowth), "The minimum growth cannot be negative: " + minimumGrowth + '.');
         }

         if (allowCompaction && amount <= readOffset)
         {
            int compactableBuffers = 0;
            foreach (IProtonBuffer candidate in buffers)
            {
               if (candidate.Capacity != candidate.ReadOffset)
               {
                  break;
               }
               compactableBuffers++;
            }

            if (compactableBuffers > 0)
            {
               IProtonBuffer[] compactable;
               if (compactableBuffers < buffers.Length)
               {
                  compactable = new IProtonBuffer[compactableBuffers];
                  Array.ConstrainedCopy(buffers, 0, compactable, 0, compactable.Length);
                  Array.ConstrainedCopy(buffers, compactable.Length, buffers, 0, buffers.Length - compactable.Length);
                  Array.ConstrainedCopy(compactable, 0, buffers, buffers.Length - compactable.Length, compactable.Length);
               }
               else
               {
                  compactable = buffers;
               }

               foreach (IProtonBuffer target in compactable)
               {
                  target.Reset();
               }

               ComputeOffsetsAndIndexes();
               if (WritableBytes >= amount)
               {
                  return this;
               }
            }
            else if (buffers.Length == 1)
            {
               // If we only have a single component buffer, then we can safely compact that in-place.
               buffers[0].Compact();
               ComputeOffsetsAndIndexes();
               if (WritableBytes >= amount)
               {
                  return this;
               }
            }
         }

         long growth = Math.Max(amount - WritableBytes, minimumGrowth);

         if (growth < 0)
         {
            throw new ArgumentOutOfRangeException("Buffer size must not be negative, but was " + growth + '.');
         }

         if ((ulong)(growth + Capacity) > (ulong)maxCapacity)
         {
            throw new ArgumentOutOfRangeException(
                    "Buffer size cannot be made greater than " + maxCapacity +
                    ", but was requested to grow to" + (ulong)(growth + Capacity) + '.');
         }

         IProtonBuffer extension = allocator.Allocate(growth);
         AppendValidatedBuffer(extension);
         return this;
      }