< Summary

Line coverage
100%
Covered lines: 178
Uncovered lines: 0
Coverable lines: 178
Total lines: 637
Line coverage: 100%
Branch coverage
100%
Covered branches: 66
Total branches: 66
Branch coverage: 100%
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 1: .ctor()100%11100%
File 1: .ctor(...)100%44100%
File 1: .ctor(...)100%88100%
File 1: .ctor(...)100%11100%
File 1: get_InnerArray()100%11100%
File 1: get_Count()100%11100%
File 1: get_Capacity()100%11100%
File 1: System.Collections.Generic.ICollection<T>.get_IsReadOnly()100%11100%
File 1: get_IsSynchronized()100%11100%
File 1: System.Collections.ICollection.get_SyncRoot()100%22100%
File 1: get_Item(...)100%11100%
File 1: set_Item(...)100%11100%
File 1: get_State()100%11100%
File 1: set_State(...)100%44100%
File 1: System.Collections.Generic.ICollection<T>.Add(...)100%11100%
File 1: Push(...)100%22100%
File 1: PushRange(...)100%44100%
File 1: System.Collections.Generic.ICollection<T>.Remove(...)100%11100%
File 1: Pop()100%22100%
File 1: Clear()100%44100%
File 1: Clear(...)100%44100%
File 1: FastClear()100%11100%
File 1: EnsureCapacity(...)100%22100%
File 1: Resize(...)100%44100%
File 1: TrimCapacity()100%44100%
File 1: Peek()100%11100%
File 1: ToString()100%22100%
File 1: AsSpan()100%11100%
File 1: AsReadOnlySpan()100%11100%
File 1: CopyTo(...)100%11100%
File 1: CopyTo(...)100%11100%
File 1: CopyTo(...)100%22100%
File 1: CloneTo(...)100%22100%
File 1: Contains(...)100%44100%
File 1: Exists(...)100%44100%
File 1: Find(...)100%44100%
File 1: GetEnumerator()100%11100%
File 1: System.Collections.Generic.IEnumerable<T>.GetEnumerator()100%11100%
File 1: 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()100%44100%
File 2: Reset()100%11100%
File 2: Dispose()100%11100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// SwiftStack.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using System.Collections;
 10using System.Collections.Generic;
 11using System.Runtime.CompilerServices;
 12using System.Text.Json.Serialization;
 13using Chronicler;
 14using Chronicler.Diagnostics;
 15using Chronicler.Serialization;
 16using MemoryPack;
 17using SwiftCollections.Utility;
 18
 19namespace SwiftCollections;
 20
 21/// <summary>
 22/// Represents a fast, array-based stack (LIFO - Last-In-First-Out) collection of objects.
 23/// <para>
 24/// The <c>SwiftStack&lt;T&gt;</c> class provides O(1) time complexity for <c>Push</c> and <c>Pop</c> operations,
 25/// making it highly efficient for scenarios where performance is critical.
 26/// It minimizes memory allocations by reusing internal arrays and offers methods
 27/// like <c>FastClear</c> to quickly reset the stack without deallocating memory.
 28/// </para>
 29/// <para>
 30/// This implementation is optimized for performance and does not perform versioning checks.
 31/// Modifying the stack during enumeration may result in undefined behavior.
 32/// </para>
 33/// </summary>
 34/// <typeparam name="T">Specifies the type of elements in the stack.</typeparam>
 35[Serializable]
 36[JsonConverter(typeof(StateJsonConverterFactory))]
 37[MemoryPackable]
 38public sealed partial class SwiftStack<T> : IStateBacked<SwiftArrayState<T>>, ISwiftCloneable<T>, IEnumerable<T>, IEnume
 39{
 40    #region Constants
 41
 42    /// <summary>
 43    /// The default initial capacity of the SwiftStack if none is specified.
 44    /// Used to allocate a reasonable starting size to minimize resizing operations.
 45    /// </summary>
 46    public const int DefaultCapacity = 8;
 47
 448    private static readonly T[] _emptyArray = Array.Empty<T>();
 449    private static readonly bool _clearReleasedSlots = RuntimeHelpers.IsReferenceOrContainsReferences<T>();
 50
 51    #endregion
 52
 53    #region Fields
 54
 55    /// <summary>
 56    /// The internal array that stores elements of the SwiftStack. Resized as needed to
 57    /// accommodate additional elements. Not directly exposed outside the stack.
 58    /// </summary>
 59    private T[] _innerArray;
 60
 61    /// <summary>
 62    /// The current number of elements in the SwiftStack. Represents the total count of
 63    /// valid elements stored in the stack, also indicating the arrayIndex of the next insertion point.
 64    /// </summary>
 65    private int _count;
 66
 67    [NonSerialized]
 68    private uint _version;
 69
 70    [NonSerialized]
 71    private object? _syncRoot;
 72
 73    #endregion
 74
 75    #region Constructors
 76
 77    /// <summary>
 78    /// Initializes a new, empty instance of SwiftStack.
 79    /// </summary>
 10280    public SwiftStack() : this(0) { }
 81
 82    /// <summary>
 83    /// Initializes a new, empty instance of SwiftStack with the specified initial capacity.
 84    /// </summary>
 6385    public SwiftStack(int capacity)
 86    {
 6387        if (capacity == 0)
 5188            _innerArray = _emptyArray;
 89        else
 90        {
 1291            capacity = capacity <= DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(capacity);
 1292            _innerArray = new T[capacity];
 93        }
 1294    }
 95
 96    /// <summary>
 97    /// Initializes a new instance of the <see cref="SwiftStack{T}"/> class that contains elements copied from the speci
 98    /// </summary>
 99    /// <remarks>
 100    /// The elements are copied onto the stack in the order they are returned by the enumerator of the collection,
 101    /// so that the last element in the collection becomes the top of the stack.
 102    /// </remarks>
 103    /// <param name="items">The collection whose elements are copied to the new stack. Cannot be null.</param>
 22104    public SwiftStack(IEnumerable<T> items)
 105    {
 22106        ChronicleGuard.ThrowIfNull(items, nameof(items));
 107
 22108        if (items is ICollection<T> collection)
 109        {
 21110            int count = collection.Count;
 21111            if (count == 0)
 7112                _innerArray = _emptyArray;
 113            else
 114            {
 14115                int capacity = SwiftHashTools.NextPowerOfTwo(count <= DefaultCapacity ? DefaultCapacity : count);
 14116                _innerArray = new T[capacity];
 14117                collection.CopyTo(_innerArray, 0);
 14118                _count = count;
 119            }
 120        }
 121        else
 122        {
 1123            _innerArray = new T[DefaultCapacity];
 8124            foreach (T item in items)
 3125                Push(item);
 126        }
 1127    }
 128
 129    ///  <summary>
 130    ///  Initializes a new instance of the <see cref="SwiftStack{T}"/> class with the specified <see cref="SwiftArraySta
 131    ///  </summary>
 132    ///  <param name="state">The state containing the internal array, count, offset, and version for initialization.</pa
 133    [MemoryPackConstructor]
 5134    public SwiftStack(SwiftArrayState<T> state)
 135    {
 5136        State = state;
 5137        ChronicleGuard.ThrowIfNull(_innerArray, nameof(_innerArray));
 5138    }
 139
 140    #endregion
 141
 142    #region Properties
 143
 144    /// <inheritdoc cref="_innerArray"/>
 145    [JsonIgnore]
 146    [MemoryPackIgnore]
 8147    public T[] InnerArray => _innerArray;
 148
 149    /// <inheritdoc cref="_count"/>
 150    [JsonIgnore]
 151    [MemoryPackIgnore]
 131152    public int Count => _count;
 153
 154    /// <summary>
 155    /// Gets the total number of elements the SwiftQueue can hold without resizing.
 156    /// Reflects the current allocated size of the internal array.
 157    /// </summary>
 158    [JsonIgnore]
 159    [MemoryPackIgnore]
 18160    public int Capacity => _innerArray.Length;
 161
 162    [JsonIgnore]
 163    [MemoryPackIgnore]
 1164    bool ICollection<T>.IsReadOnly => false;
 165
 166    /// <inheritdoc/>
 167    [JsonIgnore]
 168    [MemoryPackIgnore]
 1169    public bool IsSynchronized => false;
 170
 171    [JsonIgnore]
 172    [MemoryPackIgnore]
 3173    object ICollection.SyncRoot => _syncRoot ??= new object();
 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        {
 205185            ChronicleGuard.ThrowIfListIndexInvalid(index, _count);
 203186            return _innerArray[index];
 187        }
 188        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 189        set
 190        {
 2191            ChronicleGuard.ThrowIfListIndexInvalid(index, _count);
 1192            _innerArray[index] = value;
 1193        }
 194    }
 195
 196    /// <summary>
 197    /// Gets or sets the current state of the array, including its items and count.
 198    /// </summary>
 199    /// <remarks>
 200    /// Setting this property replaces the entire contents of the array with the items from the specified state.
 201    /// The setter is intended for internal use and may reset the array's version and capacity.
 202    /// </remarks>
 203    [JsonInclude]
 204    [MemoryPackInclude]
 205    public SwiftArrayState<T> State
 206    {
 207        get
 208        {
 2209            var items = new T[_count];
 2210            Array.Copy(_innerArray, 0, items, 0, _count);
 2211            return new SwiftArrayState<T>(items);
 212        }
 213        internal set
 214        {
 5215            ChronicleGuard.ThrowIfNull(value.Items, nameof(value.Items));
 216
 5217            int count = value.Items.Length;
 218
 5219            if (count == 0)
 220            {
 1221                _innerArray = _emptyArray;
 1222                _count = 0;
 1223                _version = 0;
 1224                return;
 225            }
 226
 4227            int capacity = SwiftHashTools.NextPowerOfTwo(count <= DefaultCapacity ? DefaultCapacity : count);
 228
 4229            _innerArray = new T[capacity];
 4230            Array.Copy(value.Items, 0, _innerArray, 0, count);
 231
 4232            _count = count;
 4233            _version = 0;
 4234        }
 235    }
 236
 237    #endregion
 238
 239    #region Collection Manipulation
 240
 241    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2242    void ICollection<T>.Add(T item) => Push(item);
 243
 244    /// <summary>
 245    /// Inserts an object at the top of the SwiftStack.
 246    /// </summary>
 247    /// <param name="item"></param>
 248    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 249    public void Push(T item)
 250    {
 450251        if ((uint)_count == (uint)_innerArray.Length)
 45252            Resize(_innerArray.Length * 2);
 450253        _innerArray[_count++] = item;
 450254        _version++;
 450255    }
 256
 257    /// <summary>
 258    /// Pushes the elements of the specified span onto the stack in order.
 259    /// </summary>
 260    /// <param name="items">The span whose elements should be pushed.</param>
 261    public void PushRange(ReadOnlySpan<T> items)
 262    {
 6263        if (items.Length == 0)
 1264            return;
 265
 5266        if (_count + items.Length > _innerArray.Length)
 267        {
 4268            int newCapacity = SwiftHashTools.NextPowerOfTwo(_count + items.Length);
 4269            Resize(newCapacity);
 270        }
 271
 5272        items.CopyTo(_innerArray.AsSpan(_count, items.Length));
 5273        _count += items.Length;
 5274        _version++;
 5275    }
 276
 277    bool ICollection<T>.Remove(T item)
 278    {
 1279        throw new NotSupportedException("Remove is not supported on Stack.");
 280    }
 281
 282    /// <summary>
 283    /// Removes and returns the object at the top of the SwiftStack.
 284    /// </summary>
 285    /// <returns></returns>
 286    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 287    public T Pop()
 288    {
 3289        ChronicleGuard.ThrowIfTrue((uint)_count == 0, message: "Stack is empty.");
 2290        T item = _innerArray[--_count];
 2291        if (_clearReleasedSlots)
 1292            _innerArray[_count] = default!;
 2293        _version++;
 2294        return item;
 295    }
 296
 297    /// <summary>
 298    /// Removes all elements from the SwiftStack, resetting its count to zero.
 299    /// </summary>
 300    public void Clear()
 301    {
 280302        if (_count == 0) return;
 12303        if (_clearReleasedSlots)
 7304            Array.Clear(_innerArray, 0, _count);
 12305        _count = 0;
 12306        _version++;
 12307    }
 308
 309    /// <summary>
 310    /// Removes all elements, optionally releasing references throughout retained backing storage.
 311    /// </summary>
 312    /// <param name="clearRetainedReferences">If true, also releases references outside the live range; otherwise uses o
 313    /// <remarks>Capacity is preserved. Full reference cleanup can take time proportional to retained capacity.</remarks
 314    public void Clear(bool clearRetainedReferences)
 315    {
 141316        if (clearRetainedReferences && _clearReleasedSlots)
 135317            Array.Clear(_innerArray, _count, _innerArray.Length - _count);
 141318        Clear();
 141319    }
 320
 321    /// <summary>
 322    /// Clears the SwiftStack without releasing the reference to the stored elements.
 323    /// Use FastClear() when you want to quickly reset the list without reallocating memory.
 324    /// </summary>
 325    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 326    public void FastClear()
 327    {
 134328        _count = 0;
 134329        _version++;
 134330    }
 331
 332    #endregion
 333
 334    #region Capacity Management
 335
 336    /// <summary>
 337    /// Ensures that the internal storage has at least the specified capacity, resizing if necessary.
 338    /// </summary>
 339    /// <remarks>
 340    /// If the current capacity is less than the specified value, the internal storage is increased to
 341    /// the next power of two greater than or equal to <paramref name="capacity"/>.
 342    /// No action is taken if the current capacity is sufficient.
 343    /// </remarks>
 344    /// <param name="capacity">The minimum number of elements that the internal storage should be able to hold. Must be 
 345    public void EnsureCapacity(int capacity)
 346    {
 2347        capacity = SwiftHashTools.NextPowerOfTwo(capacity);
 2348        if (capacity > _innerArray.Length)
 1349            Resize(capacity);
 2350    }
 351
 352    /// <summary>
 353    /// Ensures that the capacity of the stack is sufficient to accommodate the specified number of elements.
 354    /// The stack capacity can increase by double to balance memory allocation efficiency and space.
 355    /// </summary>
 356    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 357    private void Resize(int newSize)
 358    {
 50359        int newCapacity = newSize <= DefaultCapacity ? DefaultCapacity : newSize;
 50360        T[] newArray = new T[newCapacity];
 50361        if ((uint)_count > 0)
 8362            Array.Copy(_innerArray, 0, newArray, 0, _count);
 50363        _innerArray = newArray;
 50364        _version++;
 50365    }
 366
 367
 368    /// <summary>
 369    /// Sets the capacity of a <see cref="SwiftStack{T}"/> to the actual
 370    /// number of elements it contains, rounded up to a nearby next power of 2 value.
 371    /// </summary>
 372    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 373    public void TrimCapacity()
 374    {
 3375        int newCapacity = _count <= DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(_count);
 3376        T[] newArray = new T[newCapacity];
 3377        if ((uint)_count > 0)
 2378            Array.Copy(_innerArray, 0, newArray, 0, _count);
 3379        _innerArray = newArray;
 3380        _version++;
 3381    }
 382
 383    #endregion
 384
 385    #region Utility Methods
 386
 387    /// <summary>
 388    /// Returns the object at the top of the SwiftStack without removing it.
 389    /// </summary>
 390    /// <returns></returns>
 391    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 392    public T Peek()
 393    {
 7394        ChronicleGuard.ThrowIfTrue((uint)_count == 0, message: "Stack is empty.");
 6395        return _innerArray[_count - 1];
 396    }
 397
 398    /// <summary>
 399    /// Returns a string that represents the current stack, including its type and the number of elements it contains.
 400    /// </summary>
 401    /// <returns>
 402    /// A string containing the type name and the current element count if the stack is not empty;
 403    /// otherwise, a string indicating that the stack is empty.
 404    /// </returns>
 405    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2406    public override string ToString() => (uint)_count == 0 ? $"{typeof(SwiftStack<T>)}: Empty" : $"{typeof(SwiftStack<T>
 407
 408    /// <summary>
 409    /// Returns a mutable span over the populated portion of the stack.
 410    /// </summary>
 411    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2412    public Span<T> AsSpan() => _innerArray.AsSpan(0, _count);
 413
 414    /// <summary>
 415    /// Returns a read-only span over the populated portion of the stack.
 416    /// </summary>
 417    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 8418    public ReadOnlySpan<T> AsReadOnlySpan() => _innerArray.AsSpan(0, _count);
 419
 420    /// <summary>
 421    /// Copies the elements of the collection to the specified array, starting at the specified array index.
 422    /// </summary>
 423    /// <param name="array">
 424    /// The one-dimensional array that is the destination of the elements copied from the collection.
 425    /// The array must have zero-based indexing.</param>
 426    /// <param name="arrayIndex">The zero-based index in the destination array at which copying begins.</param>
 427    /// <exception cref="ArgumentOutOfRangeException">
 428    /// Thrown when <paramref name="arrayIndex"/> is less than 0 or greater than the length of <paramref name="array"/>.
 429    /// </exception>
 430    /// <exception cref="ArgumentException">
 431    /// Thrown when the number of elements in the source collection is greater than
 432    /// the available space from <paramref name="arrayIndex"/> to the end of <paramref name="array"/>.
 433    /// </exception>
 434    public void CopyTo(T[] array, int arrayIndex)
 435    {
 4436        ChronicleGuard.ThrowIfNull(array, nameof(array));
 3437        ChronicleGuard.ThrowIfArrayIndexInvalid(arrayIndex, array.Length);
 2438        ChronicleGuard.ThrowIfArgument((uint)(array.Length - arrayIndex) < (uint)_count, nameof(array), "Destination arr
 439
 1440        Array.Copy(_innerArray, 0, array, arrayIndex, _count);
 1441    }
 442
 443    /// <summary>
 444    /// Copies the populated elements of the SwiftStack into the specified destination span.
 445    /// </summary>
 446    /// <param name="destination">The destination span.</param>
 447    public void CopyTo(Span<T> destination)
 448    {
 2449        ChronicleGuard.ThrowIfArgument(destination.Length < _count, nameof(destination), "Destination span is not long e
 450
 1451        AsSpan().CopyTo(destination);
 1452    }
 453
 454    /// <inheritdoc/>
 455    public void CopyTo(Array array, int arrayIndex)
 456    {
 4457        ChronicleGuard.ThrowIfNull(array, nameof(array));
 4458        ChronicleGuard.ThrowIfArgument(array.Rank != 1, nameof(array), "Array must be single dimensional.");
 3459        ChronicleGuard.ThrowIfArgument(array.GetLowerBound(0) != 0, nameof(array), "Array must have zero-based indexing.
 2460        ChronicleGuard.ThrowIfArrayIndexInvalid(arrayIndex, array.Length);
 2461        ChronicleGuard.ThrowIfArgument((uint)(array.Length - arrayIndex) < (uint)_count, nameof(array), "Destination arr
 462
 463        try
 464        {
 10465            for (int i = 0; (uint)i < (uint)_count; i++)
 4466                array.SetValue(_innerArray[i], arrayIndex++);
 1467        }
 1468        catch (InvalidCastException)
 469        {
 1470            throw new ArgumentException("Invalid array type.");
 471        }
 1472    }
 473
 474    /// <inheritdoc/>
 475    public void CloneTo(ICollection<T> output)
 476    {
 1477        output.Clear();
 6478        for (int i = 0; (uint)i < (uint)_count; i++)
 2479            output.Add(_innerArray[i]);
 1480    }
 481
 482    /// <inheritdoc/>
 483    public bool Contains(T item)
 484    {
 2485        EqualityComparer<T> comparer = EqualityComparer<T>.Default;
 10486        for (int i = 0; i < _count; i++)
 487        {
 4488            if (comparer.Equals(_innerArray[i], item))
 1489                return true;
 490        }
 1491        return false;
 492    }
 493
 494    /// <summary>
 495    /// Determines whether the <see cref="SwiftStack{T}"/> contains an element that matches the conditions defined by th
 496    /// </summary>
 497    /// <param name="match">The predicate that defines the conditions of the element to search for.</param>
 498    /// <returns><c>true</c> if the <see cref="SwiftStack{T}"/> contains one or more elements that match the specified p
 499    public bool Exists(Predicate<T> match)
 500    {
 3501        ChronicleGuard.ThrowIfNull(match, nameof(match));
 502
 12503        for (int i = _count - 1; i >= 0; i--)
 504        {
 5505            if (match(_innerArray[i]))
 1506                return true;
 507        }
 508
 1509        return false;
 510    }
 511
 512    /// <summary>
 513    /// Searches for an element that matches the conditions defined by the specified predicate, and returns the first ma
 514    /// </summary>
 515    /// <param name="match">The predicate that defines the conditions of the element to search for.</param>
 516    /// <returns>The first element that matches the conditions defined by the specified predicate, if found; otherwise, 
 517    public T Find(Predicate<T> match)
 518    {
 2519        ChronicleGuard.ThrowIfNull(match, nameof(match));
 520
 8521        for (int i = _count - 1; i >= 0; i--)
 522        {
 3523            if (match(_innerArray[i]))
 1524                return _innerArray[i];
 525        }
 526
 1527        return default!;
 528    }
 529
 530    #endregion
 531
 532    #region Enumerators
 533
 534    /// <inheritdoc cref="IEnumerable.GetEnumerator()"/>
 58535    public SwiftStackEnumerator GetEnumerator() => new(this);
 29536    IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
 21537    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 538
 539
 540
 541    #endregion
 542}

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Collection/SwiftStack.SwiftStackEnumerator.cs

#LineLine coverage
 1//=======================================================================
 2// SwiftStack.SwiftStackEnumerator.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using System.Collections;
 10using System.Collections.Generic;
 11using System.Runtime.CompilerServices;
 12using Chronicler.Diagnostics;
 13
 14namespace SwiftCollections;
 15
 16public sealed partial class SwiftStack<T>
 17{
 18    /// <summary>
 19    /// Supports simple iteration over the elements of a <see cref="SwiftStack{T}"/> in last-in, first-out (LIFO) order.
 20    /// </summary>
 21    /// <remarks>
 22    /// The enumerator is invalidated if the collection is modified after the enumerator is created.
 23    /// This type is not thread-safe.
 24    /// </remarks>
 25    public struct SwiftStackEnumerator : IEnumerator<T>, IEnumerator, IDisposable
 26    {
 27        private readonly SwiftStack<T> _stack;
 28        private readonly T[] _array;
 29        private readonly uint _version;
 30        private readonly int _count;
 31        private int _index;
 32
 33        private T _current;
 34
 35        internal SwiftStackEnumerator(SwiftStack<T> stack)
 36        {
 5837            _stack = stack;
 5838            _array = stack._innerArray;
 5839            _count = stack._count;
 5840            _version = stack._version;
 5841            _index = -2; // Enumerator not started
 5842            _current = default!;
 5843        }
 44
 45        /// <inheritdoc/>
 45446        public T Current => _current;
 47
 48        object IEnumerator.Current
 49        {
 50            get
 51            {
 3252                ChronicleGuard.ThrowIfTrue((uint)_index > _count, message: "Bad enumeration");
 1353                return _current!;
 54            }
 55        }
 56
 57        /// <inheritdoc/>
 58        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 59        public bool MoveNext()
 60        {
 33461            ChronicleGuard.ThrowIfTrue(_version != _stack._version, message: "Enumerator modified outside of enumeration
 62
 33063            if (_index == -2)
 64            {
 6365                _index = _count - 1;
 66            }
 67            else
 68            {
 26769                _index--;
 70            }
 71
 33072            if (_index >= 0)
 73            {
 27674                _current = _array[_index];
 27675                return true;
 76            }
 77
 5478            _index = -1;
 5479            _current = default!;
 5480            return false;
 81        }
 82
 83        /// <inheritdoc/>
 84        public void Reset()
 85        {
 1386            ChronicleGuard.ThrowIfTrue(_version != _stack._version, message: "Enumerator modified outside of enumeration
 87
 988            _index = -2;
 989            _current = default!;
 990        }
 91
 92        /// <inheritdoc/>
 3493        public void Dispose() => _index = -1;
 94    }
 95}