< Summary

Information
Class: SwiftCollections.Dimensions.SwiftArray2D<T>
Assembly: SwiftCollections
File(s): /home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Dimension/SwiftArray2D.cs
Line coverage
100%
Covered lines: 130
Uncovered lines: 0
Coverable lines: 130
Total lines: 329
Line coverage: 100%
Branch coverage
100%
Covered branches: 64
Total branches: 64
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
.ctor(...)100%11100%
.ctor(...)100%11100%
.ctor(...)100%44100%
.ctor(...)100%11100%
get_Width()100%11100%
get_Height()100%11100%
get_InnerArray()100%11100%
get_Size()100%11100%
get_Length()100%11100%
get_Item(...)100%11100%
set_Item(...)100%11100%
get_State()100%11100%
set_State(...)100%11100%
AddRange(...)100%44100%
Fill(...)100%22100%
Shift(...)100%2020100%
Clear()100%11100%
Resize(...)100%88100%
Initialize(...)100%11100%
ValidateIndex(...)100%88100%
IsValidIndex(...)100%66100%
GetIndex(...)100%11100%
ToArray()100%44100%
Clone()100%44100%
GetEnumerator()100%44100%
System.Collections.IEnumerable.GetEnumerator()100%11100%

File(s)

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Dimension/SwiftArray2D.cs

#LineLine coverage
 1using MemoryPack;
 2using System;
 3using System.Collections;
 4using System.Collections.Generic;
 5using System.Text.Json.Serialization;
 6
 7namespace SwiftCollections.Dimensions;
 8
 9/// <summary>
 10/// Represents a flattened 2D array with dynamic resizing and efficient access.
 11/// </summary>
 12/// <typeparam name="T">The type of elements in the array.</typeparam>
 13[Serializable]
 14[JsonConverter(typeof(SwiftStateJsonConverterFactory))]
 15[MemoryPackable]
 16public partial class SwiftArray2D<T> : IEnumerable<T>, IEnumerable
 17{
 18    #region Fields
 19
 20    private T[] _innerArray;
 21
 22    private int _width;
 23
 24    private int _height;
 25
 26    #endregion
 27
 28    #region Constructors
 29
 30    /// <summary>
 31    /// Initializes a new instance of the <see cref="SwiftArray2D{T}"/> class.
 32    /// </summary>
 333    public SwiftArray2D() : this(0, 0) { }
 34
 35    /// <summary>
 36    /// Initializes a new instance of the <see cref="SwiftArray2D{T}"/> class with specified dimensions.
 37    /// </summary>
 3238    public SwiftArray2D(int width, int height)
 3239    {
 3240        Initialize(width, height);
 3241    }
 42
 43    /// <summary>
 44    /// Initializes a new instance of the <see cref="SwiftArray2D{T}"/> class with specified dimensions and default valu
 45    /// </summary>
 1246    public SwiftArray2D(int width, int height, T defaultValue) : this(width, height)
 1247    {
 1248        Fill(defaultValue);
 1249    }
 50
 251    public SwiftArray2D(T[,] source)
 252    {
 253        int width = source.GetLength(0);
 254        int height = source.GetLength(1);
 55
 256        Initialize(width, height);
 57
 1258        for (int x = 0; x < width; x++)
 2459            for (int y = 0; y < height; y++)
 860                this[x, y] = source[x, y];
 261    }
 62
 63    [MemoryPackConstructor]
 664    public SwiftArray2D(Array2DState<T> state)
 665    {
 666        State = state;
 667    }
 68
 69    #endregion
 70
 71    #region Properties
 72
 73    /// <summary>
 74    /// Gets the width of the 2D array.
 75    /// </summary>
 76    [JsonIgnore]
 77    [MemoryPackIgnore]
 7278    public int Width => _width;
 79
 80    /// <summary>
 81    /// Gets the height of the 2D array.
 82    /// </summary>
 83    [JsonIgnore]
 84    [MemoryPackIgnore]
 8785    public int Height => _height;
 86
 87    /// <summary>
 88    /// Gets the underlying flattened array for direct access.
 89    /// </summary>
 90    [JsonIgnore]
 91    [MemoryPackIgnore]
 11392    public T[] InnerArray => _innerArray;
 93
 94    /// <summary>
 95    /// Total size of the array
 96    /// </summary>
 97    [JsonIgnore]
 98    [MemoryPackIgnore]
 199    public int Size => _width * _height;
 100
 101    /// <inheritdoc cref="Array.Length" />
 102    [JsonIgnore]
 103    [MemoryPackIgnore]
 7104    public int Length => _innerArray.Length;
 105
 106    /// <summary>
 107    /// Gets or sets the element at the specified position in the 2D array.
 108    /// </summary>
 109    /// <param name="x">The zero-based X coordinate.</param>
 110    /// <param name="y">The zero-based Y coordinate.</param>
 111    [JsonIgnore]
 112    [MemoryPackIgnore]
 113    public T this[int x, int y]
 114    {
 115        get
 1000229116        {
 1000229117            ValidateIndex(x, y);
 1000227118            return _innerArray[GetIndex(x, y)];
 1000227119        }
 120        set
 1000080121        {
 1000080122            ValidateIndex(x, y);
 1000080123            _innerArray[GetIndex(x, y)] = value;
 1000080124        }
 125    }
 126
 127    [JsonInclude]
 128    [MemoryPackInclude]
 129    public Array2DState<T> State
 130    {
 131        get
 6132        {
 6133            var data = new T[_innerArray.Length];
 6134            Array.Copy(_innerArray, data, data.Length);
 135
 6136            return new Array2DState<T>(
 6137                _width,
 6138                _height,
 6139                data
 6140            );
 6141        }
 142
 143        internal set
 6144        {
 6145            _width = value.Width;
 6146            _height = value.Height;
 147
 6148            _innerArray = new T[value.Data.Length];
 6149            Array.Copy(value.Data, _innerArray, value.Data.Length);
 6150        }
 151    }
 152
 153    #endregion
 154
 155    #region Collection Management
 156
 157    /// <summary>
 158    /// Adds the provides source into the current 2D Array.
 159    /// </summary>
 160    /// <remarks>
 161    /// Will overwrite current values.
 162    /// </remarks>
 163    /// <param name="source"></param>
 164    public void AddRange(T[,] source)
 1165    {
 1166        Resize(source.GetLength(0), source.GetLength(1));
 6167        for (int i = 0; i < Width; i++)
 2168        {
 12169            for (int j = 0; j < Height; j++)
 4170                this[i, j] = source[i, j];
 2171        }
 1172    }
 173
 174    /// <summary>
 175    /// Fills the array with the specified value.
 176    /// </summary>
 177    public void Fill(T value)
 15178    {
 4000304179        for (int i = 0; i < _innerArray.Length; i++)
 2000137180            _innerArray[i] = value;
 15181    }
 182
 183    /// <summary>
 184    /// Shifts the elements in the array by the specified X and Y offsets.
 185    /// </summary>
 186    /// <param name="xShift">The offset to apply along the X-axis.</param>
 187    /// <param name="yShift">The offset to apply along the Y-axis.</param>
 188    /// <param name="wrap">
 189    /// Specifies whether to wrap elements that exceed the array's boundaries.
 190    /// If <c>true</c>, values wrap around to the other side of the array.
 191    /// If <c>false</c>, values that exceed boundaries are discarded.
 192    /// </param>
 193    public void Shift(int xShift, int yShift, bool wrap = true)
 5194    {
 5195        T[] newArray = new T[_innerArray.Length];
 196
 44197        for (int x = 0; x < _width; x++)
 17198        {
 17199            int newX = wrap ? (x + xShift + _width) % _width : x + xShift;
 21200            if (!wrap && (newX < 0 || newX >= _width)) continue;
 201
 124202            for (int y = 0; y < _height; y++)
 49203            {
 49204                int newY = wrap ? (y + yShift + _height) % _height : y + yShift;
 51205                if (!wrap && (newY < 0 || newY >= _height)) continue;
 206
 47207                newArray[newX * _height + newY] = this[x, y];
 47208            }
 13209        }
 210
 5211        _innerArray = newArray;
 5212    }
 213
 214    /// <summary>
 215    /// Clears all elements in the array.
 216    /// </summary>
 1217    public void Clear() => Array.Clear(_innerArray, 0, _innerArray.Length);
 218
 219    #endregion
 220
 221    #region Capacity Management
 222
 223    /// <summary>
 224    /// Resizes the 2D array to new dimensions, preserving existing values within the new bounds.
 225    /// </summary>
 226    public void Resize(int newWidth, int newHeight)
 4227    {
 4228        SwiftThrowHelper.ThrowIfNegative(newWidth, nameof(newWidth));
 4229        SwiftThrowHelper.ThrowIfNegative(newHeight, nameof(newHeight));
 230
 4231        if (newWidth == _width && newHeight == _height)
 1232            return;
 233
 3234        T[] newArray = new T[newWidth * newHeight];
 3235        int minWidth = Math.Min(_width, newWidth);
 3236        int minHeight = Math.Min(_height, newHeight);
 237
 16238        for (int x = 0; x < minWidth; x++)
 28239            for (int y = 0; y < minHeight; y++)
 9240                newArray[x * newHeight + y] = this[x, y];
 241
 3242        _innerArray = newArray;
 3243        _width = newWidth;
 3244        _height = newHeight;
 4245    }
 246
 247    #endregion
 248
 249    #region Utility Methods
 250
 251    private void Initialize(int width, int height)
 34252    {
 34253        _width = Math.Max(0, width);
 34254        _height = Math.Max(0, height);
 34255        _innerArray = new T[_width * _height];
 34256    }
 257
 258    /// <summary>
 259    /// Validates the specified index coordinates.
 260    /// </summary>
 261    public virtual void ValidateIndex(int x, int y)
 2000309262    {
 2000309263        if (x < 0 || x >= _width || y < 0 || y >= _height)
 2264            throw new IndexOutOfRangeException($"Invalid index: ({x}, {y})");
 2000307265    }
 266
 267    /// <summary>
 268    /// Checks if the specified index is valid in the current array dimensions.
 269    /// </summary>
 43270    public virtual bool IsValidIndex(int x, int y) => x >= 0 && x < Width && y >= 0 && y < Height;
 271
 272    /// <summary>
 273    /// Converts 2D coordinates to a flattened index.
 274    /// </summary>
 2000307275    public virtual int GetIndex(int x, int y) => x * _height + y;
 276
 277    /// <summary>
 278    /// Converts the flattened array back to a 2D array representation.
 279    /// </summary>
 280    public T[,] ToArray()
 2281    {
 2282        T[,] result = new T[_width, _height];
 12283        for (int x = 0; x < _width; x++)
 24284            for (int y = 0; y < _height; y++)
 8285                result[x, y] = this[x, y];
 2286        return result;
 2287    }
 288
 289    /// <summary>
 290    /// Clones a 2D array into a new instance of Array2D.
 291    /// </summary>
 292    public SwiftArray2D<T> Clone()
 1293    {
 1294        var array2D = new SwiftArray2D<T>(Width, Height);
 6295        for (int x = 0; x < Width; x++)
 2296        {
 12297            for (int y = 0; y < Height; y++)
 4298                array2D[x, y] = this[x, y];
 2299        }
 1300        return array2D;
 1301    }
 302
 303    #endregion
 304
 305    #region IEnumerator Implementation
 306
 307    /// <summary>
 308    /// Returns an enumerator that iterates through all elements in the 2D array.
 309    /// </summary>
 310    /// <returns>An enumerator for the 2D array.</returns>
 311    public IEnumerator<T> GetEnumerator()
 8312    {
 62313        for (int x = 0; x < _width; x++)
 23314        {
 180315            for (int y = 0; y < _height; y++)
 67316            {
 67317                yield return this[x, y];
 67318            }
 23319        }
 8320    }
 321
 322    /// <summary>
 323    /// Returns an enumerator that iterates through all elements in the 2D array (non-generic).
 324    /// </summary>
 325    /// <returns>An enumerator for the 2D array.</returns>
 1326    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 327
 328    #endregion
 329}