< Summary

Information
Class: Hertzole.ScriptableValues.CollectionChangedArgsExtensions
Assembly: Hertzole.ScriptableValues
File(s): ./Packages/se.hertzole.scriptable-values/Runtime/Collections/Core/CollectionChangedArgs.cs
Tag: 52_28197466029
Line coverage
100%
Covered lines: 30
Uncovered lines: 0
Coverable lines: 30
Total lines: 314
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ToNotifyCollectionChangedEventArgs[T](...)0%660100%
TryGetNewValue[TKey, TValue](...)0%110100%
TryGetOldValue[TKey, TValue](...)0%110100%
TryGetValue[TKey, TValue](...)0%440100%

File(s)

./Packages/se.hertzole.scriptable-values/Runtime/Collections/Core/CollectionChangedArgs.cs

#LineLine coverage
 1#nullable enable
 2
 3using System;
 4using System.Buffers;
 5using System.Collections.Generic;
 6using System.Collections.Specialized;
 7using System.Runtime.InteropServices;
 8
 9namespace Hertzole.ScriptableValues
 10{
 11    /// <summary>
 12    ///     Represents the method that will handle an event when a collection changes.
 13    /// </summary>
 14    /// <typeparam name="T">The type of the items in the collection.</typeparam>
 15    public delegate void CollectionChangedEventHandler<T>(CollectionChangedArgs<T> e);
 16
 17    public static class CollectionChangedArgsExtensions
 18    {
 19        /// <summary>
 20        ///     Converts the <see cref="CollectionChangedArgs{T}" /> to a <see cref="NotifyCollectionChangedEventArgs" /
 21        /// </summary>
 22        /// <param name="args">The current args.</param>
 23        /// <typeparam name="T">The type of the items in the collection.</typeparam>
 24        /// <returns>The converted <see cref="NotifyCollectionChangedEventArgs" />.</returns>
 25        /// <exception cref="NotSupportedException"><c>args.Action</c> is not supported.</exception>
 26        public static NotifyCollectionChangedEventArgs ToNotifyCollectionChangedEventArgs<T>(this CollectionChangedArgs<
 24627        {
 24628            switch (args.Action)
 29            {
 30                case NotifyCollectionChangedAction.Add:
 9031                    return new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, args.NewItems.ToArray
 32                case NotifyCollectionChangedAction.Remove:
 5433                    return new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, args.OldItems.ToAr
 34                case NotifyCollectionChangedAction.Replace:
 7835                    return new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, args.NewItems.ToA
 36                        args.NewIndex);
 37                case NotifyCollectionChangedAction.Reset:
 1838                    return new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
 39            }
 40
 641            throw new NotSupportedException($"Can't create NotifyCollectionChangedEventArgs from this action ({args.Acti
 24042        }
 43
 44        /// <summary>
 45        ///     Helper method to get a value from the <see cref="CollectionChangedArgs{T}.NewItems" /> based on the give
 46        /// </summary>
 47        /// <param name="args">The current args.</param>
 48        /// <param name="key">The key to find the value for.</param>
 49        /// <param name="value">The found value, if any.</param>
 50        /// <typeparam name="TKey">The type of the key.</typeparam>
 51        /// <typeparam name="TValue">The type of the value.</typeparam>
 52        /// <returns><see langword="true" /> if a value was found; otherwise <see langword="false" />.</returns>
 53        public static bool TryGetNewValue<TKey, TValue>(this CollectionChangedArgs<KeyValuePair<TKey, TValue>> args, TKe
 1854        {
 1855            return TryGetValue(args.NewItems.Span, key, out value);
 1856        }
 57
 58        /// <summary>
 59        ///     Helper method to get a value from the <see cref="CollectionChangedArgs{T}.OldItems" /> based on the give
 60        /// </summary>
 61        /// <param name="args">The current args.</param>
 62        /// <param name="key">The key to find the value for.</param>
 63        /// <param name="value">The found value, if any.</param>
 64        /// <typeparam name="TKey">The type of the key.</typeparam>
 65        /// <typeparam name="TValue">The type of the value.</typeparam>
 66        /// <returns><see langword="true" /> if a value was found; otherwise <see langword="false" />.</returns>
 67        public static bool TryGetOldValue<TKey, TValue>(this CollectionChangedArgs<KeyValuePair<TKey, TValue>> args, TKe
 1868        {
 1869            return TryGetValue(args.OldItems.Span, key, out value);
 1870        }
 71
 72        private static bool TryGetValue<TKey, TValue>(ReadOnlySpan<KeyValuePair<TKey, TValue>> items, TKey key, out TVal
 3673        {
 3674            if (items.Length == 0)
 1275            {
 1276                value = default;
 1277                return false;
 78            }
 79
 2480            EqualityComparer<TKey> equalityComparer = EqualityComparer<TKey>.Default;
 81
 22882            for (int i = 0; i < items.Length; i++)
 10283            {
 10284                if (equalityComparer.Equals(items[i].Key, key))
 1285                {
 1286                    value = items[i].Value;
 1287                    return true;
 88                }
 9089            }
 90
 1291            value = default;
 1292            return false;
 3693        }
 94    }
 95
 96    /// <summary>
 97    ///     Provides data for the <see cref="CollectionChangedEventHandler{T}" /> events.
 98    /// </summary>
 99    /// <typeparam name="T">The type of the items in the collection.</typeparam>
 100    [StructLayout(LayoutKind.Auto)]
 101    public readonly struct CollectionChangedArgs<T> : IEquatable<CollectionChangedArgs<T>>
 102    {
 103        /// <summary>
 104        ///     Gets the action that specifies how the collection changed.
 105        /// </summary>
 106        public NotifyCollectionChangedAction Action { get; }
 107        /// <summary>
 108        ///     Gets the index at which the new item was added.
 109        /// </summary>
 110        public int NewIndex { get; }
 111        /// <summary>
 112        ///     Gets the index at which the old item was removed.
 113        /// </summary>
 114        public int OldIndex { get; }
 115        /// <summary>
 116        ///     Gets the items that were added.
 117        /// </summary>
 118        public ReadOnlyMemory<T> OldItems { get; }
 119        /// <summary>
 120        ///     Gets the items that were removed.
 121        /// </summary>
 122        public ReadOnlyMemory<T> NewItems { get; }
 123
 124        internal CollectionChangedArgs(NotifyCollectionChangedAction action,
 125            int newIndex = -1,
 126            ReadOnlyMemory<T> newItems = default,
 127            int oldIndex = -1,
 128            ReadOnlyMemory<T> oldItems = default)
 129        {
 130            Action = action;
 131            NewIndex = newIndex;
 132            OldIndex = oldIndex;
 133            OldItems = oldItems;
 134            NewItems = newItems;
 135        }
 136
 137        /// <summary>
 138        ///     Creates a new instance of <see cref="CollectionChangedArgs{T}" /> with the <c>Add</c> action with only o
 139        /// </summary>
 140        /// <param name="newItem">The new item that was added.</param>
 141        /// <param name="startingIndex">The index at which the new item was added.</param>
 142        /// <returns>A new instance of <see cref="CollectionChangedArgs{T}" />.</returns>
 143        public static CollectionChangedArgs<T> Add(T newItem, int startingIndex)
 144        {
 145            using (IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(1))
 146            {
 147                Memory<T> memory = owner.Memory.Slice(0, 1);
 148                memory.Span[0] = newItem;
 149                return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Add, startingIndex, memory);
 150            }
 151        }
 152
 153        /// <summary>
 154        ///     Creates a new instance of <see cref="CollectionChangedArgs{T}" /> with the <c>Add</c> action with multip
 155        /// </summary>
 156        /// <param name="newItems">The new items that were added.</param>
 157        /// <param name="startingIndex">The index at which the new items were added.</param>
 158        /// <returns>A new instance of <see cref="CollectionChangedArgs{T}" />.</returns>
 159        public static CollectionChangedArgs<T> Add(ReadOnlySpan<T> newItems, int startingIndex)
 160        {
 161            using (IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(newItems.Length))
 162            {
 163                Memory<T> memory = owner.Memory.Slice(0, newItems.Length);
 164                newItems.CopyTo(memory.Span);
 165                return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Add, startingIndex, memory);
 166            }
 167        }
 168
 169        /// <summary>
 170        ///     Creates a new instance of <see cref="CollectionChangedArgs{T}" /> with the <c>Remove</c> action with onl
 171        /// </summary>
 172        /// <param name="oldItem">The old item that was removed.</param>
 173        /// <param name="removedIndex">The index at which the old item was removed.</param>
 174        /// <returns>A new instance of <see cref="CollectionChangedArgs{T}" />.</returns>
 175        public static CollectionChangedArgs<T> Remove(T oldItem, int removedIndex)
 176        {
 177            using (IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(1))
 178            {
 179                Memory<T> memory = owner.Memory.Slice(0, 1);
 180                memory.Span[0] = oldItem;
 181                return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Remove, oldIndex: removedIndex, oldIte
 182            }
 183        }
 184
 185        /// <summary>
 186        ///     Creates a new instance of <see cref="CollectionChangedArgs{T}" /> with the <c>Remove</c> action with mul
 187        ///     items.
 188        /// </summary>
 189        /// <param name="oldItems">The old items that were removed.</param>
 190        /// <param name="removedIndex">The index at which the old items were removed.</param>
 191        /// <returns>A new instance of <see cref="CollectionChangedArgs{T}" />.</returns>
 192        public static CollectionChangedArgs<T> Remove(ReadOnlySpan<T> oldItems, int removedIndex)
 193        {
 194            using (IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(oldItems.Length))
 195            {
 196                Memory<T> memory = owner.Memory.Slice(0, oldItems.Length);
 197                oldItems.CopyTo(memory.Span);
 198                return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Remove, oldIndex: removedIndex, oldIte
 199            }
 200        }
 201
 202        /// <summary>
 203        ///     Creates a new instance of <see cref="CollectionChangedArgs{T}" /> with the <c>Replace</c> action with on
 204        ///     item.
 205        /// </summary>
 206        /// <param name="oldItem">The old item that was replaced.</param>
 207        /// <param name="newItem">The new item that was added.</param>
 208        /// <param name="index">The index at which the item was replaced.</param>
 209        /// <returns>A new instance of <see cref="CollectionChangedArgs{T}" />.</returns>
 210        public static CollectionChangedArgs<T> Replace(T oldItem, T newItem, int index)
 211        {
 212            using (IMemoryOwner<T> oldOwner = MemoryPool<T>.Shared.Rent(1))
 213            {
 214                Memory<T> oldMemory = oldOwner.Memory.Slice(0, 1);
 215                oldMemory.Span[0] = oldItem;
 216
 217                using (IMemoryOwner<T> newOwner = MemoryPool<T>.Shared.Rent(1))
 218                {
 219                    Memory<T> newMemory = newOwner.Memory.Slice(0, 1);
 220                    newMemory.Span[0] = newItem;
 221                    return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Replace, index, newMemory, index, 
 222                }
 223            }
 224        }
 225
 226        /// <summary>
 227        ///     Creates a new instance of <see cref="CollectionChangedArgs{T}" /> with the <c>Replace</c> action with mu
 228        ///     items.
 229        /// </summary>
 230        /// <param name="oldItems">The old items that were replaced.</param>
 231        /// <param name="newItems">The new items that were added.</param>
 232        /// <param name="startingIndex">The index at which the items were replaced.</param>
 233        /// <returns>A new instance of <see cref="CollectionChangedArgs{T}" />.</returns>
 234        public static CollectionChangedArgs<T> Replace(ReadOnlySpan<T> oldItems, ReadOnlySpan<T> newItems, int startingI
 235        {
 236            using IMemoryOwner<T> oldOwner = MemoryPool<T>.Shared.Rent(oldItems.Length);
 237            Memory<T> oldMemory = oldOwner.Memory.Slice(0, oldItems.Length);
 238            oldItems.CopyTo(oldMemory.Span);
 239
 240            using IMemoryOwner<T> newOwner = MemoryPool<T>.Shared.Rent(newItems.Length);
 241            Memory<T> newMemory = newOwner.Memory.Slice(0, newItems.Length);
 242            newItems.CopyTo(newMemory.Span);
 243
 244            return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Replace, startingIndex, newMemory, startin
 245        }
 246
 247        /// <summary>
 248        ///     Creates a new instance of <see cref="CollectionChangedArgs{T}" /> with the <c>Reset</c> action.
 249        /// </summary>
 250        /// <param name="items">The items that were cleared.</param>
 251        /// <param name="newIndex">The index at which the items were cleared.</param>
 252        /// <param name="oldIndex">The index at which the items were cleared.</param>
 253        /// <returns>A new instance of <see cref="CollectionChangedArgs{T}" />.</returns>
 254        public static CollectionChangedArgs<T> Clear(ReadOnlySpan<T> items, int newIndex = 0, int oldIndex = 0)
 255        {
 256            using IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(items.Length);
 257            Memory<T> memory = owner.Memory.Slice(0, items.Length);
 258            items.CopyTo(memory.Span);
 259
 260            return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Reset, newIndex, oldIndex: oldIndex, oldIt
 261        }
 262
 263        /// <summary>
 264        ///     Checks if the current instance is equal to another <see cref="CollectionChangedArgs{T}" /> instance.
 265        /// </summary>
 266        /// <param name="other">The other instance to compare with.</param>
 267        /// <returns><c>true</c> if the instances are equal; otherwise, <c>false</c>.</returns>
 268        public bool Equals(CollectionChangedArgs<T> other)
 269        {
 270            return Action == other.Action && NewIndex == other.NewIndex && OldIndex == other.OldIndex && OldItems.Equals
 271                   NewItems.Equals(other.NewItems);
 272        }
 273
 274        /// <summary>
 275        ///     Checks if the current instance is the same type as the given object and if they are equal.
 276        /// </summary>
 277        /// <param name="obj">The object to compare with.</param>
 278        /// <returns>
 279        ///     <c>true</c> if the object is a <see cref="CollectionChangedArgs{T}" /> and is equal to the current insta
 280        ///     otherwise, <c>false</c>.
 281        /// </returns>
 282        public override bool Equals(object? obj)
 283        {
 284            return obj is CollectionChangedArgs<T> other && Equals(other);
 285        }
 286
 287        /// <summary>
 288        ///     Generates a hash code for the current instance.
 289        /// </summary>
 290        /// <returns>A hash code for the current instance.</returns>
 291        public override int GetHashCode()
 292        {
 293            unchecked
 294            {
 295                int hashCode = (int) Action;
 296                hashCode = (hashCode * 397) ^ NewIndex;
 297                hashCode = (hashCode * 397) ^ OldIndex;
 298                hashCode = (hashCode * 397) ^ OldItems.GetHashCode();
 299                hashCode = (hashCode * 397) ^ NewItems.GetHashCode();
 300                return hashCode;
 301            }
 302        }
 303
 304        public static bool operator ==(CollectionChangedArgs<T> left, CollectionChangedArgs<T> right)
 305        {
 306            return left.Equals(right);
 307        }
 308
 309        public static bool operator !=(CollectionChangedArgs<T> left, CollectionChangedArgs<T> right)
 310        {
 311            return !left.Equals(right);
 312        }
 313    }
 314}