< Summary

Line coverage
99%
Covered lines: 265
Uncovered lines: 2
Coverable lines: 267
Total lines: 826
Line coverage: 99.2%
Branch coverage
90%
Covered branches: 85
Total branches: 94
Branch coverage: 90.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: .cctor()100%11100%
File 2: .cctor()100%11100%
File 2: .ctor()100%11100%
File 2: .ctor(...)100%44100%
File 2: .ctor(...)83.33%66100%
File 2: .ctor(...)100%11100%
File 2: get_InnerArray()100%11100%
File 2: get_Count()100%11100%
File 2: get_Capacity()100%11100%
File 2: get_IsSynchronized()100%11100%
File 2: get_SyncRoot()100%22100%
File 2: get_IsReadOnly()100%11100%
File 2: get_Item(...)100%11100%
File 2: set_Item(...)100%11100%
File 2: get_State()100%22100%
File 2: set_State(...)75%44100%
File 2: System.Collections.Generic.ICollection<T>.Add(...)100%11100%
File 2: Enqueue(...)100%22100%
File 2: EnqueueRange(...)75%4483.33%
File 2: EnqueueRange(...)100%11100%
File 2: EnqueueRange(...)75%4488.88%
File 2: Dequeue()100%22100%
File 2: TryDequeue(...)100%44100%
File 2: System.Collections.Generic.ICollection<T>.Remove(...)100%11100%
File 2: Peek()100%11100%
File 2: TryPeek(...)100%22100%
File 2: PeekTail()100%11100%
File 2: Contains(...)83.33%66100%
File 2: Exists(...)100%44100%
File 2: Find(...)100%44100%
File 2: Clear()100%66100%
File 2: FastClear()100%11100%
File 2: EnsureCapacity(...)100%22100%
File 2: Resize(...)100%66100%
File 2: TrimExcessCapacity()87.5%88100%
File 2: ToArray()75%44100%
File 2: GetSegments(...)100%44100%
File 2: CopyTo(...)100%22100%
File 2: CopyTo(...)50%22100%
File 2: CopyTo(...)100%22100%
File 2: CopyToInternal(...)100%22100%
File 2: CloneTo(...)100%22100%
File 2: GetEnumerator()100%11100%
File 2: System.Collections.Generic.IEnumerable<T>.GetEnumerator()100%11100%
File 2: System.Collections.IEnumerable.GetEnumerator()100%11100%
File 2: .ctor(...)100%11100%
File 2: get_Current()100%11100%
File 2: System.Collections.IEnumerator.get_Current()100%11100%
File 2: MoveNext()75%44100%
File 2: Reset()100%11100%
File 2: Dispose()100%11100%

File(s)

/_/src/SwiftCollections/obj/Release/net8.0/MemoryPack.Generator/MemoryPack.Generator.MemoryPackGenerator/SwiftCollections.SwiftQueue_T_.MemoryPackFormatter.g.cs

File '/_/src/SwiftCollections/obj/Release/net8.0/MemoryPack.Generator/MemoryPack.Generator.MemoryPackGenerator/SwiftCollections.SwiftQueue_T_.MemoryPackFormatter.g.cs' does not exist (any more).

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Collection/SwiftQueue.cs

#LineLine coverage
 1using Chronicler;
 2using MemoryPack;
 3using System;
 4using System.Collections;
 5using System.Collections.Generic;
 6using System.Runtime.CompilerServices;
 7using System.Text.Json.Serialization;
 8
 9namespace SwiftCollections;
 10
 11/// <summary>
 12/// <c>SwiftQueue&lt;T&gt;</c> is a high-performance, circular buffer-based queue designed for ultra-low-latency enqueue
 13/// <para>
 14/// It leverages power-of-two capacities and bitwise arithmetic to eliminate expensive modulo operations, enhancing perf
 15/// By managing memory efficiently with a wrap-around technique and custom capacity growth strategies, SwiftQueue minimi
 16/// Aggressive inlining and optimized exception handling further reduce overhead, making SwiftQueue outperform tradition
 17/// especially in scenarios with high-frequency additions and removals.
 18/// </para>
 19/// </summary>
 20/// <typeparam name="T">Specifies the type of elements in the queue.</typeparam>
 21[Serializable]
 22[JsonConverter(typeof(StateJsonConverterFactory))]
 23[MemoryPackable]
 24public sealed partial class SwiftQueue<T> : IStateBacked<SwiftArrayState<T>>, ISwiftCloneable<T>, IEnumerable<T>, IEnume
 25{
 26    #region Constants
 27
 28    /// <summary>
 29    /// The default initial capacity of the SwiftQueue if none is specified.
 30    /// Used to allocate a reasonable starting size to minimize resizing operations.
 31    /// </summary>
 32    public const int DefaultCapacity = 8;
 33
 234    private static readonly T[] _emptyArray = Array.Empty<T>();
 235    private static readonly bool _clearReleasedSlots = RuntimeHelpers.IsReferenceOrContainsReferences<T>();
 36
 37    #endregion
 38
 39    #region Fields
 40
 41    /// <summary>
 42    /// The internal array that stores elements of the SwiftQueue. Resized as needed to
 43    /// accommodate additional elements. Not directly exposed outside the queue.
 44    /// </summary>
 45    private T[] _innerArray;
 46
 47    /// <summary>
 48    /// The current number of elements in the SwiftQueue. Represents the total count of
 49    /// valid elements stored in the queue, also indicating the arrayIndex of the next insertion point.
 50    /// </summary>
 51    private int _count;
 52
 53    /// <summary>
 54    /// The arrayIndex of the first element in the queue. Adjusts as elements are dequeued.
 55    /// </summary>
 56    private int _head;
 57
 58    /// <summary>
 59    /// The arrayIndex at which the next element will be enqueued, wrapping around as needed.
 60    /// </summary>
 61    private int _tail;
 62
 63    /// <summary>
 64    /// A bitmask used for efficient modulo operations, derived from the capacity of the internal array.
 65    /// </summary>
 66    private int _mask;
 67
 68    /// <summary>
 69    /// A version number used to track modifications to the SwiftQueue to help detect changes during enumeration and ens
 70    /// </summary>
 71    [NonSerialized]
 72    private uint _version;
 73
 74    /// <summary>
 75    /// An object used to synchronize access to the SwiftQueue, ensuring thread safety.
 76    /// </summary>
 77    [NonSerialized]
 78    private object? _syncRoot;
 79
 80    #endregion
 81
 82    #region Constructors
 83
 84    /// <summary>
 85    /// Initializes a new, empty instance of SwiftQueue.
 86    /// </summary>
 7487    public SwiftQueue() : this(0) { }
 88
 89    /// <summary>
 90    /// Initializes a new, empty instance of SwiftQueue with the specified initial capacity.
 91    /// </summary>
 5792    public SwiftQueue(int capacity)
 93    {
 5794        if (capacity == 0)
 95        {
 3796            _innerArray = _emptyArray;
 3797            _mask = 0;
 98        }
 99        else
 100        {
 20101            capacity = capacity < DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(capacity);
 20102            _innerArray = new T[capacity];
 20103            _mask = _innerArray.Length - 1;
 104        }
 20105    }
 106
 107    /// <summary>
 108    /// Initializes a new instance of SwiftQueue that contains elements copied from the provided items.
 109    /// </summary>
 2110    public SwiftQueue(IEnumerable<T> items)
 111    {
 2112        SwiftThrowHelper.ThrowIfNull(items, nameof(items));
 2113        if (items is ICollection<T> collection)
 114        {
 1115            int capacity = collection.Count < DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(collecti
 1116            _innerArray = new T[capacity];
 117        }
 118        else
 1119            _innerArray = new T[DefaultCapacity];
 120
 2121        _mask = _innerArray.Length - 1;
 16122        foreach (T item in items)
 6123            Enqueue(item);
 2124    }
 125
 126    ///  <summary>
 127    ///  Initializes a new instance of the <see cref="SwiftQueue{T}"/> class with the specified <see cref="SwiftArraySta
 128    ///  </summary>
 129    ///  <param name="state">The state containing the internal array, count, offset, and version for initialization.</pa
 130    [MemoryPackConstructor]
 3131    public SwiftQueue(SwiftArrayState<T> state)
 132    {
 3133        State = state;
 134
 3135        SwiftThrowHelper.ThrowIfNull(_innerArray, nameof(_innerArray));
 3136    }
 137
 138    #endregion
 139
 140    #region Properties
 141
 142    /// <inheritdoc cref="_innerArray"/>
 143    [JsonIgnore]
 144    [MemoryPackIgnore]
 5145    public T[] InnerArray => _innerArray;
 146
 147    /// <inheritdoc cref="_count"/>
 148    [JsonIgnore]
 149    [MemoryPackIgnore]
 129150    public int Count => _count;
 151
 152    /// <summary>
 153    /// Gets the total number of elements the SwiftQueue can hold without resizing.
 154    /// Reflects the current allocated size of the internal array.
 155    /// </summary>
 156    [JsonIgnore]
 157    [MemoryPackIgnore]
 10158    public int Capacity => _innerArray.Length;
 159
 160    /// <inheritdoc/>
 161    [JsonIgnore]
 162    [MemoryPackIgnore]
 1163    public bool IsSynchronized => false;
 164
 165    /// <inheritdoc/>
 166    [JsonIgnore]
 167    [MemoryPackIgnore]
 1168    public object SyncRoot => _syncRoot ??= new object();
 169
 170    /// <inheritdoc/>
 171    [JsonIgnore]
 172    [MemoryPackIgnore]
 1173    public bool IsReadOnly => false;
 174
 175    /// <summary>
 176    /// Gets the element at the specified arrayIndex.
 177    /// </summary>
 178    [JsonIgnore]
 179    [MemoryPackIgnore]
 180    public T this[int index]
 181    {
 182        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 183        get
 184        {
 201185            SwiftThrowHelper.ThrowIfListIndexInvalid(index, _count, message: "Index is out of range.");
 200186            return _innerArray[(_head + index) & _mask];
 187        }
 188        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 189        set
 190        {
 2191            SwiftThrowHelper.ThrowIfListIndexInvalid(index, _count, message: "Index is out of range.");
 1192            _innerArray[(_head + index) & _mask] = value;
 1193        }
 194    }
 195
 196    /// <summary>
 197    /// Gets or sets the current state of the collection, including its items and order.
 198    /// </summary>
 199    /// <remarks>
 200    /// Setting this property replaces the entire contents of the collection with the items from the specified state.
 201    /// Getting this property returns a snapshot of the collection's current items and their order.
 202    /// This property is intended for serialization and deserialization scenarios.
 203    /// </remarks>
 204    [JsonInclude]
 205    [MemoryPackInclude]
 206    public SwiftArrayState<T> State
 207    {
 208        get
 209        {
 2210            var items = new T[_count];
 211
 404212            for (int i = 0; i < _count; i++)
 200213                items[i] = _innerArray[(_head + i) & _mask];
 214
 2215            return new SwiftArrayState<T>(items);
 216        }
 217        internal set
 218        {
 3219            SwiftThrowHelper.ThrowIfNull(value.Items, nameof(value.Items));
 220
 3221            int count = value.Items.Length;
 222
 3223            if (count == 0)
 224            {
 1225                _innerArray = _emptyArray;
 1226                _count = 0;
 1227                _head = 0;
 1228                _tail = 0;
 1229                _mask = 0;
 1230                _version = 0;
 1231                return;
 232            }
 233
 2234            int capacity = SwiftHashTools.NextPowerOfTwo(count <= DefaultCapacity ? DefaultCapacity : count);
 235
 2236            _innerArray = new T[capacity];
 2237            Array.Copy(value.Items, 0, _innerArray, 0, count);
 238
 2239            _count = count;
 2240            _head = 0;
 2241            _tail = count;
 2242            _mask = capacity - 1;
 243
 2244            _version = 0;
 2245        }
 246    }
 247
 248    #endregion
 249
 250    #region Collection Management
 251
 252    /// <inheritdoc/>
 1253    void ICollection<T>.Add(T item) => Enqueue(item);
 254
 255    /// <summary>
 256    /// Adds an item to the end of the queue. Automatically resizes the queue if the capacity is exceeded.
 257    /// </summary>
 258    /// <param name="item">The item to add to the queue.</param>
 259    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 260    public void Enqueue(T item)
 261    {
 320262        if ((uint)_count >= (uint)_innerArray.Length)
 33263            Resize(_innerArray.Length * 2);
 320264        _innerArray[_tail] = item;
 320265        _tail = (_tail + 1) & _mask;
 320266        _count++;
 320267        _version++;
 320268    }
 269
 270    /// <summary>
 271    /// Adds the elements of the specified collection to the end of the queue.
 272    /// </summary>
 273    /// <remarks>
 274    /// If the specified collection implements <see cref="ICollection{T}"/>, the queue's capacity is increased once to a
 275    /// improving performance for large collections.
 276    /// </remarks>
 277    /// <param name="items">The collection of elements to add to the queue. Cannot be null.</param>
 278    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 279    public void EnqueueRange(IEnumerable<T> items)
 280    {
 2281        SwiftThrowHelper.ThrowIfNull(items, nameof(items));
 282
 2283        if (items is ICollection<T> collection)
 0284            EnsureCapacity(_count + collection.Count);
 285
 16286        foreach (T item in items)
 6287            Enqueue(item);
 2288    }
 289
 290    /// <summary>
 291    /// Adds the elements of the specified array to the end of the queue in queue order.
 292    /// </summary>
 293    /// <param name="items">The array whose elements should be enqueued.</param>
 294    public void EnqueueRange(T[] items)
 295    {
 6296        SwiftThrowHelper.ThrowIfNull(items, nameof(items));
 6297        EnqueueRange(items.AsSpan());
 6298    }
 299
 300    /// <summary>
 301    /// Adds the elements of the specified span to the end of the queue in queue order.
 302    /// </summary>
 303    /// <param name="items">The span whose elements should be enqueued.</param>
 304    public void EnqueueRange(ReadOnlySpan<T> items)
 305    {
 29306        if (items.Length == 0)
 0307            return;
 308
 29309        EnsureCapacity(_count + items.Length);
 310
 316311        for (int i = 0; i < items.Length; i++)
 312        {
 129313            _innerArray[_tail] = items[i];
 129314            _tail = (_tail + 1) & _mask;
 315        }
 316
 29317        _count += items.Length;
 29318        _version++;
 29319    }
 320
 321    /// <summary>
 322    /// Removes and returns the item at the front of the queue.
 323    /// Throws an InvalidOperationException if the queue is empty.
 324    /// </summary>
 325    /// <returns>The item at the front of the queue.</returns>
 326    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 327    public T Dequeue()
 328    {
 83329        SwiftThrowHelper.ThrowIfTrue((uint)_count == 0, message: "Queue is Empty");
 82330        T item = _innerArray[_head];
 82331        if (_clearReleasedSlots)
 5332            _innerArray[_head] = default!;
 82333        _head = (_head + 1) & _mask;
 82334        _count--;
 82335        _version++;
 82336        return item;
 337    }
 338
 339    /// <summary>
 340    /// Tries to remove and return the item at the front of the queue.
 341    /// </summary>
 342    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 343    public bool TryDequeue(out T item)
 344    {
 3345        if ((uint)_count == 0)
 346        {
 1347            item = default!;
 1348            return false;
 349        }
 350
 2351        item = _innerArray[_head];
 2352        if (_clearReleasedSlots)
 1353            _innerArray[_head] = default!;
 2354        _head = (_head + 1) & _mask;
 2355        _count--;
 2356        _version++;
 2357        return true;
 358    }
 359
 1360    bool ICollection<T>.Remove(T item) => throw new NotSupportedException("Remove is not supported for SwiftQueue.");
 361
 362    /// <summary>
 363    /// Returns the item at the front of the queue without removing it.
 364    /// Throws an InvalidOperationException if the queue is empty.
 365    /// </summary>
 366    /// <returns>The item at the front of the queue.</returns>
 367    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 368    public T Peek()
 369    {
 5370        SwiftThrowHelper.ThrowIfTrue((uint)_count == 0, message: "Queue is Empty");
 3371        return _innerArray[_head];
 372    }
 373
 374    /// <summary>
 375    /// Tries to return the item at the front of the queue without removing it.
 376    /// </summary>
 377    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 378    public bool TryPeek(out T item)
 379    {
 2380        if ((uint)_count == 0)
 381        {
 1382            item = default!;
 1383            return false;
 384        }
 385
 1386        item = _innerArray[_head];
 1387        return true;
 388    }
 389
 390    /// <summary>
 391    /// Returns the item at the end of the queue without removing it.
 392    /// Throws an InvalidOperationException if the queue is empty.
 393    /// </summary>
 394    /// <returns>The item at the end of the queue.</returns>
 395    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 396    public T PeekTail()
 397    {
 4398        SwiftThrowHelper.ThrowIfTrue((uint)_count == 0, message: "Queue is Empty");
 3399        int tailIndex = (_tail - 1) & _mask;
 3400        return _innerArray[tailIndex];
 401    }
 402
 403    /// <inheritdoc/>
 404    public bool Contains(T item)
 405    {
 2406        if ((uint)_count == 0) return false;
 407
 2408        int index = _head;
 20409        for (int i = 0; i < _count; i++)
 410        {
 9411            if (Equals(_innerArray[index], item))
 1412                return true;
 413
 8414            index = (index + 1) & _mask;
 415        }
 416
 1417        return false;
 418    }
 419
 420    /// <summary>
 421    /// Determines whether the <see cref="SwiftQueue{T}"/> contains an element that matches the conditions defined by th
 422    /// </summary>
 423    /// <param name="match">The predicate that defines the conditions of the element to search for.</param>
 424    /// <returns><c>true</c> if the <see cref="SwiftQueue{T}"/> contains one or more elements that match the specified p
 425    public bool Exists(Predicate<T> match)
 426    {
 3427        SwiftThrowHelper.ThrowIfNull(match, nameof(match));
 428
 2429        int index = _head;
 20430        for (int i = 0; i < _count; i++)
 431        {
 9432            if (match(_innerArray[index]))
 1433                return true;
 434
 8435            index = (index + 1) & _mask;
 436        }
 437
 1438        return false;
 439    }
 440
 441    /// <summary>
 442    /// Searches for an element that matches the conditions defined by the specified predicate, and returns the first ma
 443    /// </summary>
 444    /// <param name="match">The predicate that defines the conditions of the element to search for.</param>
 445    /// <returns>The first element that matches the conditions defined by the specified predicate, if found; otherwise, 
 446    public T Find(Predicate<T> match)
 447    {
 2448        SwiftThrowHelper.ThrowIfNull(match, nameof(match));
 449
 2450        int index = _head;
 22451        for (int i = 0; i < _count; i++)
 452        {
 10453            T item = _innerArray[index];
 10454            if (match(item))
 1455                return item;
 456
 9457            index = (index + 1) & _mask;
 458        }
 459
 1460        return default!;
 461    }
 462
 463    /// <summary>
 464    /// Removes all elements from the SwiftQueue, resetting its count to zero.
 465    /// </summary>
 466    public void Clear()
 467    {
 8468        if (_count == 0) return;
 469
 4470        if (_clearReleasedSlots)
 471        {
 2472            if ((uint)_head < (uint)_tail)
 1473                Array.Clear(_innerArray, _head, _count);
 474            else
 475            {
 1476                Array.Clear(_innerArray, _head, _innerArray.Length - _head);
 1477                Array.Clear(_innerArray, 0, _tail);
 478            }
 479        }
 480
 4481        _count = 0;
 4482        _head = 0;
 4483        _tail = 0;
 4484        _version++;
 4485    }
 486
 487    /// <summary>
 488    /// Clears the SwiftQueue without releasing the reference to the stored elements.
 489    /// Use FastClear() when you want to quickly reset the list without reallocating memory.
 490    /// </summary>
 491    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 492    public void FastClear()
 493    {
 1494        _count = 0;
 1495        _tail = 0;
 1496        _head = 0;
 1497        _version++;
 1498    }
 499
 500    #endregion
 501
 502    #region Capacity Management
 503
 504    /// <summary>
 505    /// Ensures that the internal storage has at least the specified capacity, resizing if necessary.
 506    /// </summary>
 507    /// <remarks>
 508    /// If the specified capacity is not a power of two, it is rounded up to the next power of two to optimize internal 
 509    /// </remarks>
 510    /// <param name="capacity">The minimum number of elements that the internal storage should be able to hold. Must be 
 511    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 512    public void EnsureCapacity(int capacity)
 513    {
 31514        capacity = SwiftHashTools.NextPowerOfTwo(capacity);  // Capacity must be a power of 2 for proper masking
 31515        if (capacity > _innerArray.Length)
 7516            Resize(capacity);
 31517    }
 518
 519    /// <summary>
 520    /// Ensures that the capacity of the queue is sufficient to accommodate the specified number of elements.
 521    /// The capacity increases to the next power of two greater than or equal to the required minimum capacity.
 522    /// </summary>
 523    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 524    private void Resize(int newSize)
 525    {
 40526        var newArray = new T[newSize <= DefaultCapacity ? DefaultCapacity : newSize];
 40527        if ((uint)_count > 0)
 528        {
 529            // If we are not wrapped around...
 10530            if ((uint)_head < (uint)_tail)
 531            {
 532                // ...copy from head to tail into new array starting at arrayIndex 0
 1533                Array.Copy(_innerArray, _head, newArray, 0, _count);
 534            }
 535            // Else if we are wrapped around...
 536            else
 537            {
 538                // ...copy from head to end of old array to beginning of new array
 9539                Array.Copy(_innerArray, _head, newArray, 0, _innerArray.Length - _head);
 540                // ...copy from start of old array to tail into new array
 9541                Array.Copy(_innerArray, 0, newArray, _innerArray.Length - _head, _tail);
 542            }
 543        }
 544
 40545        _innerArray = newArray;
 40546        _mask = _innerArray.Length - 1;
 40547        _head = 0;
 40548        _tail = _count & _mask;
 40549        _version++;
 40550    }
 551
 552    /// <summary>
 553    /// Reduces the capacity of the SwiftQueue if the element count is significantly less than the current capacity.
 554    /// This method resizes the internal array to the next power of two greater than or equal to the current count,
 555    /// optimizing memory usage.
 556    /// </summary>
 557    public void TrimExcessCapacity()
 558    {
 4559        int newSize = _count < DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(_count);
 4560        if (newSize >= _innerArray.Length) return;
 561
 4562        var newArray = new T[newSize];
 563
 4564        if ((uint)_count != 0)
 565        {
 3566            if ((uint)_head < (uint)_tail)
 567            {
 568                // No wrap-around, simple copy
 2569                Array.Copy(_innerArray, _head, newArray, 0, _count);
 570            }
 571            else
 572            {
 573                // Wrap-around, copy in two parts
 1574                Array.Copy(_innerArray, _head, newArray, 0, _innerArray.Length - _head);
 1575                Array.Copy(_innerArray, 0, newArray, _innerArray.Length - _head, _tail);
 576            }
 577        }
 578
 4579        _innerArray = newArray;
 4580        _mask = _innerArray.Length - 1;
 4581        _head = 0;
 4582        _tail = _count & _mask;
 4583        _version++;
 4584    }
 585
 586    #endregion
 587
 588    #region Utility Methods
 589
 590    /// <summary>
 591    /// Copies the elements of the SwiftQueue to a new array.
 592    /// </summary>
 593    public T[] ToArray()
 594    {
 14595        var result = new T[_count];
 14596        if ((uint)_count == 0) return result;
 14597        if ((uint)_head < (uint)_tail)
 12598            Array.Copy(_innerArray, _head, result, 0, _count);
 599        else
 600        {
 2601            int firstPartLength = _innerArray.Length - _head;
 2602            Array.Copy(_innerArray, _head, result, 0, firstPartLength);
 2603            Array.Copy(_innerArray, 0, result, firstPartLength, _tail);
 604        }
 14605        return result;
 606    }
 607
 608    /// <summary>
 609    /// Returns the current queue contents as up to two read-only spans.
 610    /// </summary>
 611    /// <param name="first">The first contiguous queue segment.</param>
 612    /// <param name="second">The wrapped tail segment, if any.</param>
 613    public void GetSegments(out ReadOnlySpan<T> first, out ReadOnlySpan<T> second)
 614    {
 4615        if ((uint)_count == 0)
 616        {
 1617            first = ReadOnlySpan<T>.Empty;
 1618            second = ReadOnlySpan<T>.Empty;
 1619            return;
 620        }
 621
 3622        if ((uint)_head < (uint)_tail)
 623        {
 1624            first = _innerArray.AsSpan(_head, _count);
 1625            second = ReadOnlySpan<T>.Empty;
 1626            return;
 627        }
 628
 2629        int firstPartLength = _innerArray.Length - _head;
 2630        first = _innerArray.AsSpan(_head, firstPartLength);
 2631        second = _innerArray.AsSpan(0, _tail);
 2632    }
 633
 634    /// <inheritdoc/>
 635    public void CopyTo(Array array, int arrayIndex)
 636    {
 6637        SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 6638        SwiftThrowHelper.ThrowIfArgument((uint)array.Rank != 1, nameof(array), "Array must be single dimensional.");
 5639        SwiftThrowHelper.ThrowIfArgument((uint)array.GetLowerBound(0) != 0, nameof(array), "Array must have zero-based i
 4640        SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length, message: "Array index is out of range.");
 4641        SwiftThrowHelper.ThrowIfArgument((uint)(array.Length - arrayIndex) < _count, nameof(array), "Destination array i
 642
 4643        if ((uint)_count == 0)
 1644            return;
 645
 646        try
 647        {
 3648            CopyToInternal(array, arrayIndex);
 2649        }
 1650        catch (ArrayTypeMismatchException)
 651        {
 1652            throw new ArgumentException("Invalid array type.", nameof(array));
 653        }
 2654    }
 655
 656    /// <inheritdoc/>
 657    public void CopyTo(T[] array, int arrayIndex)
 658    {
 2659        SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 2660        SwiftThrowHelper.ThrowIfArgument((uint)array.Rank != 1, nameof(array), "Array must be single dimensional.");
 2661        SwiftThrowHelper.ThrowIfArgument((uint)array.GetLowerBound(0) != 0, nameof(array), "Array must have zero-based i
 2662        SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length, message: "Array index is out of range.");
 2663        SwiftThrowHelper.ThrowIfArgument((uint)(array.Length - arrayIndex) < _count, nameof(array), "Destination array i
 664
 1665        if ((uint)_count == 0) return;
 666
 1667        CopyToInternal(array, arrayIndex);
 1668    }
 669
 670    /// <summary>
 671    /// Copies the elements of the SwiftQueue into the specified destination span.
 672    /// </summary>
 673    /// <param name="destination">The destination span.</param>
 674    public void CopyTo(Span<T> destination)
 675    {
 2676        SwiftThrowHelper.ThrowIfArgument((uint)destination.Length < _count, nameof(destination), "Destination span is no
 677
 1678        GetSegments(out ReadOnlySpan<T> first, out ReadOnlySpan<T> second);
 1679        first.CopyTo(destination);
 680
 1681        if (second.Length > 0)
 1682            second.CopyTo(destination[first.Length..]);
 1683    }
 684
 685    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 686    private void CopyToInternal(Array destination, int arrayIndex)
 687    {
 4688        if ((uint)_head < (uint)_tail)
 689        {
 2690            Array.Copy(_innerArray, _head, destination, arrayIndex, _count);
 691        }
 692        else
 693        {
 2694            int firstPartLength = _innerArray.Length - _head;
 2695            Array.Copy(_innerArray, _head, destination, arrayIndex, firstPartLength);
 2696            Array.Copy(_innerArray, 0, destination, arrayIndex + firstPartLength, _tail);
 697        }
 2698    }
 699
 700    /// <inheritdoc/>
 701    public void CloneTo(ICollection<T> output)
 702    {
 1703        SwiftThrowHelper.ThrowIfNull(output, nameof(output));
 1704        output.Clear();
 12705        foreach (var item in this)
 5706            output.Add(item);
 1707    }
 708
 709    #endregion
 710
 711    #region Enumerators
 712
 713    /// <summary>
 714    /// Returns an enumerator that iterates through the SwiftList.
 715    /// </summary>
 13716    public SwiftQueueEnumerator GetEnumerator() => new(this);
 8717    IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
 2718    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 719
 720    /// <summary>
 721    /// Enumerates the elements of a <see cref="SwiftQueue{T}"/> in the order they would be dequeued.
 722    /// </summary>
 723    public struct SwiftQueueEnumerator : IEnumerator<T>, IEnumerator, IDisposable
 724    {
 725        private readonly SwiftQueue<T> _queue;
 726        private readonly T[] _array;
 727        private readonly uint _version;
 728        private uint _index;
 729        private uint _currentIndex;
 730
 731        private T _current;
 732
 733        internal SwiftQueueEnumerator(SwiftQueue<T> queue)
 734        {
 13735            _queue = queue;
 13736            _array = queue._innerArray;
 13737            _version = queue._version;
 13738            _index = 0;
 13739            _currentIndex = (uint)queue._head - 1;
 13740            _current = default!;
 13741        }
 742
 743        /// <inheritdoc/>
 413744        public readonly T Current => _current;
 745
 746        readonly object IEnumerator.Current
 747        {
 748            [MethodImpl(MethodImplOptions.AggressiveInlining)]
 749            get
 750            {
 3751                SwiftThrowHelper.ThrowIfTrue(_index >= (uint)_queue._count, message: "Bad enumeration");
 2752                return _current!;
 753            }
 754        }
 755
 756        /// <inheritdoc/>
 757        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 758        public bool MoveNext()
 759        {
 229760            SwiftThrowHelper.ThrowIfTrue(_version != _queue._version, message: "Collection was modified during enumerati
 761
 229762            _index++;
 240763            if (_index > (uint)_queue._count) return false;
 218764            _currentIndex++;
 218765            if (_currentIndex == _array.Length) _currentIndex = 0;
 218766            _current = _array[_currentIndex];
 218767            return true;
 768        }
 769
 770        /// <inheritdoc/>
 771        public void Reset()
 772        {
 2773            SwiftThrowHelper.ThrowIfTrue(_version != _queue._version, message: "Collection was modified during enumerati
 774
 2775            _index = 0;
 2776            _currentIndex = (uint)_queue._head - 1;
 2777            _current = default!;
 2778        }
 779
 780        /// <inheritdoc/>
 10781        public void Dispose() => _index = 0;
 782    }
 783
 784    #endregion
 785}