< Summary

Class:Towel.DataStructures.MapHashLinked<T1, T2, T3, T4>
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/DataStructures/Map.cs
Covered lines:255
Uncovered lines:88
Coverable lines:343
Total lines:893
Line coverage:74.3% (255 of 343)
Covered branches:85
Total branches:120
Branch coverage:70.8% (85 of 120)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%6100%
File 1: .ctor(...)100%1100%
File 1: get_TableSize()100%10%
File 1: get_Count()100%1100%
File 1: get_Hash()100%1100%
File 1: get_Equate()100%1100%
File 1: get_Item(...)100%1100%
File 1: GetLocation(...)100%1100%
File 1: TryAdd(...)100%10100%
File 1: TryAddOrUpdate(...)90%1096.66%
File 1: TryRemoveOrUpdate(...)0%80%
File 1: TryUpdate(...)75%491.66%
File 1: TryGet(...)100%4100%
File 1: TrySet(...)100%10100%
File 1: TryRemove(...)87.5%887.5%
File 1: TryRemoveWithoutTrim(...)83.33%694.44%
File 1: Resize(...)83.33%688.88%
File 1: Trim()0%20%
File 1: Clone()100%1100%
File 1: Contains(...)100%4100%
File 1: Clear()100%1100%
File 1: StepperBreak(...)0%60%
File 1: KeysBreak(...)83.33%683.33%
File 1: GetKeys()100%4100%
File 1: PairsBreak(...)83.33%683.33%
File 1: GetPairs()100%4100%
File 1: System.Collections.IEnumerable.GetEnumerator()100%10%
File 1: GetEnumerator()0%40%
File 1: ToArray()0%40%
File 1: KeysToArray()100%4100%
File 1: PairsToArray()0%40%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/DataStructures/Map.cs

#LineLine coverage
 1namespace Towel.DataStructures;
 2
 3/// <summary>A map between instances of two types. The polymorphism base for Map implementations in Towel.</summary>
 4/// <typeparam name="T">The generic type to be stored in this data structure.</typeparam>
 5/// <typeparam name="TKey">The type of keys used to look up items in this structure.</typeparam>
 6public interface IMap<T, TKey> : IDataStructure<T>,
 7  DataStructure.ICountable,
 8  DataStructure.IClearable,
 9  DataStructure.IAuditable<TKey>,
 10  DataStructure.IRemovable<TKey>
 11{
 12  #region Properties
 13
 14  /// <summary>Allows indexed look-up of the structure. (Set does not replace the Add() method)</summary>
 15  /// <param name="key">The "index" to access of the structure.</param>
 16  /// <returns>The value at the index of the requested key.</returns>
 17  T this[TKey key] { get; set; }
 18
 19  #endregion
 20
 21  #region Methods
 22
 23  /// <summary>Tries to get a value by key.</summary>
 24  /// <param name="key">The key of the value to get.</param>
 25  /// <returns>
 26  /// - <see cref="bool"/> Success: true if the key was found or false if not.<br/>
 27  /// - <see cref="Exception"/>? Exception: the exception that occured if the get failed.<br/>
 28  /// - <typeparamref name="T"/>? Value: the value if the key was found or default if not.
 29  /// </returns>
 30  (bool Success, Exception? Exception, T? Value) TryGet(TKey key);
 31
 32  /// <summary>Sets value in the map.</summary>
 33  /// <param name="key">The key of the value.</param>
 34  /// <param name="value">The value to be set.</param>
 35  /// <returns>
 36  /// - <see cref="bool"/> Success: true if the key+value was set or false if not.<br/>
 37  /// - <see cref="Exception"/>? Exception: the exception that occured if the set failed.<br/>
 38  /// - <see cref="bool"/>? Existed: if the key existed prior to being set<br/>
 39  /// - <typeparamref name="T"/>? OldValue: the previous value if the key existed prior to being set
 40  /// </returns>
 41  (bool Success, Exception? Exception, bool? Existed, T? OldValue) TrySet(TKey key, T value);
 42
 43  /// <summary>Tries to add a value to the map.</summary>
 44  /// <param name="key">The key of the value.</param>
 45  /// <param name="value">The value to be added.</param>
 46  /// <returns>
 47  /// - <see cref="bool"/> Success: true if the key+value was added or false if not<br/>
 48  /// - <see cref="Exception"/>? Exception: the exception that occured if the add failed
 49  /// </returns>
 50  (bool Success, Exception? Exception) TryAdd(TKey key, T value);
 51
 52  /// <summary>Tries to update a value in the map the relative key exists.</summary>
 53  /// <typeparam name="TRemovePredicate">The type of predicate determining if the pair should be removed.</typeparam>
 54  /// <typeparam name="TUpdate">The type of function to update the value.</typeparam>
 55  /// <param name="key">The key of the value to update.</param>
 56  /// <param name="removePredicate">The predicate determining if the pair should be removed.</param>
 57  /// <param name="update">The function to update the value relative to the key.</param>
 58  /// <returns>
 59  /// - <see cref="bool"/> Success: true if the key was found or false if not<br/>
 60  /// - <see cref="Exception"/>? Exception: the exception that occured if the add failed<br/>
 61  /// - <typeparamref name="T"/>? OldValue: the non-updated value if the key was found or default if not<br/>
 62  /// - <typeparamref name="T"/>? NewValue: the updated value if the key was found or default if not
 63  /// </returns>
 64  (bool Success, Exception? Exception, bool? Removed, T? OldValue, T? NewValue) TryRemoveOrUpdate<TRemovePredicate, TUpd
 65    where TRemovePredicate : struct, IFunc<T, bool>
 66    where TUpdate : struct, IFunc<T, T>;
 67
 68  /// <summary>Tries to update a value in the map the relative key exists.</summary>
 69  /// <typeparam name="TUpdate">The type of function to update the value.</typeparam>
 70  /// <param name="key">The key of the value to update.</param>
 71  /// <param name="update">The function to update the value relative to the key.</param>
 72  /// <returns>
 73  /// - <see cref="bool"/> Success: true if the key was found or false if not<br/>
 74  /// - <see cref="Exception"/>? Exception: the exception that occured if the add failed<br/>
 75  /// - <typeparamref name="T"/>? OldValue: the non-updated value if the key was found or default if not<br/>
 76  /// - <typeparamref name="T"/>? NewValue: the updated value if the key was found or default if not
 77  /// </returns>
 78  (bool Success, Exception? Exception, T? OldValue, T? NewValue) TryUpdate<TUpdate>(TKey key, TUpdate update = default)
 79    where TUpdate : struct, IFunc<T, T>;
 80
 81  /// <summary>Adds or updates the value at the given key.</summary>
 82  /// <typeparam name="TUpdate">The type of function to update the value if present.</typeparam>
 83  /// <param name="key">The key of the value to add or update.</param>
 84  /// <param name="value">The value to add if not already present.</param>
 85  /// <param name="update">The function to update the value if present.</param>
 86  /// <returns>
 87  /// - <see cref="bool"/> Success: true if the value was added or updated or false if not.<br/>
 88  /// - <see cref="Exception"/>? Exception: the exception that occured if the add or update failed.<br/>
 89  /// - <see cref="bool"/>? Existed: if the key existed prior to the add or update<br/>
 90  /// - <typeparamref name="T"/>? OldValue: the old value if the key existed prior to the add or update
 91  /// </returns>
 92  (bool Success, Exception? Exception, bool? Existed, T? OldValue) TryAddOrUpdate<TUpdate>(TKey key, T value, TUpdate up
 93    where TUpdate : struct, IFunc<T, T>;
 94
 95  /// <summary>Gets an enumerator that will traverse the keys of the map.</summary>
 96  /// <returns>An enumerator that will traverse the keys of the map.</returns>
 97  System.Collections.Generic.IEnumerable<TKey> GetKeys();
 98
 99  /// <summary>Gets an array with all the keys in the map.</summary>
 100  /// <returns>An array with all the keys in the map.</returns>
 101  TKey[] KeysToArray();
 102
 103  /// <summary>Performs a function on every key in a map.</summary>
 104  /// <typeparam name="TStep">The type of the step function.</typeparam>
 105  /// <param name="step">The step function to perform on every key.</param>
 106  /// <returns>The status of traversal.</returns>
 107  StepStatus KeysBreak<TStep>(TStep step = default)
 108    where TStep : struct, IFunc<TKey, StepStatus>;
 109
 110  /// <summary>Gets an enumerator that will traverse the pairs of the map.</summary>
 111  /// <returns>An enumerator that will traverse the pairs of the map.</returns>
 112  System.Collections.Generic.IEnumerable<(T Value, TKey Key)> GetPairs();
 113
 114  /// <summary>Gets an array with all the pairs in the map.</summary>
 115  /// <returns>An array with all the pairs in the map.</returns>
 116  (T Value, TKey Key)[] PairsToArray();
 117
 118  /// <summary>Performs a function on every pair in a map.</summary>
 119  /// <typeparam name="TStep">The type of the step function.</typeparam>
 120  /// <param name="step">The step function to perform on every pair.</param>
 121  /// <returns>The status of traversal.</returns>
 122  StepStatus PairsBreak<TStep>(TStep step = default)
 123    where TStep : struct, IFunc<(T Value, TKey Key), StepStatus>;
 124
 125  #endregion
 126}
 127
 128/// <summary>Static Extension class for Map interface implementers.</summary>
 129public static class Map
 130{
 131  #region Extensions Methods
 132
 133  /// <summary>Updates a value in the map the relative key exists.</summary>
 134  /// <typeparam name="T">The type of values in the map.</typeparam>
 135  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 136  /// <param name="map">The map to update the value in.</param>
 137  /// <param name="key">The key of the value to update.</param>
 138  /// <param name="update">The function to update the value relative to the key.</param>
 139  /// <returns>
 140  /// (<typeparamref name="T"/> OldValue, <typeparamref name="T"/> NewValue)<br/>
 141  /// - <typeparamref name="T"/> OldValue: the value relative tothe key before to the update<br/>
 142  /// - <typeparamref name="T"/> NewValue: the value relative tothe key after to the update
 143  /// </returns>
 144  public static (T OldValue, T NewValue) Update<T, TKey>(this IMap<T, TKey> map, TKey key, Func<T, T> update) =>
 145    map.Update<T, TKey, SFunc<T, T>>(key, update);
 146
 147  /// <summary>Adds or updates the value at the given key.</summary>
 148  /// <typeparam name="T">The type of values in the map.</typeparam>
 149  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 150  /// <param name="map">The map to add or update the value in.</param>
 151  /// <param name="key">The key of the value to add or update.</param>
 152  /// <param name="value">The value to add if not already present.</param>
 153  /// <param name="update">The function to update the value if present.</param>
 154  /// <returns>
 155  /// (<see cref="bool"/> Existed, <typeparamref name="T"/> OldValue)<br/>
 156  /// - <see cref="bool"/> Existed: true if the key was already in the map<br/>
 157  /// - <typeparamref name="T"/> OldValue: the value relative tothe key before to the update if it existed or default
 158  /// </returns>
 159  public static (bool Existed, T? OldValue) AddOrUpdate<T, TKey>(this IMap<T, TKey> map, TKey key, T value, Func<T, T> u
 160    map.AddOrUpdate<T, TKey, SFunc<T, T>>(key, value, update);
 161
 162  /// <summary>Updates a value in the map the relative key exists.</summary>
 163  /// <typeparam name="T">The type of values in the map.</typeparam>
 164  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 165  /// <typeparam name="TUpdate">The type of function to update the value.</typeparam>
 166  /// <param name="map">The map to update the value in.</param>
 167  /// <param name="key">The key of the value to update.</param>
 168  /// <param name="update">The function to update the value relative to the key.</param>
 169  /// <returns>
 170  /// (<typeparamref name="T"/> OldValue, <typeparamref name="T"/> NewValue)<br/>
 171  /// - <typeparamref name="T"/> OldValue: the value relative tothe key before to the update<br/>
 172  /// - <typeparamref name="T"/> NewValue: the value relative tothe key after to the update
 173  /// </returns>
 174  public static (T OldValue, T NewValue) Update<T, TKey, TUpdate>(this IMap<T, TKey> map, TKey key, TUpdate update = def
 175    where TUpdate : struct, IFunc<T, T>
 176  {
 177    var (success, exception, oldValue, newValue) = map.TryUpdate(key, update);
 178    if (!success)
 179    {
 180      throw exception ?? new ArgumentException($"{nameof(Update)} failed but the {nameof(exception)} is null");
 181    }
 182    return (oldValue!, newValue!);
 183  }
 184
 185  /// <summary>Adds or updates the value at the given key.</summary>
 186  /// <typeparam name="T">The type of values in the map.</typeparam>
 187  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 188  /// <typeparam name="TUpdate">The type of function to update the value.</typeparam>
 189  /// <param name="map">The map to add or update the value in.</param>
 190  /// <param name="key">The key of the value to add or update.</param>
 191  /// <param name="value">The value to add if not already present.</param>
 192  /// <param name="update">The function to update the value if present.</param>
 193  /// <returns>
 194  /// - <see cref="bool"/> Existed: true if the key was already in the map<br/>
 195  /// - <typeparamref name="T"/> OldValue: the value relative tothe key before to the update if it existed or default
 196  /// </returns>
 197  public static (bool Existed, T? OldValue) AddOrUpdate<T, TKey, TUpdate>(this IMap<T, TKey> map, TKey key, T value, TUp
 198    where TUpdate : struct, IFunc<T, T>
 199  {
 200    var (success, exception, existed, oldValue) = map.TryAddOrUpdate(key, value, update);
 201    if (!success)
 202    {
 203      throw exception ?? new ArgumentException($"{nameof(AddOrUpdate)} failed but the {nameof(exception)} is null");
 204    }
 205    return (existed!.Value, oldValue);
 206  }
 207
 208  /// <summary>Tries to update a value in the map the relative key exists.</summary>
 209  /// <typeparam name="T">The type of values in the map.</typeparam>
 210  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 211  /// <param name="map">The map to update the value in.</param>
 212  /// <param name="key">The key of the value to update.</param>
 213  /// <param name="update">The function to update the value relative to the key.</param>
 214  /// <returns>
 215  /// - <see cref="bool"/> Success: true if the key was found or false if not<br/>
 216  /// - <see cref="Exception"/>? Exception: the exception that occured if the update failed<br/>
 217  /// - <typeparamref name="T"/>? OldValue: the value if the key was found or default if not<br/>
 218  /// - <typeparamref name="T"/>? NewValue: the value if the key was found or default if not
 219  /// </returns>
 220  public static (bool Success, Exception? Exception, T? OldValue, T? NewValue) TryUpdate<T, TKey>(this IMap<T, TKey> map
 221  {
 222    if (update is null) throw new ArgumentNullException(nameof(update));
 223    return map.TryUpdate<SFunc<T, T>>(key, update);
 224  }
 225
 226  /// <summary>Tries to add or update the value at the given key.</summary>
 227  /// <typeparam name="T">The type of values in the map.</typeparam>
 228  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 229  /// <param name="map">The map to add or update the value in.</param>
 230  /// <param name="key">The key of the value to add or update.</param>
 231  /// <param name="value">The value to add if not already present.</param>
 232  /// <param name="update">The function to update the value if present.</param>
 233  /// <returns>
 234  /// - <see cref="bool"/> Success: true if the value was added or updated or false if not.<br/>
 235  /// - <see cref="Exception"/>? Exception: the exception that occured if the add or update failed<br/>
 236  /// - <see cref="bool"/>? Existed: true if the key-value pair was added or updated or false<br/>
 237  /// - <typeparamref name="T"/>? OldValue: the previous value if the key existed before the add or update operation
 238  /// </returns>
 239  public static (bool Success, Exception? Exception, bool? Existed, T? OldValue) TryAddOrUpdate<T, TKey>(this IMap<T, TK
 240  {
 241    if (update is null) throw new ArgumentNullException(nameof(update));
 242    return map.TryAddOrUpdate<SFunc<T, T>>(key, value, update);
 243  }
 244
 245  /// <summary>Adds a value to a map by key.</summary>
 246  /// <typeparam name="T">The type of values in the map.</typeparam>
 247  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 248  /// <param name="map">The map to add the value to.</param>
 249  /// <param name="key">The key of the value to get.</param>
 250  /// <param name="value">The value to add to the map.</param>
 251  public static void Add<T, TKey>(this IMap<T, TKey> map, TKey key, T value)
 252  {
 253    var (success, exception) = map.TryAdd(key, value);
 254    if (!success)
 255    {
 256      throw exception ?? new ArgumentException($"{nameof(Add)} failed but the {nameof(exception)} is null");
 257    }
 258  }
 259
 260  /// <summary>Sets a value in a map relative to a key.</summary>
 261  /// <typeparam name="T">The type of the value.</typeparam>
 262  /// <typeparam name="TKey">The type of the key.</typeparam>
 263  /// <param name="map">The map to set the value in.</param>
 264  /// <param name="key">The key.</param>
 265  /// <param name="value">The value.</param>
 266  /// <returns>
 267  /// (<see cref="bool"/> Existed, <typeparamref name="T"/> OldValue)<br/>
 268  /// - <see cref="bool"/> Existed: true if the key was already in the map<br/>
 269  /// - <typeparamref name="T"/> OldValue: the value relative tothe key before to the update if it existed or default
 270  /// </returns>
 271  public static (bool Existed, T? OldValue) Set<T, TKey>(this IMap<T, TKey> map, TKey key, T value)
 272  {
 273    var (success, exception, existed, oldValue) = map.TrySet(key, value);
 274    if (!success)
 275    {
 276      throw exception ?? new ArgumentException($"{nameof(Set)} failed but the {nameof(exception)} is null");
 277    }
 278    return (existed!.Value, oldValue);
 279  }
 280
 281  /// <summary>Gets a value in a map relative to a key.</summary>
 282  /// <typeparam name="T">The type of the value.</typeparam>
 283  /// <typeparam name="TKey">The type of the key.</typeparam>
 284  /// <param name="map">The map to set the value in.</param>
 285  /// <param name="key">The key.</param>
 286  /// <returns>The value relative to the key.</returns>
 287  public static T Get<T, TKey>(this IMap<T, TKey> map, TKey key)
 288  {
 289    var (success, exception, value) = map.TryGet(key);
 290    if (!success)
 291    {
 292      throw exception ?? new ArgumentException($"{nameof(Get)} failed but the {nameof(exception)} is null");
 293    }
 294    return value!;
 295  }
 296
 297  /// <summary>Performs a function on every key in a map.</summary>
 298  /// <typeparam name="T">The type of values in the map.</typeparam>
 299  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 300  /// <param name="map">The map to traverse the keys of.</param>
 301  /// <param name="step">The step function to perform on every key.</param>
 302  public static void Keys<T, TKey>(this IMap<T, TKey> map, Action<TKey> step)
 303  {
 304    if (step is null) throw new ArgumentNullException(nameof(step));
 305    map.Keys<T, TKey, SAction<TKey>>(step);
 306  }
 307
 308  /// <summary>Performs a function on every key in a map.</summary>
 309  /// <typeparam name="T">The type of values in the map.</typeparam>
 310  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 311  /// <typeparam name="TStep">The type of step function to perform on every key.</typeparam>
 312  /// <param name="map">The map to traverse the keys of.</param>
 313  /// <param name="step">The step function to perform on every key.</param>
 314  public static void Keys<T, TKey, TStep>(this IMap<T, TKey> map, TStep step = default)
 315    where TStep : struct, IAction<TKey> =>
 316    map.KeysBreak<StepBreakFromAction<TKey, TStep>>(step);
 317
 318  /// <summary>Performs a function on every key in a map.</summary>
 319  /// <typeparam name="T">The type of values in the map.</typeparam>
 320  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 321  /// <param name="map">The map to traverse the keys of.</param>
 322  /// <param name="step">The step function to perform on every key.</param>
 323  /// <returns>The status of the traversal.</returns>
 324  public static StepStatus KeysBreak<T, TKey>(this IMap<T, TKey> map, Func<TKey, StepStatus> step)
 325  {
 326    if (step is null) throw new ArgumentNullException(nameof(step));
 327    return map.KeysBreak<SFunc<TKey, StepStatus>>(step);
 328  }
 329
 330  /// <summary>Performs a function on every pair in a map.</summary>
 331  /// <typeparam name="T">The type of values in the map.</typeparam>
 332  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 333  /// <param name="map">The map to traverse the pairs of.</param>
 334  /// <param name="step">The step function to perform on every pair.</param>
 335  public static void Pairs<T, TKey>(this IMap<T, TKey> map, Action<(T Value, TKey Key)> step)
 336  {
 337    if (step is null) throw new ArgumentNullException(nameof(step));
 338    map.Pairs<T, TKey, SAction<(T Value, TKey Key)>>(step);
 339  }
 340
 341  /// <summary>Performs a function on every pair in a map.</summary>
 342  /// <typeparam name="T">The type of values in the map.</typeparam>
 343  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 344  /// <typeparam name="TStep">The type of step function to perform on every pair.</typeparam>
 345  /// <param name="map">The map to traverse the pairs of.</param>
 346  /// <param name="step">The step function to perform on every pair.</param>
 347  public static void Pairs<T, TKey, TStep>(this IMap<T, TKey> map, TStep step = default)
 348    where TStep : struct, IAction<(T Value, TKey Key)> =>
 349    map.PairsBreak<StepBreakFromAction<(T Value, TKey Key), TStep>>(step);
 350
 351  /// <summary>Performs a function on every pair in a map.</summary>
 352  /// <typeparam name="T">The type of values in the map.</typeparam>
 353  /// <typeparam name="TKey">The type of keys in the map.</typeparam>
 354  /// <param name="map">The map to traverse the pairs of.</param>
 355  /// <param name="step">The step function to perform on every pair.</param>
 356  /// <returns>The status of the traversal.</returns>
 357  public static StepStatus PairsBreak<T, TKey>(this IMap<T, TKey> map, Func<(T Value, TKey Key), StepStatus> step)
 358  {
 359    if (step is null) throw new ArgumentNullException(nameof(step));
 360    return map.PairsBreak<SFunc<(T Value, TKey Key), StepStatus>>(step);
 361  }
 362
 363  #endregion
 364}
 365
 366/// <summary>Static helpers.</summary>
 367public static class MapHashLinked
 368{
 369  #region Extension Methods
 370
 371  /// <summary>Constructs a new <see cref="MapHashLinked{T, K, TEquate, THash}"/>.</summary>
 372  /// <typeparam name="T">The type of values stored in this data structure.</typeparam>
 373  /// <typeparam name="TKey">The type of keys used to look up values.</typeparam>
 374  /// <param name="equate">The function for comparing <typeparamref name="T"/> values for equality.</param>
 375  /// <param name="hash">The function for hashing <typeparamref name="T"/> values.</param>
 376  /// <returns>The new constructed <see cref="MapHashLinked{T, K, TEquate, THash}"/>.</returns>
 377  public static MapHashLinked<T, TKey, SFunc<TKey, TKey, bool>, SFunc<TKey, int>> New<T, TKey>(
 378    Func<TKey, TKey, bool>? equate = null,
 379    Func<TKey, int>? hash = null) =>
 380    new(equate ?? Equate, hash ?? Hash);
 381
 382  #endregion
 383}
 384
 385/// <summary>An unsorted structure of unique items.</summary>
 386/// <typeparam name="T">The generic type of the structure.</typeparam>
 387/// <typeparam name="TKey">The generic key type of this map.</typeparam>
 388/// <typeparam name="TEquate">The type of function for quality checking <typeparamref name="TKey"/> values.</typeparam>
 389/// <typeparam name="THash">The type of function for hashing <typeparamref name="TKey"/> values.</typeparam>
 390public class MapHashLinked<T, TKey, TEquate, THash> : IMap<T, TKey>,
 391  ICloneable<MapHashLinked<T, TKey, TEquate, THash>>,
 392  DataStructure.IEquating<TKey, TEquate>,
 393  DataStructure.IHashing<TKey, THash>
 394  where TEquate : struct, IFunc<TKey, TKey, bool>
 395  where THash : struct, IFunc<TKey, int>
 396{
 397  internal const float _maxLoadFactor = .7f;
 398  internal const float _minLoadFactor = .3f;
 399
 400  internal TEquate _equate;
 401  internal THash _hash;
 402  internal Node?[] _table;
 403  internal int _count;
 404
 405  #region Nested Types
 406
 407  internal class Node
 408  {
 409    internal TKey Key;
 410    internal T Value;
 411    internal Node? Next;
 412
 602477413    internal Node(T value, TKey key, Node? next = null)
 602477414    {
 602477415      Value = value;
 602477416      Key = key;
 602477417      Next = next;
 602477418    }
 419  }
 420
 421  #endregion
 422
 423  #region Constructors
 424
 425  /// <summary>Constructs a new <see cref="MapHashLinked{T, K, TEquate, THash}"/>.</summary>
 426  /// <param name="equate">The function for quality checking <typeparamref name="TKey"/> values.</param>
 427  /// <param name="hash">The function for hashing <typeparamref name="TKey"/> values.</param>
 428  /// <param name="expectedCount">The expected count of the map.</param>
 430429  public MapHashLinked(
 430430    TEquate equate = default,
 430431    THash hash = default,
 430432    int? expectedCount = null)
 430433  {
 430434    if (expectedCount.HasValue && expectedCount.Value > 0)
 26435    {
 26436      int tableSize = (int)(expectedCount.Value * (1 / _maxLoadFactor));
 49437      while (!IsPrime(tableSize))
 23438      {
 23439        tableSize++;
 23440      }
 26441      _table = new Node[tableSize];
 26442    }
 443    else
 404444    {
 404445      _table = new Node[2];
 404446    }
 430447    _equate = equate;
 430448    _hash = hash;
 430449    _count = 0;
 430450  }
 451
 452  /// <summary>This constructor is for cloning purposes.</summary>
 453  /// <param name="map">The map to clone.</param>
 1454  internal MapHashLinked(MapHashLinked<T, TKey, TEquate, THash> map)
 1455  {
 1456    _equate = map._equate;
 1457    _hash = map._hash;
 1458    _table = (Node[])map._table.Clone();
 1459    _count = map._count;
 1460  }
 461
 462  #endregion
 463
 464  #region Properties
 465
 466  /// <summary>The current size of the hashed table.</summary>
 0467  public int TableSize => _table.Length;
 468
 469  /// <inheritdoc/>
 174470  public int Count => _count;
 471
 472  /// <inheritdoc/>
 198473  public THash Hash => _hash;
 474
 475  /// <inheritdoc/>
 198476  public TEquate Equate => _equate;
 477
 478  /// <summary>Gets the value of a specified key.</summary>
 479  /// <param name="key">The key to get the value of.</param>
 480  /// <returns>The value of the key.</returns>
 601408481  public T this[TKey key] { get => this.Get(key); set => this.Set(key, value); }
 482
 483  #endregion
 484
 485  #region Methods
 486
 1700243487  internal int GetLocation(TKey key) => (_hash.Invoke(key) & int.MaxValue) % _table.Length;
 488
 489  /// <inheritdoc/>
 490  public (bool Success, Exception? Exception) TryAdd(TKey key, T value)
 400242491  {
 400242492    int location = GetLocation(key);
 1000090493    for (Node? node = _table[location]; node is not null; node = node.Next)
 99810494    {
 99810495      if (_equate.Invoke(node.Key, key))
 7496      {
 7497        return (false, new ArgumentException("Attempting to add a duplicate key to a map.", nameof(key)));
 498      }
 99803499    }
 400235500    _table[location] = new Node(value: value, key: key, next: _table[location]);
 400235501    _count++;
 400235502    if (_count > _table.Length * _maxLoadFactor)
 143503    {
 143504      float tableSizeFloat = (_count * 2) * (1 / _maxLoadFactor);
 143505      if (tableSizeFloat <= int.MaxValue)
 143506      {
 143507        int tableSize = (int)tableSizeFloat;
 426508        while (!IsPrime(tableSize))
 283509        {
 283510          tableSize++;
 283511        }
 143512        Resize(tableSize);
 143513      }
 143514    }
 400235515    return (true, null);
 400242516  }
 517
 518  /// <inheritdoc/>
 519  public (bool Success, Exception? Exception, bool? Existed, T? OldValue) TryAddOrUpdate<TUpdate>(TKey key, T value, TUp
 520    where TUpdate : struct, IFunc<T, T>
 3070521  {
 3070522    int location = GetLocation(key);
 6140523    for (Node? node = _table[location]; node is not null; node = node.Next)
 2028524    {
 2028525      if (_equate.Invoke(node.Key, key))
 2028526      {
 2028527        T oldValue = node.Value;
 2028528        node.Value = update.Invoke(node.Value);
 2028529        return (true, null, true, oldValue);
 530      }
 0531    }
 1042532    _table[location] = new Node(
 1042533      value: value,
 1042534      key: key,
 1042535      next: _table[location]);
 1042536    _count++;
 1042537    if (_count > _table.Length * _maxLoadFactor)
 12538    {
 12539      float tableSizeFloat = (_count * 2) * (1 / _maxLoadFactor);
 12540      if (tableSizeFloat <= int.MaxValue)
 12541      {
 12542        int tableSize = (int)tableSizeFloat;
 39543        while (!IsPrime(tableSize))
 27544        {
 27545          tableSize++;
 27546        }
 12547        Resize(tableSize);
 12548      }
 12549    }
 1042550    return (true, null, false, default);
 3070551  }
 552
 553  /// <inheritdoc/>
 554  public (bool Success, Exception? Exception, bool? Removed, T? OldValue, T? NewValue) TryRemoveOrUpdate<TRemovePredicat
 555    where TRemovePredicate : struct, IFunc<T, bool>
 556    where TUpdate : struct, IFunc<T, T>
 0557  {
 0558    int location = GetLocation(key);
 559
 0560    for (Node? node = _table[location], previous = null; node is not null; previous = node, node = node.Next)
 0561    {
 0562      if (_equate.Invoke(node.Key, key))
 0563      {
 0564        if (removePredicate.Invoke(node.Value))
 0565        {
 0566          if (previous is null)
 0567          {
 0568            _table[location] = node.Next;
 0569          }
 570          else
 0571          {
 0572            previous.Next = node.Next;
 0573          }
 0574          _count--;
 0575          return (true, null, true, node.Value, default);
 576        }
 577        else
 0578        {
 0579          T oldValue = node.Value;
 0580          node.Value = update.Invoke(node.Value);
 0581          return (true, null, false, oldValue, node.Value);
 582        }
 583      }
 0584    }
 0585    return (false, new ArgumentException(paramName: nameof(key), message: "key not found"), default, default, default);
 0586  }
 587
 588  /// <inheritdoc/>
 589  public (bool Success, Exception? Exception, T? OldValue, T? NewValue) TryUpdate<TUpdate>(TKey key, TUpdate update = de
 590    where TUpdate : struct, IFunc<T, T>
 62591  {
 62592    int location = GetLocation(key);
 124593    for (Node? node = _table[location]; node is not null; node = node.Next)
 60594    {
 60595      if (_equate.Invoke(node.Key, key))
 60596      {
 60597        T oldValue = node.Value;
 60598        node.Value = update.Invoke(node.Value);
 60599        return (true, null, oldValue, node.Value);
 600      }
 0601    }
 2602    return (false, new ArgumentException(paramName: nameof(key), message: "key not found"), default, default);
 62603  }
 604
 605  /// <inheritdoc/>
 606  public (bool Success, Exception? Exception, T? Value) TryGet(TKey key)
 420879607  {
 420879608    int location = GetLocation(key);
 926052609    for (Node? node = _table[location]; node is not null; node = node.Next)
 459909610    {
 459909611      if (_equate.Invoke(node.Key, key))
 417762612      {
 417762613        return (true, null, node.Value);
 614      }
 42147615    }
 3117616    return (false, new ArgumentException("Attempting to get a value from the map that has not been added.", nameof(key))
 420879617  }
 618
 619  /// <inheritdoc/>
 620  public (bool Success, Exception? Exception, bool? Existed, T? OldValue) TrySet(TKey key, T value)
 203210621  {
 203210622    int location = GetLocation(key);
 507206623    for (Node? node = _table[location]; node is not null; node = node.Next)
 52403624    {
 52403625      if (_equate.Invoke(node.Key, key))
 2010626      {
 2010627        T oldValue = node.Value;
 2010628        node.Value = value;
 2010629        return (true, null, true, oldValue);
 630      }
 50393631    }
 201200632    _table[location] = new Node(
 201200633      value: value,
 201200634      key: key,
 201200635      next: _table[location]);
 201200636    _count++;
 201200637    if (_count > _table.Length * _maxLoadFactor)
 120638    {
 120639      float tableSizeFloat = (_count * 2) * (1 / _maxLoadFactor);
 120640      if (tableSizeFloat <= int.MaxValue)
 120641      {
 120642        int tableSize = (int)tableSizeFloat;
 340643        while (!IsPrime(tableSize))
 220644        {
 220645          tableSize++;
 220646        }
 120647        Resize(tableSize);
 120648      }
 120649    }
 201200650    return (true, null, false, default);
 203210651  }
 652
 653  /// <inheritdoc/>
 654  public (bool Success, Exception? Exception) TryRemove(TKey key)
 66672655  {
 66672656    var (success, exception) = TryRemoveWithoutTrim(key);
 66672657    if (!success)
 0658    {
 0659      return (false, exception);
 660    }
 66672661    else if (_table.Length > 2 && _count < _table.Length * _minLoadFactor)
 3662    {
 3663      int tableSize = (int)(_count * (1 / _maxLoadFactor));
 4664      while (!IsPrime(tableSize))
 1665      {
 1666        tableSize++;
 1667      }
 3668      Resize(tableSize);
 3669    }
 66672670    return (true, null);
 66672671  }
 672
 673  /// <summary>Tries to remove a keyed value without shrinking the hash table.</summary>
 674  /// <param name="key">The key of the value to remove.</param>
 675  /// <returns>True if the removal was successful for false if not.</returns>
 676  public (bool Success, Exception? Exception) TryRemoveWithoutTrim(TKey key)
 66672677  {
 66672678    int location = GetLocation(key);
 221961679    for (Node? node = _table[location], previous = null; node is not null; previous = node, node = node.Next)
 73987680    {
 73987681      if (_equate.Invoke(node.Key, key))
 66672682      {
 66672683        if (previous is null)
 60307684        {
 60307685          _table[location] = node.Next;
 60307686        }
 687        else
 6365688        {
 6365689          previous.Next = node.Next;
 6365690        }
 66672691        _count--;
 66672692        return (true, null);
 693      }
 7315694    }
 0695    return (false, new ArgumentException("Attempting to remove a key that is no in a map.", nameof(key)));
 66672696  }
 697
 698  internal void Resize(int tableSize)
 278699  {
 278700    if (tableSize == _table.Length)
 0701    {
 0702      return;
 703    }
 704
 278705    Node?[] temp = _table;
 278706    _table = new Node[tableSize];
 707
 3759610708    for (int i = 0; i < temp.Length; i++)
 1879527709    {
 6015450710      for (Node? node = temp[i]; node is not null; node = temp[i])
 1128198711      {
 1128198712        temp[i] = node.Next;
 713
 1128198714        int hashCode = _hash.Invoke(node.Key);
 1128198715        int location = (hashCode & int.MaxValue) % _table.Length;
 716
 1128198717        node.Next = _table[location];
 1128198718        _table[location] = node;
 1128198719      }
 1879527720    }
 278721  }
 722
 723  /// <summary>
 724  /// Trims the table to an appropriate size based on the current count.<br/>
 725  /// Runtime: O(n), Î©(1)
 726  /// </summary>
 727  public void Trim()
 0728  {
 0729    int tableSize = _count;
 0730    while (!IsPrime(tableSize))
 0731    {
 0732      tableSize++;
 0733    }
 0734    Resize(tableSize);
 0735  }
 736
 737  /// <inheritdoc/>
 1738  public MapHashLinked<T, TKey, TEquate, THash> Clone() => new(this);
 739
 740  /// <inheritdoc/>
 741  public bool Contains(TKey key)
 606108742  {
 606108743    int location = GetLocation(key);
 1385008744    for (Node? node = _table[location]; node is not null; node = node.Next)
 624803745    {
 624803746      if (_equate.Invoke(node.Key, key))
 538407747      {
 538407748        return true;
 749      }
 86396750    }
 67701751    return false;
 606108752  }
 753
 754  /// <inheritdoc/>
 755  public void Clear()
 9756  {
 9757    _table = new Node[2];
 9758    _count = 0;
 9759  }
 760
 761  /// <inheritdoc/>
 762  public StepStatus StepperBreak<TStep>(TStep step = default)
 763    where TStep : struct, IFunc<T, StepStatus>
 0764  {
 0765    for (int i = 0; i < _table.Length; i++)
 0766    {
 0767      for (Node? node = _table[i]; node is not null; node = node.Next)
 0768      {
 0769        if (step.Invoke(node.Value) is Break)
 0770        {
 0771          return Break;
 772        }
 0773      }
 0774    }
 0775    return Continue;
 0776  }
 777
 778  /// <inheritdoc/>
 779  public StepStatus KeysBreak<TStep>(TStep step = default)
 780    where TStep : struct, IFunc<TKey, StepStatus>
 31781  {
 282782    for (int i = 0; i < _table.Length; i++)
 110783    {
 314784      for (Node? node = _table[i]; node is not null; node = node.Next)
 47785      {
 47786        if (step.Invoke(node.Key) is Break)
 0787        {
 0788          return Break;
 789        }
 47790      }
 110791    }
 31792    return Continue;
 31793  }
 794
 795  /// <inheritdoc/>
 796  public System.Collections.Generic.IEnumerable<TKey> GetKeys()
 3797  {
 30798    for (int i = 0; i < _table.Length; i++)
 12799    {
 38800      for (Node? node = _table[i]; node is not null; node = node.Next)
 7801      {
 7802        yield return node.Key;
 7803      }
 12804    }
 3805  }
 806
 807  /// <inheritdoc/>
 808  public StepStatus PairsBreak<TStep>(TStep step = default)
 809    where TStep : struct, IFunc<(T Value, TKey Key), StepStatus>
 11810  {
 180811    for (int i = 0; i < _table.Length; i++)
 79812    {
 224813      for (Node? node = _table[i]; node is not null; node = node.Next)
 33814      {
 33815        if (step.Invoke((node.Value, node.Key)) is Break)
 0816        {
 0817          return Break;
 818        }
 33819      }
 79820    }
 11821    return Continue;
 11822  }
 823
 824  /// <inheritdoc/>
 825  public System.Collections.Generic.IEnumerable<(T Value, TKey Key)> GetPairs()
 27826  {
 54864827    for (int i = 0; i < _table.Length; i++)
 27405828    {
 84858829      for (Node? node = _table[i]; node is not null; node = node.Next)
 15024830      {
 15024831        yield return (node.Value, node.Key);
 15024832      }
 27405833    }
 27834  }
 835
 0836  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 837
 838  /// <inheritdoc/>
 839  public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 0840  {
 0841    for (int i = 0; i < _table.Length; i++)
 0842    {
 0843      for (Node? node = _table[i]; node is not null; node = node.Next)
 0844      {
 0845        yield return node.Value;
 0846      }
 0847    }
 0848  }
 849
 850  /// <inheritdoc/>
 851  public T[] ToArray()
 0852  {
 0853    T[] array = new T[_count];
 0854    for (int i = 0, index = 0; i < _table.Length; i++)
 0855    {
 0856      for (Node? node = _table[i]; node is not null; node = node.Next)
 0857      {
 0858        array[index++] = node.Value;
 0859      }
 0860    }
 0861    return array;
 0862  }
 863
 864  /// <inheritdoc/>
 865  public TKey[] KeysToArray()
 1866  {
 1867    TKey[] array = new TKey[_count];
 25868    for (int i = 0, index = 0; i < _table.Length; i++)
 11869    {
 32870      for (Node? node = _table[i]; node is not null; node = node.Next)
 5871      {
 5872        array[index++] = node.Key;
 5873      }
 11874    }
 1875    return array;
 1876  }
 877
 878  /// <inheritdoc/>
 879  public (T Value, TKey Key)[] PairsToArray()
 0880  {
 0881    (T Value, TKey Key)[] array = new (T Value, TKey Key)[_count];
 0882    for (int i = 0, index = 0; i < _table.Length; i++)
 0883    {
 0884      for (Node? node = _table[i]; node is not null; node = node.Next)
 0885      {
 0886        array[index++] = (node.Value, node.Key);
 0887      }
 0888    }
 0889    return array;
 0890  }
 891
 892  #endregion
 893}