< Summary

Information
Class: Hertzole.ScriptableValues.CollectionChangedArgs[T]
Assembly: Hertzole.ScriptableValues
File(s): ./Packages/se.hertzole.scriptable-values/Runtime/Collections/Core/CollectionChangedArgs.cs
Tag: 52_28197466029
Line coverage
82%
Covered lines: 72
Uncovered lines: 15
Coverable lines: 87
Total lines: 314
Line coverage: 82.7%
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
CollectionChangedArgs(...)0%110100%
Add(...)0%220100%
Add(...)0%220100%
Remove(...)0%220100%
Remove(...)0%220100%
Replace(...)0%330100%
Replace(...)0%330100%
Clear(...)0%220100%
Equals(...)0%550100%
Equals(...)0%6200%
GetHashCode()0%2100%
operator==(...)0%110100%
operator!=(...)0%2100%

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<
 27        {
 28            switch (args.Action)
 29            {
 30                case NotifyCollectionChangedAction.Add:
 31                    return new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, args.NewItems.ToArray
 32                case NotifyCollectionChangedAction.Remove:
 33                    return new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, args.OldItems.ToAr
 34                case NotifyCollectionChangedAction.Replace:
 35                    return new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, args.NewItems.ToA
 36                        args.NewIndex);
 37                case NotifyCollectionChangedAction.Reset:
 38                    return new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
 39            }
 40
 41            throw new NotSupportedException($"Can't create NotifyCollectionChangedEventArgs from this action ({args.Acti
 42        }
 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
 54        {
 55            return TryGetValue(args.NewItems.Span, key, out value);
 56        }
 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
 68        {
 69            return TryGetValue(args.OldItems.Span, key, out value);
 70        }
 71
 72        private static bool TryGetValue<TKey, TValue>(ReadOnlySpan<KeyValuePair<TKey, TValue>> items, TKey key, out TVal
 73        {
 74            if (items.Length == 0)
 75            {
 76                value = default;
 77                return false;
 78            }
 79
 80            EqualityComparer<TKey> equalityComparer = EqualityComparer<TKey>.Default;
 81
 82            for (int i = 0; i < items.Length; i++)
 83            {
 84                if (equalityComparer.Equals(items[i].Key, key))
 85                {
 86                    value = items[i].Value;
 87                    return true;
 88                }
 89            }
 90
 91            value = default;
 92            return false;
 93        }
 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>
 1452106        public NotifyCollectionChangedAction Action { get; }
 107        /// <summary>
 108        ///     Gets the index at which the new item was added.
 109        /// </summary>
 744110        public int NewIndex { get; }
 111        /// <summary>
 112        ///     Gets the index at which the old item was removed.
 113        /// </summary>
 450114        public int OldIndex { get; }
 115        /// <summary>
 116        ///     Gets the items that were added.
 117        /// </summary>
 36942118        public ReadOnlyMemory<T> OldItems { get; }
 119        /// <summary>
 120        ///     Gets the items that were removed.
 121        /// </summary>
 36894122        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)
 10590129        {
 10590130            Action = action;
 10590131            NewIndex = newIndex;
 10590132            OldIndex = oldIndex;
 10590133            OldItems = oldItems;
 10590134            NewItems = newItems;
 10590135        }
 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)
 6192144        {
 6192145            using (IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(1))
 6192146            {
 6192147                Memory<T> memory = owner.Memory.Slice(0, 1);
 6192148                memory.Span[0] = newItem;
 6192149                return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Add, startingIndex, memory);
 150            }
 6192151        }
 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)
 1338160        {
 1338161            using (IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(newItems.Length))
 1338162            {
 1338163                Memory<T> memory = owner.Memory.Slice(0, newItems.Length);
 1338164                newItems.CopyTo(memory.Span);
 1338165                return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Add, startingIndex, memory);
 166            }
 1338167        }
 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)
 210176        {
 210177            using (IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(1))
 210178            {
 210179                Memory<T> memory = owner.Memory.Slice(0, 1);
 210180                memory.Span[0] = oldItem;
 210181                return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Remove, oldIndex: removedIndex, oldIte
 182            }
 210183        }
 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)
 84193        {
 84194            using (IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(oldItems.Length))
 84195            {
 84196                Memory<T> memory = owner.Memory.Slice(0, oldItems.Length);
 84197                oldItems.CopyTo(memory.Span);
 84198                return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Remove, oldIndex: removedIndex, oldIte
 199            }
 84200        }
 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)
 150211        {
 150212            using (IMemoryOwner<T> oldOwner = MemoryPool<T>.Shared.Rent(1))
 150213            {
 150214                Memory<T> oldMemory = oldOwner.Memory.Slice(0, 1);
 150215                oldMemory.Span[0] = oldItem;
 216
 150217                using (IMemoryOwner<T> newOwner = MemoryPool<T>.Shared.Rent(1))
 150218                {
 150219                    Memory<T> newMemory = newOwner.Memory.Slice(0, 1);
 150220                    newMemory.Span[0] = newItem;
 150221                    return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Replace, index, newMemory, index, 
 222                }
 223            }
 150224        }
 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
 222235        {
 222236            using IMemoryOwner<T> oldOwner = MemoryPool<T>.Shared.Rent(oldItems.Length);
 222237            Memory<T> oldMemory = oldOwner.Memory.Slice(0, oldItems.Length);
 222238            oldItems.CopyTo(oldMemory.Span);
 239
 222240            using IMemoryOwner<T> newOwner = MemoryPool<T>.Shared.Rent(newItems.Length);
 222241            Memory<T> newMemory = newOwner.Memory.Slice(0, newItems.Length);
 222242            newItems.CopyTo(newMemory.Span);
 243
 222244            return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Replace, startingIndex, newMemory, startin
 222245        }
 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)
 2388255        {
 2388256            using IMemoryOwner<T> owner = MemoryPool<T>.Shared.Rent(items.Length);
 2388257            Memory<T> memory = owner.Memory.Slice(0, items.Length);
 2388258            items.CopyTo(memory.Span);
 259
 2388260            return new CollectionChangedArgs<T>(NotifyCollectionChangedAction.Reset, newIndex, oldIndex: oldIndex, oldIt
 2388261        }
 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)
 396269        {
 396270            return Action == other.Action && NewIndex == other.NewIndex && OldIndex == other.OldIndex && OldItems.Equals
 271                   NewItems.Equals(other.NewItems);
 396272        }
 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)
 0283        {
 0284            return obj is CollectionChangedArgs<T> other && Equals(other);
 0285        }
 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()
 0292        {
 293            unchecked
 0294            {
 0295                int hashCode = (int) Action;
 0296                hashCode = (hashCode * 397) ^ NewIndex;
 0297                hashCode = (hashCode * 397) ^ OldIndex;
 0298                hashCode = (hashCode * 397) ^ OldItems.GetHashCode();
 0299                hashCode = (hashCode * 397) ^ NewItems.GetHashCode();
 0300                return hashCode;
 301            }
 0302        }
 303
 304        public static bool operator ==(CollectionChangedArgs<T> left, CollectionChangedArgs<T> right)
 396305        {
 396306            return left.Equals(right);
 396307        }
 308
 309        public static bool operator !=(CollectionChangedArgs<T> left, CollectionChangedArgs<T> right)
 0310        {
 0311            return !left.Equals(right);
 0312        }
 313    }
 314}